目录
封装的必要性
封装是面向对象的方法应该遵循的一个重要原则!它的英文是encapsulation,有时也叫做数据隐藏。
从形式上看,封装不过是将数据和行为组合在一个包中,并对对象的使用者隐藏了数据的实现形式。
对象中的数据称为实例域(instance field),操纵数据的过程叫做方法(method)对于每个特定的类实例(也就是对象),都有一组特定的实例域值。这些值的集合就是这个对象的当前状态(state).无论何时,只要向对象发送一个消息,它的状态就有可能发生改变。
实现封装的关键在于绝对不能让类中的方法直接地访问其他类的实例域。程序仅通过对象的方法,与对象数据进行交互。封装给对象赋予了“黑盒”特征,这是提高重用性和可靠性的关键。这意味着一个类可以全面地改变存储数据的方式,只要仍旧使用同样的方法操作数据,其他对象就不会知道或介意所发生的变化。
举个例子,当你用表单传参时,如果参数过多,则你需要写许多不必要的代码
String user=request.getParameter("user");
String pwd=request.getParameter("pwd");
String sex=request.getParameter("sex");
String[] favours=request.getParameterValues("favours");
...
...
我们可以写一个公共类CommonServlet:
继承HttpServlet,以后你写的类只需要继承CommonServlet即可
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.Map;
public abstract class CommonServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
super.service(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
//若子类不重写doGet()方法,则总是调用doPost()方法
}
protected <T> T parseRequestToT(HttpServletRequest request, Class<T> cls){
T obj=null;
try {
obj =cls.newInstance(); //通过class字节码创建一个对象
}catch (Exception e){
e.printStackTrace();
}
Map<String,String[]> names=request.getParameterMap();//拿到所有的属性名
Method[] ms=cls.getMethods();//拿到所有的方法名
for (Method m:ms){
if (m.getName().startsWith("set")){
String fieldName=getFieldName(m);//如果以set开头,则取出后面的属性名
String[] values=request.getParameterValues(fieldName);
String v=null;
if (values!=null){
if (values.length>1){
StringBuffer sb=new StringBuffer();
for (String s:values){
sb.append(s+",");
}
v=sb.toString();
}else {
v=values[0];
}
}
if (v==null){
continue;
}
//判断这个方法的传参类型,进行转换
String methodTypeName=m.getParameterTypes()[0].getTypeName();
try {
if ("java.lang.Integer".equals(methodTypeName)){
Integer va=Integer.parseInt(v);
m.invoke(obj,va);
}else if ("java.lang.Double".equals(methodTypeName)){
Double va=Double.parseDouble(v);
m.invoke(obj,va);
}else if ("java.lang.Float".equals(methodTypeName)){
Float va=Float.parseFloat(v);
m.invoke(obj,va);
}else if ("java.lang.Long".equals(methodTypeName)){
Long va=Long.parseLong(v);
m.invoke(obj,va);
}else {
m.invoke(obj,v);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
return obj;
}
private String getFieldName(Method m) {
String fieldName=m.getName().substring("set".length());
//首字母小写
fieldName=fieldName.substring(0,1).toLowerCase()+fieldName.substring(1);
return fieldName;
}
}
parseRequestToT()方法可以将传过来的参数转成任意一个对象,只要传过来的参数名中有这个类的字段,就可赋值,比如这个类cust
public class cust {
private Long id;
private String user;
private String pwd;
private String sex;
private String favours;
private String comments;
private Integer age;
public Integer getAge() {
return age;
}
@Override
public String toString() {
return "cust{" +
"id=" + id +
", user='" + user + '\'' +
", pwd='" + pwd + '\'' +
", sex='" + sex + '\'' +
", favours='" + favours + '\'' +
", comments='" + comments + '\'' +
", age=" + age +
'}';
}
public void setAge(Integer age) {
this.age = age;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getFavours() {
return favours;
}
public void setFavours(String favours) {
this.favours = favours;
}
public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments;
}
}
这样我们可以根据这种类来写有关的Servlet,通常这种类都对应数据库中的一张表
例如利用custServlet类来操纵这张表,我们可以在这个servlet再封装,这样可以避免写大量
servlet导致你的项目中存在大量的servlet
import bea.cust;
import dao.DbHelper;
import utils.MD5;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
@WebServlet("/cust.action")
public class CustServlet extends CommonServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String op=request.getParameter("op");
Method[] methods=CustServlet.class.getDeclaredMethods();
for (Method m:methods){
if (m.getName().equals(op)){
try {
m.invoke(new CustServlet(),request,response);
return;
} catch (Exception e) {
e.printStackTrace();
}
}
}
response.setContentType("text/html;charset=utf-8");
PrintWriter out=response.getWriter();
out.println("请求失败");
out.flush();
}
protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");//unicode转成utf-8
String user=request.getParameter("user");
String pwd=request.getParameter("pwd");
DbHelper db=new DbHelper();
int sum=(int)db.Selectaggreation("select count(*) from users where user=? and pwd=?",user, MD5.MD5Encode(pwd,"utf-8"));
response.setContentType("text/html;charset=utf-8");
PrintWriter out=response.getWriter();
if (sum!=1){
out.println("用户名或密码错误");
}else
out.println("登录成功");
out.flush();
}
protected void regster(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
cust cust=super.parseRequestToT(request, cust.class);
//加密
cust.setPwd(MD5.MD5Encode(cust.getPwd(),"utf-8"));
DbHelper dbHelper=new DbHelper();
int a=dbHelper.insert("insert into users (user,pwd,sex,favours,comments,age) values (?,?,?,?,?,?)",cust.getUser(),cust.getPwd(),cust.getSex(),cust.getFavours(),cust.getComments(),cust.getAge());
System.out.println(a);
response.setContentType("text/html;charset=utf-8");
PrintWriter out=response.getWriter();
if (a>0){
out.println("注册成功,"+cust.getUser());
}else {
out.println("注册失败");
}
out.flush();
}
private void showAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
DbHelper db=new DbHelper();
List<cust>custs=db.select("select * from users",cust.class);
response.setContentType("text/html;charset=utf-8");
PrintWriter out=response.getWriter();
if (custs.size()<=0){
out.println("<h1>暂无注册用户</h1>");
return;
}
out.println("<ul>");
for (cust c:custs){
out.println("<li>"+c.toString()+"</li>");
}
out.println("</ul>");
}
在doPost()方法中,通过op这个参数来调用下面不同的方法