面试题之--SpringMVC 原理

前言

一次为了解决跨域问题,采用了CORS方法。根据官方解释,只需要在响应头里设置
1、Access-Control-Allow-Origin
2、Access-Control-Allow-Methods
3、Access-Control-Allow-Headers
三个值就可以了,于是想到在HandlerInterceptor#preHandle()里去拦截跨域请求(options),然后再根据自定义注解判断请求的controller是否支持跨域请求,再设置对应的响应头。(项目基于spring3.2.x)但是发现请求死活无法进入preHandle里(项目里只有一个自定义的preHandle,不存在提前被别的HandlerInterceptor返回的情况)。于是利用debug大法,发现spring获取拦截器时是根据url和请求类型进行判断的,由于跨域请类型是options,无法获取对于的handler和HandlerInterceptor,导致直接就返回了,没有进入拦截器里。(spring4.x后有个默认的handler支持处理options)。于是把debug过程中学习到的知识,下次排查问题可以更快。

Dispathcher处理请求的流程概览

image-20191201184710800

组件 说明
Dispatcher 负责接收用户请求,并且协调内部的各个组件完成请求的响应
HandlerMapping 通过request获取handler和interceptors
HandlerAdapter 处理器的适配器。Spring 中的处理器的实现多变,可以通过实现 Controller 接口,也可以用 @RequestMapping 注解将方法作为一个处理器等,这就导致调用处理器是不确定的。所以这里需要一个处理器适配器,统一调用逻辑。
ViewResolver 解析视图,返回数据

Dispathcer的继承图

image-20191127200505690

从继承视图可以看出,Dispatcher是Servlet的一个实现类。也就是遵循了J2EE规范的处理器。

Servlet是一个接口,包含以下方法

public interface Servlet {
   
   
    /**
    * 对配置文件(web.xml)的解析,初始化
    */
    public void init(ServletConfig config) throws ServletException;

    public ServletConfig getServletConfig();

    /**
    * 业务逻辑实现在该方法内
    * 该方法会被Web容器(如:Tomcat)调用
    */
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException;

    public String getServletInfo();

    public void destroy();
}

HttpServlet这个类是和 HTTP 协议相关。该类的关注点在于怎么处理 HTTP 请求,比如其定义了 doGet 方法处理 GET 类型的请求,定义了 doPost 方法处理 POST 类型的请求等。我们若需要基于 Servlet 写 Web 应用,应继承该类,并覆盖指定的方法。所有的处理get请求、post请求都是由service 方法进行调用的。如下:

public abstract class HttpServlet extends GenericServlet
        implements java.io.Serializable {
   
  
  /**
    *实现Servlet的service方法,并且将请求转为http请求
    *调用内部方法service(HttpServletRequest req, HttpServletResponse resp),处理http请求
    *
    */
  public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException {
   
        HttpServletRequest request;
        HttpServletResponse response;

        try {
   
            request = (HttpServletRequest) req;
            response = (HttpServletResponse) res;
        } catch (ClassCastException e) {
   
            throw new ServletException("non-HTTP request or response");
        }
        service(request, response);
    }
  
  /**
    *http请求的分发
    */
   protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
   
        String method = req.getMethod();

        if (method.equals(METHOD_GET)) {
   
            long lastModified = getLastModified(req);
            if (lastModified == -1) {
   
                // servlet doesn't support if-modified-since, no reason
                // to go through further expensive logic
                doGet(req, resp);
            } else {
   
                long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                    doGet(req, resp);
                } else {
   
                    resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                }
            }

        } else if (method
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值