基于反射抽取父类Servlet实现请求处理
基于反射抽取父类Servlet实现请求处理
学习于:https://www.bilibili.com/video/BV1Dh41197mE?share_source=copy_web
背景:
由于在web项目中,Servlet会对于前端传过来的请求携带的method参数(有可能叫其他名字),进行if...else if ...的判断,实现Servlet复用,但是如果每个模块的Servlet都先获得参数,再多轮判断,就会产生很多冗余的代码,于是想到提取出一个父类,来简化代码。至此,我们再创建新的Servlet模块的时候,只需要继承这个父类,然后实现对应的方法就可以完整请求的处理。
分析:
- Servlet层的共同点:
- 都会获取前端请求来的路径中的参数,以判断请求方法名;
- 在处理完请求之后,都会进行相应的后续处理,可以大致分为4种:
- 1、请求转发----forward;
- 2、重定向----redirect;
- 3、向页面输出内容----write/print;(例如与ajax进行交互)
- 4、没有任何的处理,这种情形下,可以默认重新回到首页;
分析得到这些控制层的共同点之后,就可以根据这些共同点,抽取出方法,由于具体的很多参数都是在实例化的具体Servlet类中才能够得知要调用什么方法,所以利用反射机制,动态的获取处理方法!
父类代码实例:BaseController
package com.wxy.servlet; import javax.servlet.ServletException; 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; import com.wxy.util.Constants; /** * @Description: 基于反射实现的父类Servlet,动态的执行子类的处理方法; */ public class BaseController extends HttpServlet { /** * 子类中,只需要重写doGet/doPost 方法,不重写service方法,所以子类会自动调用父类的方法,也就是下面的方法; * * @param req * @param resp * @throws ServletException * @throws IOException * @Description: 内容详细介绍; * 1、获取方法名:前端提交的url请求中携带着关于请求处理的参数,例如---> url: "/user?method=check..."; * 2、判断方法名:此时无法得知具体的 method 等于什么,所以对method进行判断; * 3、通过反射机制获得当前类的字节码; * 4、获得方法对象,执行方法,invoke(执行对象,传入参数) 执行对象:this --->就是当前调用的子类; * 5、统一规定方法返回一个String类型的result;供判断处理后的输出或跳转方法; * 6、根据方法的返回值,分别处理:请求转发、重定向、向页面输出内容 3种响应方式; * 7、在catch异常的时候,向页面携带一个信息,告诉客户出错了,并且让网页自动跳转会首页; * 8、在此类中,另外专门写一个index() 方法,专门处理前端传递过来的没有携带method参数的请求; */ @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //req.setCharacterEncoding("utf-8"); //获取一个方法名,method="check/login/register.....(req,resp) String methodName = req.getParameter(Constants.TAG);// 常量类中定义:Constants.TAG="method" //此时无法得知具体的 method 等于什么,所以对method进行判断 if (methodName == null && "".equals(methodName)) { //若前端没有传回method参数,默认前往index页面, methodName = Constants.INDEX; // Constants.INDEX="index" } try { //获得当前类的字节码 Class<? extends BaseController> clazz = this.getClass(); //check(req,resp) Method method = clazz.getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class); //result=this.check(req,resp) Object result = method.invoke(this, req, resp); if (result != null) { //返回值:要么带"forward:xxxx",或者"redirect:xxxx",要么是其他 String str = (String) result; //请求转发的请求地址 String path = str.substring(str.indexOf(Constants.FLAG) + 1); // Constants.FLAG=":" if (str.startsWith(Constants.FOWARD)) { req.getRequestDispatcher(path).forward(req, resp); } else if (str.startsWith(Constants.REDIRECT)) { resp.sendRedirect(path); } else { //若不请求也不转发,就向页面输出返回值str resp.getWriter().print(str); } } } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { e.printStackTrace(); //加入出现异常,就传回一个msg值 req.setAttribute("msg", "网络异常,请检查自己的网络"); req.getRequestDispatcher("/message.jsp").forward(req, resp); } } /* * 跳转到首页 * 为默认情况设置方法,如果method=index 就走当前类的这个方法 */ public String index(HttpServletRequest req, HttpServletResponse resp) { return Constants.FOWARD + "/index.jsp"; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!