Loading

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 {
}
posted @ 2021-03-31 19:28  克豪  阅读(58)  评论(0)    收藏  举报