BaseServlet基础类的实现+反射机制

一.BaseServlet类的实现

public class BaseServlet extends HttpServlet {
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        // 设置请求和响应的字符编码为UTF-8,确保中文等字符能正确处理
        req.setCharacterEncoding("UTF-8");
        res.setCharacterEncoding("UTF-8");
        
        // 从请求中获取名为"method"的参数,该参数用于指定要调用的方法名
        String method = req.getParameter("method");
        
        // 如果method参数不为空,则尝试动态调用对应的方法
        if(method != null) {
            try {
                // 通过反射获取当前类中名称为method,且参数为HttpServletRequest和HttpServletResponse的方法
                Method m = this.getClass().getMethod(method, HttpServletRequest.class, HttpServletResponse.class);
                
                // 调用找到的方法,传入当前Servlet实例和请求/响应对象
                m.invoke(this, req, res);
            } catch (Exception e) {
                // 捕获反射调用过程中可能出现的异常,并打印堆栈信息
                e.printStackTrace();
            }
        }
    }
}

倘若不使用这个基础类代码

@WebServlet("/categorytest")
public class CategoryTest extends HttpServlet {
    public CategoryService categoryService= new CategoryServiceImpl();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            req.setCharacterEncoding("UTF-8");
            resp.setCharacterEncoding("UTF-8");
            resp.setContentType("text/html;charset=UTF-8");
            String method=req.getParameter("method");
            switch (method) {
                case "list":
                    list(req,resp);
                    break;
                default:
                    System.out.println("没有此操作");
            }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
    public void list(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        List<Category>categories=categoryService.list();
        System.out.println(categories.toString());
    }
}
  • 就需要在每一个类都重写doGet和doPost方法,这样代码会比较复杂,但是写BaseServlet中有反射可能会影响性能,调试也不好调试

2.实现的过程:

  • BaseServlet是一个基础父类,各种子类继承它
  • 当客户端访问(/userServlet)的时候,会现在Servlet容器中找到对应的类,如果这个类重写了service就调用,如果没有重写,就调用父类的service一直往上找这是继承机制
  • 注意:如果子类没有重写service从而调用父类的,那么父类service中的this实际上指的还是子类实例对象,因为是子类创造了对应实例并且是这个实例去调用的
  • this只能指向对象实例,就像直接创建的类Usersrevlet,但是引用类型就是BaseServlet servlet=new UserServlet();

二.反射机制

  • 这里面两个主要的反射API:Class.getMethod(String name, Class<?>... parameterTypes) 获得指定名称和参数的public方法;Method.invoke(Object obj, Object... args): 调用指定对象上的方法
  • 反射查找的步骤:this.getClass返回当前的实例对象(比如Uservlet),getMothed("login", HttpServletRequest.class, HttpServletResponse.class)就是在UserServlet中找"login"方法,如果找到就返回对应的Mothed方法
  • 注意:service方法接收的是ServletRequest和ServletResponse类型的参数,但反射调用时要求的是HttpServletRequest和HttpServletResponse
  • m.invoke(this, req, res)就是用返回的m对象表示UserServlet对象,并且调用这个方法,实际上等价于this.register((HttpServletRequest)req, (HttpServletResponse)res);
    这里参数都被强行转换成HttpServletRequest
posted @ 2025-05-27 16:47  Huangyien  阅读(27)  评论(0)    收藏  举报