一.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