• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

springboot Rest映射和源码(里面包括@RequestMapping()和@GetMapping()用法)

武飞扬头像
结城明日奈是我老婆
帮助1

springboot在底层使用springMVC来进行web处理的整个细节

首先第一个跟 请求 有关的

请求参数处理

在做我们所有web开发之前我们最先要做的事情就是:

0、请求映射

xxxMapping

也就是我们编写一个@RestController每一个方法上使用@RequestMapping来申明我们的方法能处理什么请求,我们把这个申明过程称做请求映射。

那请求映射大家最习惯用的就是@RequestMapping注解:

package org.springframework.web.bind.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
    String name() default "";

    @AliasFor("path")
    String[] value() default {};

    @AliasFor("value")
    String[] path() default {};

    RequestMethod[] method() default {};

    String[] params() default {};

    String[] headers() default {};

    String[] consumes() default {};

    String[] produces() default {};
}
学新通

这里有value()path()俩个方法都一样, 它们能代表我们当前请求能处理哪个路劲 ,包括这还有一个 能处理请求的请求方式(RequestMethod[] method()) ,这块就牵扯到了我们请求处理里的第二个Rest风格后来开发我们都习惯与用Rest风格,因为以前:

比如:我们要 对用户进行增删改查操作,我们可能定义的url 是 /getUser /deleteUser /editUser /saveUser,这样我们项目一大期间,我们整个路劲起名都感觉很麻烦。

我们现在希望的是 所有对用户 资源的操作我们都叫/user 怎么代表对用户的增删改查:

  • Rest风格(使用HTTP请求方式动词来表示对资源的操作)

  • Rest原理(表单提交要使用Rest风格的时候)

    • 以前: /getUser /deleteUser /editUser /saveUser
    • 现在: /user GET-获取用户 DELETE-删除用户 PUT-修改用户 POST-保存用户

    我们现在希望能用这种请求方式来区分我们对资源的操作。那我们现在就是路劲(无论是增删改查都叫/user)那我们以前使用springMVC要来完成这个事情,那我们的核心就是在我们整个mvc中配置一个叫HiddenHttpMethodFilter有了它才行,为什么要配置它?我们来测试一下:

    在我们Controller里面添加代码:

    package com.example.boot05web01.Contorller;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class HelloController {
        
        @RequestMapping(value = "/user" , method = RequestMethod.GET)
        public String getUser(){
            return "GET-李四";
        }
        @RequestMapping(value = "/user" , method = RequestMethod.POST)
        public String saveUser(){
            return "POST-李四";
        }
        @RequestMapping(value = "/user" , method = RequestMethod.PUT)
        public String putUser(){
            return "PUT-李四";
        }
        @RequestMapping(value = "/user" , method = RequestMethod.DELETE)
        public String deleteUser(){
            return "DELETE-李四";
        }
    }
    
    学新通

    写了四个方法,请求路劲都是叫/user但是我是以什么方式来区分我到底是查询还是添加请求?

    是以后面method = RequestMethod方式来判断的.

    但这种方式的写法问题就是我们的页面的这个表单<form method="">这一项就算写,提示出来它只能有getpost而我们DELETEPUT发不出来

    我们在index上添加:

    <div>
            <form action="/user" method="get">
                <input type="submit" value="REST-GET 提交" />
            </form>
            <form action="/user" method="post">
                <input type="submit" value="REST-POST 提交" />
            </form>
            <form action="/user" method="put">
                <input type="submit" value="REST-PUT 提交" />
            </form>
            <form action="/user" method="delete">
                <input type="submit" value="REST-DELETE 提交" />
            </form>
        </div>
    

    我们访问到当前项目

    localhost:8080/
    

    getpost都正常,就是putdelete的结果都变成了GET-李四 原因就是你写的put methoddelete method并不支持,也就是说都会当成默认的GET方式,来到了getUser()请求处理。我们怎样才能让它能处理putdelete呢?

    我们需要给我们springMVC中配一个HiddenHttpMethodFilter但是按照我们springbootwebMvcAtuoCondiguration.java(springboot整个对mvc功能的配置),我们可以看到它已经配了一个

    @Bean
    	@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
    	@ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled")
    	public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
    		return new OrderedHiddenHttpMethodFilter();
    	}
    

    也就是说:我们默认就Rest功能是能用的

    我们来做一个测试:

    如果你想要做这个功能,你就首先点开OrderedHiddenHttpMethodFilter点开

    package org.springframework.boot.web.servlet.filter;
    
    import org.springframework.core.Ordered;
    import org.springframework.web.filter.HiddenHttpMethodFilter;
    
    public class OrderedHiddenHttpMethodFilter extends HiddenHttpMethodFilter implements OrderedFilter {...}
    

    在这个Filter里面人家规定HiddenHttpMethodFilterFilter里面

    package org.springframework.web.filter;
    
    import java.io.IOException;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.List;
    import java.util.Locale;
    import javax.servlet.FilterChain;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    import javax.servlet.http.HttpServletResponse;
    import org.springframework.http.HttpMethod;
    import org.springframework.util.Assert;
    import org.springframework.util.StringUtils;
    
    public class HiddenHttpMethodFilter extends OncePerRequestFilter {
        private static final List<String> ALLOWED_METHODS;
        public static final String DEFAULT_METHOD_PARAM = "_method";
        private String methodParam = "_method";
    
        public HiddenHttpMethodFilter() {
        }
    
        public void setMethodParam(String methodParam) {
            Assert.hasText(methodParam, "'methodParam' must not be empty");
            this.methodParam = methodParam;
        }
    
        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);
        }
    
        static {
            ALLOWED_METHODS = Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(), HttpMethod.DELETE.name(), HttpMethod.PATCH.name()));
        }
    
        private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {
            private final String method;
    
            public HttpMethodRequestWrapper(HttpServletRequest request, String method) {
                super(request);
                this.method = method;
            }
    
            public String getMethod() {
                return this.method;
            }
        }
    }
    
    学新通

    public static final String DEFAULT_METHOD_PARAM = "_method";: 你只要给我们带来一个隐藏的参数项叫_method就行

    你想要真正的起到delete请求了,表单还是method="post"方式,为什么是post:

    因为在HiddenHttpMethodFilter底层doFilter在写的时候

    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);
    }
    

    只有你的表单是post方式,然后我才把你表单里真正提交的(request.getParameter())methodParam这个请求参数就是_method。我就拿到你post表单这个_method的参数:

    <form action="/user" method="post">
        <input name="_method" type="hidden" value="PUT"/>
    	<input type="submit" value="REST-PUT 提交" />
    </form>
    

    我们一般把它(_method)隐藏(type="hidden")起来。然后_method作为你的真正请求方式(value=""),比如你想要put提交就写value="PUT",(DELETE也一样), 要想要在页面提交Rest风格,那必须都是这么来做(给表单上提交一个_method(name="_method")隐藏参数(type="hidden"),然后在隐藏参数上写上它的隐藏参数类型(value=""))

    然后可以测试一下:

    可是DELETE还是变成POST-李四,而且PUT也还是POST-李四 可是明明springboot在我们底层已经开启这个功能了,我们就来好好分析一下:

    @Bean
    	@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
    	@ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled")
    	public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
    		return new OrderedHiddenHttpMethodFilter();
    	}
    

    它是给我们在容器中放了一个HiddenHttpMethodFilter但条件是@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)也就是容器没有的时候再放,也就是说如果你配的就按照你的,现在我们没配,它就放;然后接下来有一个@ConditionalOnProperty也就是说它判断我们配置文件中会配一个属性叫spring.mvc.hiddenmethod.filter然后enabled相当于要不要开启我们这个Rest风格的hiddenHttpMethodFilter这个功能,我们这里没说默认赋的值是什么,我们在yml里面看一下:

    spring:
      mvc:
        hiddenmethod:
          filter:
            enabled: false
    

    按照提示下来enabled: false的值是false就是说默认功能是不开启的,所以我们要在propertiesyml里开启一下功能(enabled:true)

    我们重新启动

    原理就是在我们容器中放了一个Filter

    我们想要看它是怎么处理的,我们可以在HiddenHttpMethodFilterdoFilterInternal()方法打上断点。(在Debug的时候我这里是没有进入到断点这,得在页面上点击PUT或DELETE按键时进入到断点)

  • Rest风格(使用HTTP请求方式动词来表示对资源的操作)

  • Rest原理(表单提交要使用Rest风格的时候)

    • 以前: /getUser /deleteUser /editUser /saveUser
    • 现在: /user GET-获取用户 DELETE-删除用户 PUT-修改用户 POST-保存用户

    我们现在希望能用这种请求方式来区分我们对资源的操作。那我们现在就是路劲(无论是增删改查都叫/user)那我们以前使用springMVC要来完成这个事情,那我们的核心就是在我们整个mvc中配置一个叫HiddenHttpMethodFilter有了它才行,为什么要配置它?我们来测试一下:

    在我们Controller里面添加代码:

    package com.example.boot05web01.Contorller;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class HelloController {
        
        @RequestMapping(value = "/user" , method = RequestMethod.GET)
        public String getUser(){
            return "GET-李四";
        }
        @RequestMapping(value = "/user" , method = RequestMethod.POST)
        public String saveUser(){
            return "POST-李四";
        }
        @RequestMapping(value = "/user" , method = RequestMethod.PUT)
        public String putUser(){
            return "PUT-李四";
        }
        @RequestMapping(value = "/user" , method = RequestMethod.DELETE)
        public String deleteUser(){
            return "DELETE-李四";
        }
    }
    
    学新通

    写了四个方法,请求路劲都是叫/user但是我是以什么方式来区分我到底是查询还是添加请求?

    是以后面method = RequestMethod方式来判断的.

    但这种方式的写法问题就是我们的页面的这个表单<form method="">这一项就算写,提示出来它只能有getpost而我们DELETEPUT发不出来

    我们在index上添加:

    <div>
            <form action="/user" method="get">
                <input type="submit" value="REST-GET 提交" />
            </form>
            <form action="/user" method="post">
                <input type="submit" value="REST-POST 提交" />
            </form>
            <form action="/user" method="put">
                <input type="submit" value="REST-PUT 提交" />
            </form>
            <form action="/user" method="delete">
                <input type="submit" value="REST-DELETE 提交" />
            </form>
        </div>
    

    我们访问到当前项目

    localhost:8080/
    

    getpost都正常,就是putdelete的结果都变成了GET-李四 原因就是你写的put methoddelete method并不支持,也就是说都会当成默认的GET方式,来到了getUser()请求处理。我们怎样才能让它能处理putdelete呢?

    我们需要给我们springMVC中配一个HiddenHttpMethodFilter但是按照我们springbootwebMvcAtuoCondiguration.java(springboot整个对mvc功能的配置),我们可以看到它已经配了一个

    @Bean
    	@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
    	@ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled")
    	public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
    		return new OrderedHiddenHttpMethodFilter();
    	}
    

    也就是说:我们默认就Rest功能是能用的

    我们来做一个测试:

    如果你想要做这个功能,你就首先点开OrderedHiddenHttpMethodFilter点开

    package org.springframework.boot.web.servlet.filter;
    
    import org.springframework.core.Ordered;
    import org.springframework.web.filter.HiddenHttpMethodFilter;
    
    public class OrderedHiddenHttpMethodFilter extends HiddenHttpMethodFilter implements OrderedFilter {...}
    

    在这个Filter里面人家规定HiddenHttpMethodFilterFilter里面

    package org.springframework.web.filter;
    
    import java.io.IOException;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.List;
    import java.util.Locale;
    import javax.servlet.FilterChain;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    import javax.servlet.http.HttpServletResponse;
    import org.springframework.http.HttpMethod;
    import org.springframework.util.Assert;
    import org.springframework.util.StringUtils;
    
    public class HiddenHttpMethodFilter extends OncePerRequestFilter {
        private static final List<String> ALLOWED_METHODS;
        public static final String DEFAULT_METHOD_PARAM = "_method";
        private String methodParam = "_method";
    
        public HiddenHttpMethodFilter() {
        }
    
        public void setMethodParam(String methodParam) {
            Assert.hasText(methodParam, "'methodParam' must not be empty");
            this.methodParam = methodParam;
        }
    
        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);
        }
    
        static {
            ALLOWED_METHODS = Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(), HttpMethod.DELETE.name(), HttpMethod.PATCH.name()));
        }
    
        private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {
            private final String method;
    
            public HttpMethodRequestWrapper(HttpServletRequest request, String method) {
                super(request);
                this.method = method;
            }
    
            public String getMethod() {
                return this.method;
            }
        }
    }
    
    学新通

    public static final String DEFAULT_METHOD_PARAM = "_method";: 你只要给我们带来一个隐藏的参数项叫_method就行

    你想要真正的起到delete请求了,表单还是method="post"方式,为什么是post:

    因为在HiddenHttpMethodFilter底层doFilter在写的时候

    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);
    }
    

    只有你的表单是post方式,然后我才把你表单里真正提交的(request.getParameter())methodParam这个请求参数就是_method。我就拿到你post表单这个_method的参数:

    <form action="/user" method="post">
        <input name="_method" type="hidden" value="PUT"/>
    	<input type="submit" value="REST-PUT 提交" />
    </form>
    

    我们一般把它(_method)隐藏(type="hidden")起来。然后_method作为你的真正请求方式(value=""),比如你想要put提交就写value="PUT",(DELETE也一样), 要想要在页面提交Rest风格,那必须都是这么来做(给表单上提交一个_method(name="_method")隐藏参数(type="hidden"),然后在隐藏参数上写上它的隐藏参数类型(value=""))

    然后可以测试一下:

    可是DELETE还是变成POST-李四,而且PUT也还是POST-李四 可是明明springboot在我们底层已经开启这个功能了,我们就来好好分析一下:

    @Bean
    	@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
    	@ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled")
    	public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
    		return new OrderedHiddenHttpMethodFilter();
    	}
    

    它是给我们在容器中放了一个HiddenHttpMethodFilter但条件是@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)也就是容器没有的时候再放,也就是说如果你配的就按照你的,现在我们没配,它就放;然后接下来有一个@ConditionalOnProperty也就是说它判断我们配置文件中会配一个属性叫spring.mvc.hiddenmethod.filter然后enabled相当于要不要开启我们这个Rest风格的hiddenHttpMethodFilter这个功能,我们这里没说默认赋的值是什么,我们在yml里面看一下:

    spring:
      mvc:
        hiddenmethod:
          filter:
            enabled: false
    

    按照提示下来enabled: false的值是false就是说默认功能是不开启的,所以我们要在propertiesyml里开启一下功能(enabled:true)

    我们重新启动

    原理就是在我们容器中放了一个Filter

    我们想要看它是怎么处理的,我们可以在HiddenHttpMethodFilterdoFilterInternal()方法打上断点。(在Debug的时候我这里是没有进入到断点这,得在页面上点击PUT或DELETE按键时进入到断点)


    原理是这样:

    首先我们在页面上

    • 核心Filter:HiddenHttpMethodFilter
      • 用法: 表单=post, 隐藏域_method=put
      • Spring中要手动开启

Rest原理(表单提交要使用Rest风格的时候)

  • 表单提交会带上我们__method的参数,因为按照要求我们在表单里面带了个name="_method"的等于真正请求方式的参数

  • 因为我们配了Filter(OrderedHiddenHttpMethodFilter这是一个过滤器)``所以请求过来会被Filter拦截`

  • 接下来时处理请求:在doFilterInternal()打上断点,点击网页的putdelete按键到断点,首先拿到我们这个请求(HttpServletRequest requestToUse = request;)step Over(F8) ,开始判断(if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null))第一步:是不是POST,这就要求我们表单提交的时候必须是POST方式才能使用表单Rest的风格;第二步: request.getAttribute()Attribute获取当前请求是不是有没有什么错误,如果没啥错误咱们继续,所以我们这个请求一切正常我们来到里面方法,然后接下来request.getParameter这个是我们嘴常见的方法,在原生的request里面它会获取请求参数,获取this.methodParam(也就是我们_method的请求参数)

    • 判断请求是否正常,并且是我们POST方式
      • 获取到_method的值
      • 还兼容PUT,DELETE,PATCH
      • 这是原生request(POST),包装模式的RequestWrapper重写了getMethod方法,返回的是传入的值,而传入的值又是从请求参数_method获取的
      • 过滤器链放行的时候用wrapper作为request放行了

    _method的值是DELETE要是按倒PUT值就是PUT,这是我们表单里面带过来的,因为他获取的是请求参数;然后他判断你的值(if (StringUtils.hasLength(paramValue)))hasLength()判断你有没有值(不是空的)不是空的以后他把你的Delete管你是不是大小写都以英文的信息给你转成大写;之后它(if (ALLOWED_METHODS.contains(method)))判断它们允许的请求方式(ALLOWED_METHODS)里面包不包含你的delete允许的请求方式:

    private static final List<String> ALLOWED_METHODS =
    			Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(),
    					HttpMethod.DELETE.name(), HttpMethod.PATCH.name()));
    

    是这样的一个集合,人家允许你给我发PUT(HttpMethod.PUT.name())DELETE(HttpMethod.DELETE.name())和PATCH(HttpMethod.PATCH.name())当然除了我们的httpGET,POST请求外还额外兼容。

    在它的范围内没问题,接下来就是requestToUse = new HttpMethodRequestWrapper(request, method);,关键核心就在这整了一个HttpMethodRequestWrapper,然后Wrapper变成了requestToUse;原来requestToUse是原生request,然后看我们HttpMethodRequestWrapper:

    public HttpMethodRequestWrapper(HttpServletRequest request, String method) {
    			super(request);
    			this.method = method;
    		}
    

    再看继承的父类``:

    public class HttpServletRequestWrapper extends ServletRequestWrapper implements HttpServletRequest {...}
    

    还是实现了原生Request请求,只不过不同的是我们这个Wrapper里面,它接收一个method传参(public HttpMethodRequestWrapper(HttpServletRequest request, String method))也就是说把我们现在新的请求方式传参传来进来然后HttpMethodRequestWrapper把新的请求方式一保存(保存到method参数里面)然后重写了HttpServletRequest 的getMethod()方法所以这块使用了一个包装模式

所以以后后来人我们这个Filter(HiddenHttpMethodFilter)一执行过,后来人相当于来到

@RequestMapping(value = "/user" , method = RequestMethod.PUT)
public String putUser(){
    return "PUT-李四";
}

来到这个方法里面,来到我们这个方法里面,这个resquest就相当于就变成了被包装了的那个类所以在那个类里面我们一放行(放行的是wrapper),以后的方法调用getMethod是调用wrapper里面requestWrapper的。requestWrapper是封装的是_method的值所以我们以后调用就是_method是什么就是什么,所以springMVC就在这里判断你的请求,它会把原生的请求拿过来,它一判断如果请求方式是DELETE就进

@RequestMapping(value = "/user" , method = RequestMethod.DELETE)
public String deleteUser(){
    return "DELETE-李四";
}

方法了,那怎么知道请求方式就是delete呢?

就正因为这个方法处理之前先过FilterFilter把原生请求的getMethod()重写了变成了delete然后在方法里面拿到了请求再来getMethod的时候已经变成delete,跟它就匹配了这就是我们Rest风格

Rest只是用来做表单的,我们如果是Rest使用我们客户端工具直接发,那就跟它没关系了。

比如我们安卓直接给我们发请求一个delete或put,哪怕我们使用postman模拟

所以

spring:
  mvc:
    hiddenmethod:
      filter:
        enabled: true

是选择性开启

学新通

我们在http层就已经不是不是post了,所以我们不会进入到转换流层直接放行,所以说是表单只能写getpost所以表单加入我们Filter就可以了,所以我们原生的方式也没有问题不影响原先的功能。

@RequestMapping(value = "/user" , method = RequestMethod.POST)这样写太麻烦了所以springMVC里面派生了新的注解(@GetMapping("/user")@PostMapping("/user")@PutMapping("/user")@DeleteMapping("/user"))


<input name="_method" type="hidden" value="PUT" />_method能不能变成自定义的名字?

怎么改变默认的_method

在原理中,也就是说springboot给容器中来放这个Filter(OrderedHiddenHttpMethodFilter)的时候它是来判断@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)(如果你容器中没有这个类型的组件,我就给你放一个),因为它放的这个组件默认用的是我们_method所以我们不如就自己给容器中放一个HiddenHttpMethodFilter

新建一个java取名随便取,比如config.WebConfig:

@Configuration(proxyBeanMethods = false)
public class WebConfig {
    @Bean
    public HiddenHttpMethodFilter hiddenHttpMethodFilter(){
        HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter();
        return methodFilter;
    }
}
@Configuration:是一个配置类

(proxyBeanMethods = false):没有依赖给它快速放

HiddenHttpMethodFilter:大家注意HiddenHttpMethodFilter的包是叫org.springframework.web.filter.HiddenHttpMethodFilter
org.springframework.web.filter.HiddenHttpMethodFilter.reactive是响应式编程用的

@Bean:给容器中一放

因为这个HiddenHttpMethodFilter它里面有一个public static final String DEFAULT_METHOD_PARAM = "_method";赋值给private String methodParam = DEFAULT_METHOD_PARAM;虽然static final是不可变的但是methodParam人家给了我们一个setMethodParam()方法所以:

@Configuration(proxyBeanMethods = false)
public class WebConfig {

    @Bean
    public HiddenHttpMethodFilter hiddenHttpMethodFilter(){
        HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter();
        methodFilter.setMethodParam("_m");
        return methodFilter;
    }
}

我来重新启动

那就要修改<input name="_method" type="hidden" value="PUT" />name要等与你写的methodFilter.setMethodParam("_m");_m值。


Rest风格(使用HTTP请求方式动词来表示对资源的操作)

  • 以前: /getUser /deleteUser /editUser /saveUser
  • 现在: /user GET-获取用户 DELETE-删除用户 PUT-修改用户 POST-保存用户

后来我们springboot应用我们最多是用来做微服务开发给人家提供接口,给我们发请求我们返回json数据所以可能都不交互页面,前后端分离页面时别人写的

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgejhci
系列文章
更多 icon
同类精品
更多 icon
继续加载