修改时间:2021年2月2日
作者:pp_x
邮箱:[email protected]
通用Servlet类
为什么要创建通用Servlet类
- 由于有些项目模块功能过多,如果一个功能一个Servlet类来进行实现的话,需要的Servlet类过多,会占用服务器资源,服务器运行的会相对较慢,所以我们可以设置一个通用的Servlet类来优化
创建Servlet的通用类
- 我们可以使一个模块对应一个Servlet类,前端请求的时候携带请求类型参数,Servlet类中用doget或者dopost进行接收来调用具体的实现方法
- index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%-- 一个模块对应一个Servlet --%>
<a href="${pageContext.request.contextPath}/test?methodName=addCourse">新建课程</a>
<a href="${pageContext.request.contextPath}/test?methodName=findByName">根据课程名查询</a>
<a href="${pageContext.request.contextPath}/test?methodName=findByStatus">根据状态查询</a>
</body>
</html>
- TestServlet类
/**
* 模拟课程模块 ,模块中有很多功能
* */
@WebServlet("/test")
public class TestServlet extends HttpServlet {
/**
* doGet()方法作为调度器 控制器,根据请求的功能不同,调用对应的方法
*
* */
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取参数
//获取要调用的方法名
String methodName = req.getParameter("methodName");
//2.业务处理
//判断 执行对应的方法
if("addCourse".equals(methodName)){
addCourse(req,resp);
}else if("findByStatus".equals(methodName)){
findByName(req,resp);
}else if("findByStatus".equals(methodName)){
findByStatus(req,resp);
}else{
System.out.println("访问的功能不存在!");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
/**
* 2.模块对应的功能部分
* */
public void addCourse(HttpServletRequest req, HttpServletResponse resp){
System.out.println("新建课程");
}
public void findByStatus(HttpServletRequest req, HttpServletResponse resp){
System.out.println("根据状态查询");
}
public void findByName(HttpServletRequest req, HttpServletResponse resp){
System.out.println("根据课程名称查询");
}
}
进一步优化Servlet类
- 判断请求类型来调用具体方法的部分代码可扩展性相对较差,如果方法过多,就需要更多的判断语句,所以我们使用反射的方式去对该部分代码进行优化
- 优化前
if("addCourse".equals(methodName)){
addCourse(req,resp);
}else if("findByStatus".equals(methodName)){
findByName(req,resp);
}else if("findByStatus".equals(methodName)){
findByStatus(req,resp);
}else{
System.out.println("访问的功能不存在!");
}
- 反射优化步骤:
- 先获取请求携带的请求类型参数
- 获取指定类的字节码对象
- 根据请求携带的方法参数值,在通过字节码对象(class)获取指定的方法
- 执行指定的方法
- 优化后
try {
//1.获取参数
//获取要调用的方法名
String methodName = req.getParameter("methodName");
//2.业务处理
if(methodName != null){
//通过反射优化代码,提升代码的可维护性
//1.获取字节码对象 this = TestServlet对象
Class c = this.getClass();
//2.根据传入的方法名, 获取对应方法对象,执行方法即可
Method method = c.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
//3.调用Method对象的 invoke()方法,执行对应的功能
method.invoke(this,req,resp);
}
} catch (Exception e) {
System.out.println("请求的功能不存在! !");
e.printStackTrace();
}
抽取相同代码再进行优化
- 虽然使用反射的方法来优化了判断类型部分的代码量,但是对于doPost和doGet部分,每一个模块的Servlet类都要进行重写,所以我们可以将doget和dopost方法重写后的代码进行提取,放入一个类中作为base类(此类继承HttpServlet类),后续的模块功能方法的Servlet类继承base类(相当于也是HttpServlet类的子类,也可以使用其方法)
- baseServlet类
public class BaseServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
//1.获取参数
//获取要调用的方法名
String methodName = req.getParameter("methodName");
//2.业务处理
if(methodName != null){
//通过反射优化代码,提升代码的可维护性
//1.获取字节码对象 this = TestServlet对象
Class c = this.getClass();//如果子类继承base类,那么反射的使具体的子类
//2.根据传入的方法名, 获取对应方法对象,执行方法即可
Method method = c.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
//3.调用Method对象的 invoke()方法,执行对应的功能
method.invoke(this,req,resp);
}
} catch (Exception e) {
System.out.println("请求的功能不存在! !");
e.printStackTrace();
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
- 进行提取后的TestServlet类
@WebServlet("/test")
public class TestServlet extends BaseServlet {
/**
* 在模块对应的Servlet中只保留 业务相关代码
* 当有请求访问到 TestServlet时, 发现没有doGet和doPost方法,就回去父类中找,从而执行BaseServlet中的
* doGet方法
* */
public void addCourse(HttpServletRequest req, HttpServletResponse resp){
System.out.println("新建课程");
}
public void findByStatus(HttpServletRequest req, HttpServletResponse resp){
System.out.println("根据状态查询");
}
public void findByName(HttpServletRequest req, HttpServletResponse resp){
System.out.println("根据课程名称查询");
}
}