# 优化 Servlet

减少 Servlet 的数量,现在是一个功能一个 Servlet, 将其优化为一个模块一个 Servlet, 相当于在数据库中一张表对应一个 Servlet, 在 Servlet 中提供不同的方法,完成用户的请求

image_2023-01-22-14-22-05

将所有相关的操作写到一个类中来减少代码的冗余度,比如一个模块如:用户登录,用户查询是一个模块,而商品查询,旅游景点则是另一个模块

  • Servlet 继承自 HttpServlet 而 HttpServlet 根据请求方式不同完成 doPost 或 doGet 的分发

代码案例:

  1. 创建一个 BaseServlet 类,类中定义一个 service 方法
@SuppressWarnings("all")
public class BaseServlet extends HttpServlet {
    protected void service(HttpServletRequest req,HttpServletResponse resp){
//        System.out.println ("baseServlet 的 service 方法被执行了!");
//        完成方法分发
//        1. 获取请求路径
        String uri = req.getRequestURI();///dkx/user/add : 截取字符串最后一个 / 就可以拿到 add 了
//        2. 获取方法名称
        String add = uri.substring(uri.lastIndexOf("/")+1);// 截取包头不含尾,lastIndexOf+1 来去掉 /
//        3. 获取方法对象 method
        /*
        this: 谁调用我,我就代表谁,而这个 service 又是被 UserServlet 调用的所以 this 代表的是 UserServlet 对象
         */
        try{
            Method method = this.getClass().getMethod(add,HttpServletRequest.class,HttpServletResponse.class);
//        4. 执行方法
            method.invoke(this,req,resp);
        }catch(Exception e){
            e.printStackTrace();
            
        }
    }
}
  1. 创建 UserServlet 类而让该类继承 BaseServlet 类,该类虚拟目录为 user/*
@WebServlet("/user/*")
public class UserServlet extends BaseServlet {
    public void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        p("UerServlet的add方法");
    }
    public void find(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        p("UerServlet的find方法");
    }
}

UserServlet 继承了 BaseServlet 当我们访问 UserServlet 的方法时就会调用 BaseServlet 中的 service 方法,我们可以创建多个模块来进行管理

  1. 创建 CategoryServlet 类,让该类也继承 BaseServlet
@WebServlet("/category/*")
public class CategoryServlet extends BaseServlet {
    public void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        p("CategoryServlet的find方法");
    }
    public void find(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        p("CategoryServlet的find方法");
    }
}
  • 当访问虚拟目录 /category/* 时调用的是 CategoryServlet 的方法对象

添加一些使用频繁的操作比如: json序列化

/**
 * 直接将传入对象序列化为 json, 并且写回客户端
 * @param obj
 */
public void writeValue(Object obj,HttpServletResponse response) throws IOException {
    try{
        ObjectMapper mapper = new ObjectMapper();
        response.setContentType("application/json;charset=utf-8");
        mapper.writeValue(response.getOutputStream(),obj);
    }catch(Exception e){
        e.printStackTrace();
        p(e);//* 无限递归,已经解决
    }
}
/**
 * 将传入的对象序列化为 json, 返回
 * @param obj
 */
public String writeAsString(Object obj) throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();
    return mapper.writeValueAsString(obj);
}

调用方法类

public void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //1. 获取用户名和密码数据
    Map<String, String[]> map = request.getParameterMap();
    //2. 封装 User 对象
    User user = new User();
    try {
        BeanUtils.populate(user,map);
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
    //3. 调用 Service 查询
    User u  = service.login(user);
    ResultInfo info = new ResultInfo();
    //4. 判断用户对象是否为 null
    if(u == null){
        // 用户名密码或错误
        info.setFlag(false);
        info.setErrorMsg("用户名密码或错误");
    }
    //5. 判断用户是否激活
    if(u != null && !"Y".equals(u.getStatus())){
        // 用户尚未激活
        info.setFlag(false);
        info.setErrorMsg("您尚未激活,请激活");
    }
    //6. 判断登录成功
    if(u != null && "Y".equals(u.getStatus())){
        request.getSession().setAttribute("user",u);// 登录成功标记
        // 登录成功
        info.setFlag(true);
    }
    // 响应数据
    writeValue(info,response);
}