项目中公用Servlet代码写到BaseServlet类中让其它的Servlet继承从而优化代码

项目中公用Servlet代码写到BaseServlet类中让其它的Servlet继承从而优化代码

  • 思路:

  |--Servlet的运行顺序:

    |--1、当请求第一次访问某个Servlet时,由Servlet引擎去初始化该Servlet并创建该Servlet的对象。

    |--2、Servlet对象调用service()方法处理具体的请求,若没有重写service()方法,由自动调用相应的doGet()或doPost()方法。

    |--3、Servlet在doGet()或doPost()方法中调用相应的业务方法完成请求,并跳转(转发或是重定向)。

  1. 一个项目中会有多个Servlet,每个Servlet都要继承HttpServlet,并且都要重写相应的doGet(),doPost(),和相应的跳转代码,还有要写创建相应业务类对象的代码,相当冗余。
  2. 如果把这些公用的代码(包括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 }
BaseServlet的代码实现
  • 处理方法
  1. 在Servlet引擎初始化完Servlet并创建Servelt对象后就转去执行service()方法,由于子类中没有相应的方法了,所以就去父类中找,最后在BaseServlet中执行doGet()或doPost(),然后利用反射技术得到其子类Servlet中的方法,根据子类方法的返回值做相应的跳转工作。
  2. 由于在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 }
继承了BaseServlet的类
  • 跳转方法的统一处理:
 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 }
跳转方法的统一处理

 

posted @ 2015-12-31 23:35  心灵召唤  阅读(866)  评论(0)    收藏  举报