从零构建轻量级Java Web框架 互动版

请求转发器

请求转发器是框架的核心。请求转发器转发器用来处理所有的请求。DispatherServlet继承HttpServlet,在init()方法调用Loader.init()来初始化框架和应用。service()方法响应所有的请求。

请求转发过程:

  • 1、通过req.getMethod().toLowerCase()获取请求方法(get,post,put delete);req.getContextPath()获取请求路径,根据请求路径和请求方法调用ControllerHelper.getHandler()方法获取处理这个请求对应的handler。

  • 2、Hanler封装处理请求的Controller和方法,所有获取的handler,就可以获取处理请求的Controller和方法method。

  • 3、获取了处理这个请求的Controller类,现在需要在Bean获取这个Controller类的实例对象,调用BeanContainer.getBean()来获取Controller类的实例对象。

  • 4、调用ParameterUtil.createParam(req)来解析请求参数。

  • 5、调用handler.getMethod()获取处理这个请求的方法,通过反射机制BeanFactory.invokeMethod()来调用这个方法,处理这个请求的方法就会来处理这个请求。

  • 6、根据返回的结果是ModelAndView还是Data来处理返回问题。返回结果为ModelAndView,调用req.getRequestDispatcher(ConfigHelper.getAppJspPath() + path).forward(req, resp)将页面响应转发到ConfigHelper.getAppJspPath() + path;返回结果为Data,将返回结果POJO转换为JSON格式,写入HttpServletRespone对象中,输出到客户端浏览器。

/**
 * 请求转发器
 */
@WebServlet(urlPatterns = "/",loadOnStartup = 0)
public class DispatherServlet extends HttpServlet {

    @Override
    public void init(ServletConfig config) throws ServletException {
        Loader.init();//初始化框架&应用
        ServletContext sc = config.getServletContext();
        //注册JSP的Servlet
        ServletRegistration jspServlet = sc.getServletRegistration("jsp");
        jspServlet.addMapping(ConfigHelper.getAppJspPath() + "*");
        //注册处理静态资源的Servlet
        ServletRegistration defaultServlet = sc.getServletRegistration("default");
        defaultServlet.addMapping(ConfigHelper.getAppAssetPath() + "*");
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取请求方法
        String requestMethod = req.getMethod().toLowerCase();
        //请求路径url
        String url = req.getRequestURI();
        String contextPath = req.getContextPath();
        String requestPath = null;
        if (contextPath != null && contextPath.length() > 0) {
            requestPath = url.substring(contextPath.length());
        }
        //获取处理这个请求的handler
        Handler handler = ControllerHelper.getHandler(requestMethod, requestPath);
       // System.out.println(requestMethod + "  " + requestPath);
        if (handler != null) {
            Class<?> controllerClass = handler.getControllerClass();
            Object controllerBean =    BeanContainer.getBean(controllerClass.getName());
            //解析请求参数
            Param param = ParameterUtil.createParam(req);
            Object result;//请求返回对象
            Method method = handler.getMethod();//处理请求的方法
            if (param.isEmpty()) {
                result = BeanFactory.invokeMethod(controllerBean, method);
            } else {
                result = BeanFactory.invokeMethod(controllerBean, method, param);
            }
            if (result instanceof ModelAndView) {
                handleViewResult((ModelAndView) result, req, resp);
            } else {
                handleDataResult((Data) result, resp);
            }
        }
    }

    //返回为JSP页面
    private static void handleViewResult(ModelAndView view, HttpServletRequest req, HttpServletResponse resp)
            throws IOException, ServletException {
        String path = view.getPath();
        if (StringUtil.isNotEmpty(path)) {
            if (path.startsWith("/")) {
                resp.sendRedirect(req.getContextPath() + path);
            } else {
                Map<String, Object> data = view.getmData();
                for (Map.Entry<String, Object> entry : data.entrySet()) {
                    req.setAttribute(entry.getKey(), entry.getValue());
                }
                //forward将页面响应转发到ConfigHelper.getAppJspPath() + path
                //补全代码

            }
        }
    }

    //返回JSON数据
    private static void handleDataResult(Data data, HttpServletResponse resp)
            throws IOException {
        Object model = data.getData();
        if (model != null) {
            resp.setContentType("application/json");
            resp.setCharacterEncoding("UTF-8");
            PrintWriter writer = resp.getWriter();
            String json = JsonUtil.toJSON(model);
            writer.write(json);
            writer.flush();
            writer.close();
        }
    }

}
在com.hubwiz.web.DispatherServlet类service方法中,实现返回视图的功能。