项目中公用Servlet代码写到BaseServlet类中让其它的Servlet继承从而优化代码
项目中公用Servlet代码写到BaseServlet类中让其它的Servlet继承从而优化代码
- 思路:
|--Servlet的运行顺序:
|--1、当请求第一次访问某个Servlet时,由Servlet引擎去初始化该Servlet并创建该Servlet的对象。
|--2、Servlet对象调用service()方法处理具体的请求,若没有重写service()方法,由自动调用相应的doGet()或doPost()方法。
|--3、Servlet在doGet()或doPost()方法中调用相应的业务方法完成请求,并跳转(转发或是重定向)。
- 一个项目中会有多个Servlet,每个Servlet都要继承HttpServlet,并且都要重写相应的doGet(),doPost(),和相应的跳转代码,还有要写创建相应业务类对象的代码,相当冗余。
- 如果把这些公用的代码(包括doGet(),doPost(),跳转代码和业务类对象的创建代码)写到一个抽象的BaseServlet类中,让该类继承HttpServlet,其它的Servlet类不再继承HttpServlet,而是去继承BaseServlet,这样,子类的Servlet中将不再有以上的冗余代码。
具体实现见以下代码:
1 package com.servlet; 2 3 import java.io.IOException; 4 import java.lang.reflect.Method; 5 6 import javax.servlet.ServletException; 7 import javax.servlet.http.HttpServlet; 8 import javax.servlet.http.HttpServletRequest; 9 import javax.servlet.http.HttpServletResponse; 10 11 import cn.itcast.factory.BeanFactory; 12 import cn.itcast.service.IDinnerTableService; 13 import cn.itcast.service.IFoodService; 14 import cn.itcast.service.IFoodTypeService; 15 import cn.itcast.utils.WebUtils; 16 17 /** 18 * 项目中通用的Servlet,希望所有的servlet都继承此类 19 */ 20 public abstract class BaseServlet extends HttpServlet { 21 22 // 通过工厂创建所有的Service层对象,由于子类要用,所以用protected修饰符: 23 protected IDinnerTableService dinnerTableService = 24 BeanFactory.getInstance("dinnerTableService", IDinnerTableService.class); 25 protected IFoodTypeService foodTypeService = 26 BeanFactory.getInstance("foodTypeService",IFoodTypeService.class); 27 protected IFoodService foodService = 28 BeanFactory.getInstance("foodService",IFoodService.class); 29 30 @Override 31 protected void doGet(HttpServletRequest request, HttpServletResponse response) 32 throws ServletException, IOException { 33 // (保存跳转的资源) returnValue是调用子类Servlet方法后的方法返回值: 34 Object returnValue = null; 35 36 // 获取操作类型(客户端访问页面时,页面会传过来一个method参数给Servlet,代表返回什么页面给客户端); 【约定 > 俗成: 操作类型的值,必须对应servlet中的方法名称】 37 String methodName = request.getParameter("method"); // listTable 38 39 try { 40 // 1. 利用反射获取当前运行类的字节码(this代表当前运行类的对象,在这里,是子类Servlet的对象,因为Servlet引擎初始化的是子类的对象,然后调用的doGet方法是在BaseServlet中,所以当前的this指具体的引擎初始化的对象: 41 42 Class clazz = this.getClass(); 43 // 2. 获取当前执行的方法的Method类型 44 Method method = clazz.getDeclaredMethod(methodName, HttpServletRequest.class,HttpServletResponse.class); 45 // 3. 执行方法(执行方法,代码跳回到到具体的子类Servlet中去执行,下面这个代码是指,方法执行完成后会有返回值保存到returnValue中,然后根据这个值做相应的跳转 46 returnValue = method.invoke(this, request,response); 47 } catch (Exception e) { 48 e.printStackTrace(); 49 returnValue = "/error/error.jsp"; 50 } 51 52 // 跳转(跳转的公用代码写在了WebUtils.goTo()方法中,优化了代码): 53 WebUtils.goTo(request, response, returnValue); 54 } 55 56 @Override 57 protected void doPost(HttpServletRequest req, HttpServletResponse resp) 58 throws ServletException, IOException { 59 this.doGet(req, resp); 60 } 61 }
- 处理方法
- 在Servlet引擎初始化完Servlet并创建Servelt对象后就转去执行service()方法,由于子类中没有相应的方法了,所以就去父类中找,最后在BaseServlet中执行doGet()或doPost(),然后利用反射技术得到其子类Servlet中的方法,根据子类方法的返回值做相应的跳转工作。
- 由于在BaseServlet中将业务逻辑层的对象创建好了,子类的Servelet对象都拥有一份,故不用再去每个子类的Servlet中再写创建Service层的对象代码,具体实现见以下代码:
1 ackage com.servlet; 2 3 import java.io.IOException; 4 import java.util.List; 5 6 import javax.servlet.ServletException; 7 import javax.servlet.http.HttpServlet; 8 import javax.servlet.http.HttpServletRequest; 9 import javax.servlet.http.HttpServletResponse; 10 11 import cn.itcast.entity.FoodType; 12 import cn.itcast.factory.BeanFactory; 13 import cn.itcast.service.IFoodTypeService; 14 import cn.itcast.utils.WebUtils; 15 16 /** 17 * 菜系管理Servlet开发 18 Tomcat 初始化完这个Servlet后,在执行doGet()时跳转到了BaseServlet中。 19 * 20 * a. 添加菜系 b. 菜系列表展示 c. 进入更新页面 d. 删除 e. 更新 21 */ 22 public class FoodTypeServlet extends BaseServlet { 23 // a. 添加菜系 24 public Object addFoodType(HttpServletRequest request, 25 HttpServletResponse response) throws ServletException, IOException { 26 Object uri = null; 27 // 1. 获取请求数据封装 28 String foodTypeName = request.getParameter("foodTypeName"); 29 FoodType ft = new FoodType(); 30 ft.setTypeName(foodTypeName); 31 32 // 2. 调用service处理业务逻辑 33 foodTypeService.save(ft); 34 35 // 3. 跳转 36 uri = request.getRequestDispatcher("/foodType?method=list"); 37 38 return uri; 39 40 } 41 }
- 跳转方法的统一处理:
1 package com.utils; 2 3 import java.io.IOException; 4 5 import javax.servlet.RequestDispatcher; 6 import javax.servlet.ServletException; 7 import javax.servlet.http.HttpServletRequest; 8 import javax.servlet.http.HttpServletResponse; 9 10 public class WebUtils { 11 12 /** 13 * 跳转的通用方法:根据传过来的rui类型做相应的跳转,若uri类型是xxDespatcher对象就执行跳转,如果uri类型是一个字符串,就执行response.sendRedirect(uri);方法 14 */ 15 public static void goTo(HttpServletRequest request, HttpServletResponse response, Object uri) 16 throws ServletException, IOException { 17 if (uri instanceof RequestDispatcher){ 18 ((RequestDispatcher)uri).forward(request, response); 19 } else if (uri instanceof String) { 20 response.sendRedirect(request.getContextPath() + uri); 21 } 22 } 23 }

浙公网安备 33010602011771号