SpringMVC源码(四)- 常用HandlerMapping和HandlerAdaptor组合和使用方式

目录

一、HandlerMapping和HandlerAdaptor初始化(initStrategies)

二、常用的HandlerMapping和HandlerAdaptor组合

三、常用的Controller方式

1、RequestMappingHandlerAdapter

2、HttpRequestHandlerAdapter

3、SimpleControllerHandlerAdapter

4、HandlerFunctionAdapter

5、SimpleServletHandlerAdapter


一、HandlerMapping和HandlerAdaptor初始化(initStrategies

    之前分析过九大件中会初始化HandlerMapping和HandlerAdaptor(操作适配器),就是解析各种Controller类型和负责解析调用。Spring允许各种形式初始化Controller,那么对于的接口名称、配置方式等都是不同的。所以需要适配器挨个去适配HttpServletRequest。继续九大件中关于HandlerMapping和HandlerAdaptor的初始化,(之前的版本可能是没有配置就直接调用策略中的,当前版本为5.2.0可能稍微不同,但是主要使用的是@RequestMapping注解的RequestMappingHandlerMappingRequestMappingHandlerAdapter类型)。

    HandlerMapping和HandlerAdaptor的初始化方式基本都一样,只是策略中初始化的类型有所不同。但是必须进行对应,否则doDispatch方法中,HandlerMapping列表遍历解析Controller和HandlerInteceptor链后,需要对应的HandlerAdaptor类型进行解析调用具体的Controller方法。下面是HandlerAdaptor的初始化过程,HandlerMapping类似,如下:

private void initHandlerAdapters(ApplicationContext context) {
    this.handlerAdapters = null;
    // 查询所有的HandlerAdapter类型(默认为true)
    if (this.detectAllHandlerAdapters) {
        // 擦汗寻BeanFactory中所有的HandlerAdapter类型
        Map<String, HandlerAdapter> matchingBeans =
                BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
        if (!matchingBeans.isEmpty()) {
            this.handlerAdapters = new ArrayList<>(matchingBeans.values());
            // 按照实现order接口的排序(比如常用的RequestMappingHandlerAdapter
            // 就在父类中实现了getOrder为Ordered.LOWEST_PRECEDENCE)
            AnnotationAwareOrderComparator.sort(this.handlerAdapters);
        }
    } else {
        // 省略try catch代码
        HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
        this.handlerAdapters = Collections.singletonList(ha);
    }
    // 最后兜底是静态代码块中策略模式初始化的HandlerAdapter类型
    if (this.handlerAdapters == null) {
        this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
    }
}

    1、如果参数detectAllHandlerAdapters(查询所有HandlerAdapter类型Bean,包括非单利)表示为true,默认为true。直接进行BeanFactory中获取全部,并且按照事先了排序接口返回值进行排序。

    2、detectAllHandlerAdapters参数被修改过,则可以直接获取容器中自定义的HANDLER_ADAPTER_BEAN_NAME名称的Bean。之前的版本中只要配置该Bean名称就会使用自定义的。

    3、如果上面都没有获取到,则使用静态代码块策略模式加载的DispatcherServlet.properties中的配置HandlerAdapter类型。

 

二、常用的HandlerMapping和HandlerAdaptor组合

    但是不论哪种方式,主要常用的适配器有以下几种(现在很少使用xml方式配置了,基本都是使用Spring boot方式,这里也是使用该方式进行demo搭建的,详细地址为:)

1、@RequestMapping注解方式的适配器

    RequestMappingHandlerMapping -> RequestMappingHandlerAdapter

2、继承HttpRequestHandler的HTTP请求处理器适配器

    BeanNameUrlHandlerMapping -> HttpRequestHandlerAdapter

3、继承Controller接口方式的适配器,现在很少使用了

    BeanNameUrlHandlerMapping -> SimpleControllerHandlerAdapter

4、返回RouterFunction类型的适配器

    HandlerFunctionAdapter -> RouterFunctionMapping

5、继承自HttpServlet接口,现在已经废弃了

    SimpleUrlHandlerMapping -> SimpleServletHandlerAdapter

 

三、常用的Controller方式

    需要配置不同类型的Controller注册成Bean,这里直接使用@Bean注解而不是xml配置的形式,如下

@Controller
public class BeanController {

    @Bean("/controllerAdaptorController")
    public ControllerAdaptorController initControllerAdaptorController() {
        return new ControllerAdaptorController();
    }

    @Bean("/httpRequestController")
    public HttpRequestController initHttpRequestController() {
        return new HttpRequestController();
    }

    @Bean("simpleServletHandlerAdapter")
    public SimpleServletHandlerAdapter initSimpleServletHandlerAdapter() {
        return new SimpleServletHandlerAdapter();
    }
}

1、RequestMappingHandlerAdapter

/**
 *  适配器类型为: {@link RequestMappingHandlerAdapter}, 处理注解{@link RequestMapping} 类型的方法
 * @author lihongmin
 * @date 2019/12/26 9:50
 * @since 1.0.0
 */
@Controller
public class AnnotationController {

    @ResponseBody
    @RequestMapping("annotationController")
    public String annotationController() {
        return "AnnotationController -> @Controller!";
    }
}

    我们最常用的@RequestMapping注解形式的适配器使用RequestMappingHandlerAdapter类型,后续Spring MVC适配器主要分析该类型的实现过程。

    访问地址为:http://127.0.0.1:9999/annotationController

2、HttpRequestHandlerAdapter

/**
 *  适配器类型为: {@link HttpRequestHandlerAdapter},不返回
 *  {@link ModelAndView} 或者 {@link View}
 *
 * @author lihongmin
 * @date 2019/12/26 9:58
 * @since 1.0.0
 */
public class HttpRequestController implements HttpRequestHandler {

    @Override
    public void handleRequest(HttpServletRequest request, 
        HttpServletResponse response) throws ServletException, IOException {

        response.getWriter().println("HttpRequestController -> HttpRequestHandler!");
    }
}

    访问地址为:http://127.0.0.1:9999/httpRequestController

3、SimpleControllerHandlerAdapter

/**
 *  适配器为: {@link SimpleControllerHandlerAdapter} 但是不能
 *  与{@link ResponseBody}一起使用(不生效) 
 *
 * @author lihongmin
 * @date 2019/12/26 9:40
 * @since 1.0.0
 */
public class ControllerAdaptorController implements Controller {

    @Override
    @ResponseBody
    public ModelAndView handleRequest(HttpServletRequest request, 
        HttpServletResponse response) throws Exception {

        ModelAndView modelAndView = new ModelAndView("test");
        modelAndView.addObject("key", "ControllerAdaptorController -> Controller!");
        return modelAndView;
    }
}

    直接将自己的Controller类实现Controller接口,缺点很明细只有一个接口方法。

    访问地址为:http://127.0.0.1:9999/controllerAdaptorController

 

4、HandlerFunctionAdapter

/**
 *  适配器类型为:{@link HandlerFunctionAdapter}
 *  reactive 相关,当前总是报错MediaType设置问题
 * @author lihongmin
 * @date 2019/12/26 10:21
 * @since 1.0.0
 */
@Configuration
public class HandlerFunctionAdapterController {
    @Bean
    public RouterFunction<ServerResponse> testRouterFunction() {
        return RouterFunctions.route(RequestPredicates.path("/handlerFunctionAdapter")
                        .and(RequestPredicates.accept(MediaType.APPLICATION_JSON)),
                request -> ok().body(fromObject("HandlerFunctionAdapterController ->
                   HandlerFunctionAdapter!")));
    }
}

    访问地址为:http://127.0.0.1:9999/handlerFunctionAdapter

5、SimpleServletHandlerAdapter

/**
 *  适配器类型为: {@link SimpleServletHandlerAdapter}
 * @author lihongmin
 * @date 2019/12/26 9:48
 * @since 1.0.0
 */
public class HttpServletController extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, 
        HttpServletResponse resp) throws IOException {

        resp.getWriter().write("HttpServletController -> HttpServlet!");
    }
}

    访问地址为:http://127.0.0.1:9999/simpleServletHandlerAdapter

©️2020 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值