应用场景: 如果一个servlet对应一个功能,那么我们 要做一个 学生 的 增删改查 需要写 5 个 servlet来处理。可能只有几个功能却要写 几十个servlet。非常麻烦。
1、冗余servlet合并思路
- 我们在前端请求的路径中加上想要请求的方法。例如:
"/testServlet?method=addStu"
- 我们在后台根据 传递过来的 method 来寻找对应的处理逻辑
- method 传递过来的参数不同,我们处理逻辑也不同
示例
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class BaseServlet extends javax.servlet.http.HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取客户端提交到服务端的method对应的值
String md=request.getParameter("method");
//定义变量,存放功能执行完毕之后要转发的路径
String path=null;
//通过判断md中不同的内容来决定本次功能
if("addStu".equals(md)){
path=addStu(request, response);
}else if("delStu".equals(md)){
path=delStu(request, response);
}else if("checkStu".equals(md)){
path=checkStu(request, response);
}else if("".equals(md)){
}
if(null!=path){
//服务端的转发
request.getRequestDispatcher(path).forward(request, response);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
public String addStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("添加学生");
return "/test.html";
}
public String delStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("删除学生");
return "/test.html";
}
public String checkStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("检查学生");
response.getWriter().println("DDDDDD");
return null;
}
}
这样我们就在一个servlet中处理了 增加 删除 和 检查学生的逻辑
2、问题及改善(利用反射)
如果学生模块的方法特别多,有几十个,那么我们要写 几十个 if else 条件判断,代码重复,并且比较繁琐
解决思路
- 获取前台传递的参数,得知要调用的方法
- 利用反射获取该servlet类的对象
- 检查该对象有没有这个方法
- 有的话就调用,没有的话不调用
代码示例
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
public class BaseServlet extends javax.servlet.http.HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取客户端提交到服务端的method对应的值
String md=request.getParameter("method");
//定义变量,存放功能执行完毕之后要转发的路径
String path=null;
//通过判断md中不同的内容来决定本次功能
/* if("addStu".equals(md)){
path=addStu(request, response);
}else if("delStu".equals(md)){
path=delStu(request, response);
}else if("checkStu".equals(md)){
path=checkStu(request, response);
}else if("".equals(md)){
}*/
// 当前类的字节码对象(当前类在内存中的对象)
Class clazz = this.getClass();
// 获取clazz上的名称为 md 方法
try {
Method method = clazz.getMethod(md, HttpServletRequest.class, HttpServletResponse.class);
if(null != method){
path = (String)method.invoke(this, request, response);
}
if(null!=path){
//服务端的转发
request.getRequestDispatcher(path).forward(request, response);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
public String addStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("添加学生");
return "/test.html";
}
public String delStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("删除学生");
return "/test.html";
}
public String checkStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("检查学生");
response.getWriter().println("DDDDDD");
return null;
}
}
代码说明:
判断的逻辑
//通过判断md中不同的内容来决定本次功能
if("addStu".equals(md)){
path=addStu(request, response);
}else if("delStu".equals(md)){
path=delStu(request, response);
}else if("checkStu".equals(md)){
path=checkStu(request, response);
}else if("".equals(md)){
}
if(null!=path){
//服务端的转发
request.getRequestDispatcher(path).forward(request, response);
}
用简洁的反射代码替代
// 当前类的字节码对象(当前类在内存中的对象)
Class clazz = this.getClass();
// 获取clazz上的名称为 md 方法
try {
Method method = clazz.getMethod(md, HttpServletRequest.class, HttpServletResponse.class);
if(null != method){
path = (String)method.invoke(this, request, response);
}
if(null!=path){
//服务端的转发
request.getRequestDispatcher(path).forward(request, response);
}
} catch (Exception e) {
e.printStackTrace();
}
3、多模块冗余优化
利用反射,我们可以应对某个servlet有很多方法的情况。但是如果我们有很多功能模块,几十个,几百个。那么我们的每一个servlet中都有如下这段代码。造成了代码冗余。
//定义变量,存放功能执行完毕之后要转发的路径
String path=null;
// 当前类的字节码对象(当前类在内存中的对象)
Class clazz = this.getClass();
// 获取clazz上的名称为 md 方法
try {
Method method = clazz.getMethod(md, HttpServletRequest.class, HttpServletResponse.class);
if(null != method){
String invoke = (String)method.invoke(this, request, response);
}
if(null!=path){
//服务端的转发
request.getRequestDispatcher(path).forward(request, response);
}
} catch (Exception e) {
e.printStackTrace();
}
解决思路
- 利用servlet的生命周期,我们把这段代码提取出来
- servlet的生命周期为: init() service() destory()
- 我们封装一个 父类 BaseServlet,在这个类中重写 service方法
- 在service中把上面代码放进去
- 并让以后所有的servlet类 继承该类即可
代码示例
BaseServlet.java (父类)
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
public class BaseServlet extends javax.servlet.http.HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String md=request.getParameter("method");
//定义变量,存放功能执行完毕之后要转发的路径
String path=null;
// 当前类的字节码对象(当前类在内存中的对象)
Class clazz = this.getClass();
// 获取clazz上的名称为 md 方法
try {
Method method = clazz.getMethod(md, HttpServletRequest.class, HttpServletResponse.class);
if(null != method){
String invoke = (String)method.invoke(this, request, response);
}
if(null!=path){
//服务端的转发
request.getRequestDispatcher(path).forward(request, response);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
TestServlet.java (测试子类)
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
public class TestServlet extends BaseServlet{
public String addStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("添加学生");
return "/test.html";
}
public String delStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("删除学生");
return "/test.html";
}
public String checkStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("检查学生");
response.getWriter().println("DDDDDD");
return null;
}
}
这样就把学生模块的功能分离出来了,以后每增加一个 功能模块 只需要 增加一个servlet 并继承 父类 BaseServlet即可。
欢迎留言讨论你的想法