SpringMVC底层分析--2.RequestMappingHandlerMapping和RequestMappingHandlerAdaptor

一.RequestMappingHandlerMapping

RequestMappingHandlerMapping是sprringmvc核心的控制映射组件,它主要是用来解析

@RequestMapping和它的一些派生注解,例如@GetMapping,@PostMapping等

它和对应的路径和处理方法联系起来

二.RequestMappingHandlerMapping示例

1.创建Controller

我们创建springboot项目,然后我们先配置好MyController类

@Controller
public class MyController {

    @GetMapping("/test1")
    public String test1(){

        return "test1";
    }

    @PostMapping("/test2")
    public String test2(@RequestParam("p1") String p1){
        return  "test2";
    }

    @RequestMapping("/test3")
    public String test3(){
        return "test3";
    }



}

2.配置自定义RequesetMappingHandlerMapping

注意:要说明一点,如果我们自己不配置RequestMappingHandlerMapping,那么spring使用的是默认的处理映射,如果自己配置了,那么就会用我们的,下面我们来自己配置处理映射

在配置类中声明为bean即可:

    //自定义RequestMappingHandlerMappening
    @Bean
    public RequestMappingHandlerMapping requestMappingHandlerMapping(){
        return new RequestMappingHandlerMapping();
    }

3.测试

然后我们通过容器获取这个bean,通过getHandlerMethods()获取它的路径方法映射集合

 public static void main(String[] args) {

        AnnotationConfigServletWebServerApplicationContext context =
                new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);

        RequestMappingHandlerMapping handlerMapping =
                context.getBean(RequestMappingHandlerMapping.class);

        Map<RequestMappingInfo, HandlerMethod> handlerMethods =
                handlerMapping.getHandlerMethods();

        handlerMethods.forEach((k,v)->{
            System.out.println(k+"="+v);

        });

    }

我们运行一下:

{POST [/test2]}=com.jjh.config.MyController#test2(String)
{ [/test3]}=com.jjh.config.MyController#test3()
{GET [/test1]}=com.jjh.config.MyController#test1()

我们发现我们在Controller里定义的方法都获取出来了!

4.模拟请求获取调用链

下面我们来模拟一个get请求,观察一下他的调用链:

这里我们为了方便演示,我们使用了Spring为我们提供的MockHttpServletRequest,它可以模拟发送http请求

   HandlerExecutionChain chain = handlerMapping
                .getHandler(new MockHttpServletRequest("GET", "/test1"));

        System.out.println(chain);

我们运行一下:

09:38:04.100 [main] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to com.jjh.config.MyController#test1()
HandlerExecutionChain with [com.jjh.config.MyController#test1()] and 0 interceptors

我们看到这个调用链,它调用了我们的test1方法,现在没有拦截器,所以拦截器数量为0

三.RequestMappingHandlerAdaptor

该对象是用来调用上面调用链中的controller方法的,下面我们来模拟实现一下:

1.通过继承修改权限为public来突破保护

该类中有个关键方法是invokeHandlerMethod,它就是用来调用chain中的方法,但是他是protectecd的,不能直接使用,我们可以自定义一个类来继承它,然后重新该方法,只需要把该方法改为public就可以了,然后super调用原来的方法就可以了,这是一种解决方法,我们以后可以用这种方法来突破保护

2.自定义MyRequestMappingHandlerAdaptor,继承RequestMappingHandlerAdaptor

public class MyRequestMappingHandlerAdapter extends RequestMappingHandlerAdapter {

    @Override
    public ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
        return super.invokeHandlerMethod(request, response, handlerMethod);
    }
}

3.将自定义的这个类注册为bean,以覆盖spring默认的适配器

   //自定义RequestMappingHandlerAdapter
    @Bean
    public RequestMappingHandlerAdapter requestMappingHandlerAdapter(){
        return new MyRequestMappingHandlerAdapter();
    }

3.测试

 MyRequestMappingHandlerAdapter handlerAdapter =  context
                .getBean(MyRequestMappingHandlerAdapter.class);
        
        //创建模拟请求 和 响应
        HttpServletRequest request = new MockHttpServletRequest("GET", "/test1");
        HttpServletResponse response = new MockHttpServletResponse();

        //调用该方法
        handlerAdapter.invokeHandlerMethod(request,response, (HandlerMethod) chain.getHandler());

运行一下,查看:

10:18:52.436 [main] INFO com.jjh.config.MyController - test1...

我们可以看到成功调用了test1方法!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值