# 优化 Servlet
减少 Servlet 的数量,现在是一个功能一个 Servlet, 将其优化为一个模块一个 Servlet, 相当于在数据库中一张表对应一个 Servlet, 在 Servlet 中提供不同的方法,完成用户的请求
将所有相关的操作写到一个类中来减少代码的冗余度,比如一个模块如:用户登录,用户查询是一个模块,而商品查询,旅游景点则是另一个模块
- Servlet 继承自 HttpServlet 而 HttpServlet 根据请求方式不同完成 doPost 或 doGet 的分发
代码案例:
- 创建一个
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(); | |
} | |
} | |
} |
- 创建
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 方法,我们可以创建多个模块来进行管理
- 创建
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); | |
} |