BaseServlet抽取

平常我们写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方法底层的优化机制。

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值