Jslfl【软件开发技术笔记】

自己写框架-MVC(二)

技术要点:
反射

改造计划:
1.自动封装formbean对象
2.业务处理代码从servlet中分离

代码结构:
img1-1

1、创建FormBeanUtil工具类,用来完成自动封装formbean的任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package cn.jslfl.mvc.core.form;

import java.lang.reflect.Field;
import javax.servlet.http.HttpServletRequest;

/**
 * 请求表单form对象封装工具类
 * @author jslfl
 */

public class FormBeanUtil {
    /**
     * @param req HttpServletRequest对象
     * @param formBeanName formBean类全名
     * @return formBean实例
     */

    public static Object packFormBean(HttpServletRequest req, String formBeanName){
        Object form = null;
        try {
            Class c = Class.forName(formBeanName);
            form = c.newInstance();
           
            Field[] fieldArr = c.getDeclaredFields();
            for(Field f : fieldArr){
                f.setAccessible(true);//设置private的属性可访问
                f.set(form, req.getParameter(f.getName()));
                f.setAccessible(false);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return form;
    }
}

注意:这儿用到反射来实例化类,并且newInstance()是通过类的无参构造方法进行实例化,所以如果类中没有定义无参构造方法的话,会出错。因此如果Form类中(LoginForm、RegForm)如果重载了参构造方法(带参),则必须也定义一个无参构造方法。

2、改造登录业务
新建LoginAction.java,把LoginServlet中的业务处理代码抽离到LoginAction的doService方法中
2.1、LoginAction.java代码清单:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package cn.jslfl.mvc.demo.action;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.jslfl.mvc.core.form.FormBeanUtil;
import cn.jslfl.mvc.demo.form.LoginForm;

public class LoginAction {
    public String doService(HttpServletRequest req, HttpServletResponse resp){
        LoginForm formBean = (LoginForm)FormBeanUtil.packFormBean(req, "cn.jslfl.mvc.demo.form.LoginForm");
       
        //业务处理开始...
        boolean flag = false;
        if("aa".equals(formBean.getUserName()) && "bb".equals(formBean.getPassWord())){
            flag = true;
        }
        //业务处理结束...
       
        String info = "<h1>登录" + (flag ? "成功" : "失败") + "!userName: " + formBean.getUserName()+ ", " + "password: " + formBean.getPassWord() + "</h1>";
       
        req.setAttribute("info", info);
       
        return "/web/userInfo.jsp";
    }
}

LoginAction处理流程:
a.从request中封装form表单对象
b.业务处理操作
c.request中设置返回数据
d.返回请求要跳转的路径

2.2、LoginServlet.java代码清单:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package cn.jslfl.mvc.demo.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.jslfl.mvc.demo.action.LoginAction;

public class LoginServlet extends HttpServlet{
    private static final long serialVersionUID = 1L;

    public void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.setCharacterEncoding("GBK");
       
        LoginAction action = new LoginAction();
        String returnPath = action.doService(req, resp);
       
        req.getRequestDispatcher(returnPath).forward(req, resp);
    }
   
    public void doGet(HttpServletRequest req, HttpServletResponse resp){
        try {
            doPost(req, resp);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

LoginServlet处理流程:
a.创建LoginAction对象,并调用其doService方法
b.跳转到指定(获取的doService返回值)路径

2.3、发布到tomcat测试
访问登录页面提交表单
img2-3-1
img2-3-2

3、改造注册业务
3.1、RegAction.java代码清单:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package cn.jslfl.mvc.demo.action;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.jslfl.mvc.core.form.FormBeanUtil;
import cn.jslfl.mvc.demo.form.RegForm;

public class RegAction {
    public String doService(HttpServletRequest req, HttpServletResponse resp){

        RegForm regBean = (RegForm)FormBeanUtil.packFormBean(req, "cn.jslfl.mvc.demo.form.RegForm");
       
        //业务处理开始...
        String msg = "";
        if(regBean.getUserName() == null || "".equals(regBean.getUserName().trim())
                ||regBean.getPassWord() == null || "".equals(regBean.getPassWord().trim())
                || regBean.getPassWord2() == null || "".equals(regBean.getPassWord2().trim())){
            msg = "数据不完整";
        }else if(!regBean.getPassWord().equals(regBean.getPassWord2())){
            msg = "两次密码不匹配";
        }else{
            msg = "成功";
        }
        //业务处理结束...
       
        String info = "<h1>注册" + msg + "!userName: " + regBean.getUserName() + ", " + "password: " + regBean.getPassWord() + ", " + "password2: " + regBean.getPassWord2() +"</h1>";
        req.setAttribute("info", info);
       
        return "/web/login.jsp";
    }
}

3.2、RegServlet.java代码清单:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package cn.jslfl.mvc.demo.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.jslfl.mvc.demo.action.RegAction;

public class RegServlet extends HttpServlet{
    private static final long serialVersionUID = 1L;

    public void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.setCharacterEncoding("GBK");
       
        RegAction action = new RegAction();
        String returnPath = action.doService(req, resp);
       
        req.getRequestDispatcher(returnPath).forward(req, resp);
    }
   
    public void doGet(HttpServletRequest req, HttpServletResponse resp){
        try {
            doPost(req, resp);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3.3、发布到tomcat测试
访问登录页面提交表单
img3-3-1
img3-3-2

本节中login.jsp、reg.jsp、userInfo.jsp、LoginForm.java、RegForm.java、web.xml未做修改,后台业务处理操作已转移到action中,servlet中代码已经很简单和单一,下一节将继续改造servlet。

Comments are currently closed.