servlet抽取三:依然是基于注解的方式,利用监听器进行优化
前言
上一篇博客servlet抽取二:基于注解的方式实现的程序还有许多的优化空间,需要改进,首先每次调用都需要扫描类和方法,需要新建了一个对象,而这些过程是重复的,所以这篇博客是基于上次的程序进行改进,在Tomcat启动的时候,就进行控制器的扫描,并存储,然后提高效率
当Tomcat启动或终止时,ServletContextListener ,会对这两个事件进行处理
思想
当Tomcat启动的时候,扫描类和方法,将映射与对象和方法存储到map中,当得到请求的时候,通过map来获取对象和方法进行调用
代码
- MyControllerLoaderListener ——Tomcat启动加载contextInitialized函数
@WebListener
public class MyControllerLoaderListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
MyApplicaitonContext.initController();
}
}
- MyApplicaitonContext ——加载Controller,放到map中
public class MyApplicaitonContext {
public static final Map<String, ControllerAndMethod> map = new HashMap<>();
public static void initController(){
List<Class<?>> classsFromPackage = ClassScanner.getClasssFromPackage("com.kehao.controller");
classsFromPackage.stream().filter(clz-> clz.isAnnotationPresent(MyCompoent.class)).forEach(
(clz)->{
try {
Object controller = clz.newInstance();
Arrays.stream(clz.getDeclaredMethods()).
filter(method -> method.isAnnotationPresent(MyRequestMapping.class)).
forEach(method -> {
map.put(method.getAnnotation(MyRequestMapping.class).value(), new ControllerAndMethod(controller,method));
}
);
}catch (Exception e) {
e.printStackTrace();
}
}
);
}
}
- ControllerAndMethod ——用于存储方法和对象
public class ControllerAndMethod {
private Object controller;
private Method method;
public ControllerAndMethod(Object controller, Method method) {
this.controller = controller;
this.method = method;
}
public Object getController() {
return controller;
}
public Method getMethod() {
return method;
}
}
@WebServlet("*.do")
public class DispatherServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
String requestURI = req.getRequestURI();
String contextPath = req.getContextPath();
String mappingPath = requestURI.substring(contextPath.length(),requestURI.length());
ControllerAndMethod controllerAndMethod = MyApplicaitonContext.map.get(mappingPath);
try {
if(controllerAndMethod!=null){
controllerAndMethod.getMethod().invoke(controllerAndMethod.getController(),req,resp);
}else {
throw new ServletException("no such mapping found! "+mappingPath);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
- HelloController ——实际的控制层
@MyCompoent
public class HelloController {
@MyRequestMapping("/hello.do")
public void hello(HttpServletRequest req, HttpServletResponse resp) throws Exception {
resp.getWriter().println("hello,i'm in HelloController!!!");
}
}
- 注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyRequestMapping {
String value();
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyCompoent {
}

浙公网安备 33010602011771号