• SpringBoot2.0---------------9、SpringBoot请求映射使用与原理


    1. 请求映射

    1.1 rest使用与原理

    ● @xxxMapping;如:@RequestrianMapping及其衍生注解,@GetMapping(处理get请求)、@PostMapping(处理post请求)、@PutMapping(处理put请求)、@DeleteMapping(处理delete请求)
    ● Rest风格支持(使用HTTP请求方式动词来表示对资源的操作)
      ○ 以前:/getUser 获取用户 /deleteUser 删除用户 /editUser 修改用户 /saveUser 保存用户
      ○ 现在: /user GET-获取用户 DELETE-删除用户 PUT-修改用户 POST-保存用户
      ○ 核心Filter;HiddenHttpMethodFilter
       ■ 用法: 表单method=post,隐藏域 _method=put
       ■ SpringBoot中手动开启
      ○ 扩展:如何把_method 这个名字换成我们自己喜欢的。

    Rest原理:
    DELETE、PUT请求不被浏览器支持(浏览器只支持GET、POST请求)。

    <body>
    测试REST风格,GET POST DELETE PUT四种请求
    <form action="/user" method="get">
        <input value="REST-GET 提交" type="submit">
    form>
    <form action="/user" method="post">
        <input value="REST-POST 提交" type="submit">
    form>
    <form action="/user" method="post">
        <input name="_method" type="hidden" value="DELETE">
        <input value="REST-DELETE 提交" type="submit">
    form>
    <form action="/user" method="put">
        <input name="_method" type="hidden" value="PUT">
        <input value="REST-PUT 提交" type="submit">
    form>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    DELETE、PUT请求的处理:
    1)表单提交中带上请求参数 _method= PUT (或DELETE);
    2)然后请求会被HiddenHttpMethodFilter过滤器拦截,判定请求是否正常,并且是POST请求
    3)获取_method的值(表单里面带过来的)
    4)原生request(POST),包装模式requestWrapper重写了getMethod方法,返回的是传入的值。
    5)过滤器放行的时候用wrapper。以后的方法调用getMethod是调用requesWrapper(封装的是_method的值)的。

    拦截器对POST请求的处理部分代码如下:

        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
            HttpServletRequest requestToUse = request;
            if ("POST".equals(request.getMethod()) && request.getAttribute("javax.servlet.error.exception") == null) {
                String paramValue = request.getParameter(this.methodParam);
                if (StringUtils.hasLength(paramValue)) {
                    String method = paramValue.toUpperCase(Locale.ENGLISH);
                    if (ALLOWED_METHODS.contains(method)) {
                        requestToUse = new HiddenHttpMethodFilter.HttpMethodRequestWrapper(request, method);
                    }
                }
            }
    
            filterChain.doFilter((ServletRequest)requestToUse, response);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    Rest原理(表单提交要使用REST的时候)
    ● 表单提交会带上_method=PUT
    ● 请求过来被HiddenHttpMethodFilter拦截
    ○ 请求是否正常,并且是POST
    ■ 获取到_method的值。
    ■ 兼容以下请求;PUT.DELETE.PATCH
    ■ 原生request(post),包装模式requesWrapper重写了getMethod方法,返回的是传入的值。
    ■ 过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用requesWrapper的。

    Rest使用客户端工具,
    ● 如PostMan直接发送Put、delete等方式请求,无需Filter。

    rest使用开启配置:

    spring:
      mvc:
        hiddenmethod:
          filter:
            enabled: true   #开启页面表单的Rest功能
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2. 请求映射原理

    SpringMVC功能分析都从 org.springframework.web.servlet.DispatcherServlet-》doDispatch()开始分析

    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    		HttpServletRequest processedRequest = request;
    		HandlerExecutionChain mappedHandler = null;
    		boolean multipartRequestParsed = false;
    
    		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    
    		try {
    			ModelAndView mv = null;
    			Exception dispatchException = null;
    
    			try {
    				processedRequest = checkMultipart(request);
    				multipartRequestParsed = (processedRequest != request);
    
    				// 找到当前请求使用哪个Handler(Controller的方法)处理
    				mappedHandler = getHandler(processedRequest);
                    
                    //HandlerMapping:处理器映射。/xxx->>xxxx
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述
    RequestMappingHandlerMapping:保存了所有@RequestMapping 和handler的映射规则。
    在这里插入图片描述
    所有的请求映射都在HandlerMapping中。

     ● SpringBoot自动配置欢迎页的 WelcomePageHandlerMapping 。访问 /能访问到index.html;
     ● SpringBoot自动配置了默认 的 RequestMappingHandlerMapping
     ● 请求进来,挨个尝试所有的HandlerMapping看是否有请求信息。
       ○ 如果有就找到这个请求对应的handler
       ○ 如果没有就是下一个 HandlerMapping
     ● 我们需要一些自定义的映射处理,我们也可以自己给容器中放HandlerMapping。自定义 HandlerMapping

    	protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    		if (this.handlerMappings != null) {
    			for (HandlerMapping mapping : this.handlerMappings) {
    				HandlerExecutionChain handler = mapping.getHandler(request);
    				if (handler != null) {
    					return handler;
    				}
    			}
    		}
    		return null;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  • 相关阅读:
    设计模式-抽象工厂模式
    微信小程序 uniapp+vue餐厅美食就餐推荐系统
    微信自动通过好友请求是怎么设置的?
    Echarts折线图隐藏markPoint只显示最大值和最小值的文本,且只在该两点显示symbol
    Java Agent场景性能测试分析优化经验分享
    三国志14信息查询小程序(历史武将信息一览)制作更新过程03-主要页面的设计
    OKR 锦囊妙计
    UE4 命名规范
    MFC的CPen与CBush画图对象使用步骤
    136. 只出现一次的数字(hot100)
  • 原文地址:https://blog.csdn.net/lyy_sss/article/details/126166356