【抽取servlet共性】实现高内聚提高开发效率

【抽取servlet共性】实现高内聚提高开发效率

平常我们写Servlet时总是一个功能一个Servlet,然后发现自己写的Servlet文件一大堆。
就比如登录,注册,退出,验证等等。

但是我们仔细分析登录,注册,退出,验证等等好像都是和用户有关的。那么我们能不能将与用户有关的写一个Servlet,与货物有关的写一个Servet呢?

再仔细想,平常我们写Java项目时总是采用三层架构模式,那么能不能有一种方法将我们写的所有Servlet也像Service层或者Dao层一样,写一个模块的Servlet,这个Servlet里包含这个模块相应的方法,通过调用这个模块的方法来实现不同功能呢?

回想一下,我们现在编写的Servlet方法,都是extends自HttpServlet,HttpServlet又extends自GenericServlet,在GenericServlet中实现了Servlet这个接口,而Servlet接口中定义了Servlet的规范,Tomcat在运行的时候,要去执行Servlet中的service方法,而在HttpServlet中重写了service方法,通过判断你是get还是post或者其他请求,然后去调用相应的方法,实现了方法的分发。

现在我们不让编写的Servlet去继承HttpServlet,而是去继承我们自己编写的一个BaseServlet,让这个BaseServlet去继承HttpServlet,既然HttpServet中重写了service方法,实现了通过不同的请求来调用不同的方法,我们就从BaseServlet中重写service方法,通过判断来实现某个模块的所请求的方法。

那么根据请求来获取Servlet所要实现的功能,我们可以在请求路径上做些准备,比如用户需要注册的时候,我可以将对应请求路径设置为/user/regist。这样我们的请求路径上就出现了我们所需要的调用的方法名了。

紧接着又出现个问题,光有方法名我们怎么才能让UserSerlvet调用对应的方法呢?
仔细一想,通过方法名实现方法我们可以通过反射实现,通过反射我们可以获取类的方法并且可以实现对应的方法。

package cn.siyi.travel.web.servlet;

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.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class BaseServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取请求路径  例如:/user/regist
        String uri = req.getRequestURI();
        //获取方法名称 regist
        String methodName = uri.substring(uri.lastIndexOf('/') + 1);
        //获取方法对象Method
        try {
        	//当子类调用父类的service时,this代表子类对象 例如UserServlet
            Method method = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
            //实现对应方法
            method.invoke(this,req,resp);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

以下这段代码的共性:
根据不同的参数值调用不同的方法(约定前提:对应模块的Servlet类继承自BaseServlet,并且不能重写service方法)
用户访问的URI:

  • 用户注册: /user/regist
  • 用户登录:/user/login
  • 用户退出:/user/exit
  • 用户激活:/user/active
  • 用户查询:/user/findOne
package cn.siyi.travel.web.servlet;

import cn.siyi.travel.domain.ResultInfo;
import cn.siyi.travel.domain.User;
import cn.siyi.travel.service.UserService;
import cn.siyi.travel.service.impl.UserServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.beanutils.BeanUtils;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

@WebServlet("/user/*") //  /user/add /user/find
public class UserServlet extends BaseServlet {

    private UserService service = new UserServiceImpl();

    /**
     * 注册功能
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    protected void regist(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String check = request.getParameter("check");
        //从session中获取验证码
        HttpSession session = request.getSession();
        String checkcode_server = (String)session.getAttribute("CHECKCODE_SERVER");
        session.removeAttribute("CHECKCODE_SERVER");
        //比较
        if(checkcode_server==null || !checkcode_server.equalsIgnoreCase(check)){
            ResultInfo resultInfo = new ResultInfo();
            resultInfo.setFlag(false);
            resultInfo.setErrorMsg("验证码错误");
            ObjectMapper objectMapper = new ObjectMapper();
            String json = objectMapper.writeValueAsString(resultInfo);
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().write(json);
            return;
        }
        //获取数据
        Map<String, String[]> map = request.getParameterMap();
        //封装对象
        User user = new User();
        try {
            BeanUtils.populate(user,map);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        boolean flag = service.regist(user);
        ResultInfo resultInfo = new ResultInfo();
        if(flag){
            resultInfo.setFlag(true);
        }else{
            resultInfo.setFlag(false);
            resultInfo.setErrorMsg("注册失败!");
        }
        //将resultInfo对象序列化为json
        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writeValueAsString(resultInfo);
        //将json数据写回客户端
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(json);
    }

    /**
     * 登录功能
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //验证码验证
        String check = request.getParameter("check");
        HttpSession session = request.getSession();
        String checkcode_server = (String)session.getAttribute("CHECKCODE_SERVER");
        session.removeAttribute("CHECKCODE_SERVER");
        ResultInfo resultInfo = new ResultInfo();
        ObjectMapper objectMapper = new ObjectMapper();
        response.setContentType("application/json;charset=utf-8");
        if(checkcode_server==null || !checkcode_server.equalsIgnoreCase(check)){
            resultInfo.setFlag(false);
            resultInfo.setErrorMsg("验证码错误");
            objectMapper.writeValue(response.getOutputStream(),resultInfo);
            return;
        }
        //获取用户名和密码数据
        Map<String, String[]> map = request.getParameterMap();
        //封装User对象
        User user = new User();
        try {
            BeanUtils.populate(user,map);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        User u = service.login(user);
        //判断
        if(u == null){
            //用户名或密码错误
            resultInfo.setFlag(false);
            resultInfo.setErrorMsg("用户名或密码错误");;
        }else if(!"Y".equals(u.getStatus())){
            resultInfo.setFlag(false);
            resultInfo.setErrorMsg("您尚未激活,请激活");
        }else{
            request.getSession().setAttribute("user",u);
            resultInfo.setFlag(true);
        }
        objectMapper.writeValue(response.getOutputStream(),resultInfo);
    }

    /**
     * 查询单个对象
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    protected void findOne(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Object user = request.getSession().getAttribute("user");
        ObjectMapper objectMapper = new ObjectMapper();
        response.setContentType("application/json;charset=utf-8");
        objectMapper.writeValue(response.getOutputStream(),user);
    }

    /**
     * 退出功能
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    protected void exit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //销毁session
        request.getSession().invalidate();
        //跳转到登录页面
        response.sendRedirect(request.getContextPath()+"/login.html");
    }

    /**
     * 激活功能
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    protected void active(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取激活码
        String code = request.getParameter("code");
        if(code != null){
            boolean flag = service.active(code);
            String msg;
            if(flag){
                //激活成功
                msg = "激活成功,请<a href='login.html'>登录</a>";
            }else{
                //激活失败
                msg = "激活失败,请联系管理员";
            }
            response.setContentType("text/html;charset=utf-8");
            response.getWriter().write(msg);
        }
    }
}

这样我们就不用分别去写每个功能的Servlet了,只需要写一个对应方法即可,并且我们还可以共享一些数据,比如session。

虽然重写了service方法实现了方法的分发,但是service方法底层做了一些优化,如果我们直接就用几行简单的代码去重写了service方法,它底层一些优化好的机制我们就无法体验到。

所以,现在我们有另一种方案,我们还是让BaseServlet去继承HttpServlet,并分别去继承doGet与doPost方法,我们在doGet或者doPost里再去实现方法的分发,这样我们既抽取了servlet,也能体验到service方法底层的优化机制。

但是这样的话感觉代码量又增加了一点,看情况选择吧。

发布了476 篇原创文章 · 获赞 152 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/qq_41879343/article/details/104699407
今日推荐