REST使用与原理

REST使用与原理,第1张

REST使用与原理

文章目录
        • 表单提交发送PUT和DELETe请求
        • IDEA模拟HTTP请求

本篇和RESTFul与RESTFul案例这篇文章有很多重复的地方,就当是复习吧。

表单提交发送PUT和DELETE请求

REST(Representational State Transfer,表述性状态转移)是一种架构风格,它使用HTTP请求方式动词表示对资源的 *** 作。

具体看下面的例子吧。

  1. 新建Spring项目:demo3。
    新建时添加3个依赖:Lombok、Spring Configuration Processor和SpringWeb。
    项目新建好后,自动生成的pom.xml如下所示。
    另外,将自动生成的配置文件application.properties重命名为application.yml。


    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.6.2
         
    
    com.example
    demo3
    0.0.1-SNAPSHOT
    demo3
    Demo project for Spring Boot
    
        1.8
    
    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.springframework.boot
            spring-boot-configuration-processor
            true
        
        
            org.projectlombok
            lombok
            true
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
                
                    
                        
                            org.projectlombok
                            lombok
                        
                    
                
            
        
    


  1. com.example.boot下新建控制器类controller.Demo3Controller。
package com.example.boot.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class Demo3Controller {

    @RequestMapping(value = "/user",method = RequestMethod.GET)
    public String get(){
        return "get user";
    }

    @RequestMapping(value = "/user",method = RequestMethod.POST)
    public String post(){
        return "add user";
    }

    @RequestMapping(value = "/user",method = RequestMethod.PUT)
    public String put(){
        return "update user";
    }

    @RequestMapping(value = "/user",method = RequestMethod.DELETE)
    public String delete(){
        return "delete user";
    }
}
  1. resources.static下新建欢迎页面index.html。



    
    首页


  
  
  
  


  1. 启动应用,访问localhost:8080。

点击按钮REST-GET,表单method设置为get,返回“查询用户”,OK;
点击按钮REST-POST,表单method设置为post,返回“新增用户”,OK;
点击按钮REST-PUT表单method设置为put,返回“新增用户”,NOK
点击按钮REST-POST表单method设置为delete,返回“新增用户”,NOK
由于表单method仅支持get和post方法,如果method设置为其他请求方式,如本例中的put或delete,浏览器会当作get请求方式处理。

要想使用表单发送put或delete请求,需要借助过滤器HiddenHttpMethodFilter,其源码如下,

public class HiddenHttpMethodFilter extends OncePerRequestFilter {
    private static final List 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;
        }
    }
}

做好以下两点就行:
1)表单的method设置为post。

 

2)发送给服务器的数据必须包括名为_method,值为put或delete的这么一个数据,可用input[type=“hidden”]实现。


按照以上思路修改index.html,修改后的结果如下,




    
    首页


  
  
  
  


另外,还有很重要的一点,那就是需要在配置文件application.yml中添加以下内容,以启用HiddenHttpMethodFilter。

spring:
  mvc:
    hiddenmethod:
      filter:
        enabled: true

想知道为啥,到spring-boot-autoconfigure-2.6.2.jar的org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration里看看了。

public class WebMvcAutoConfiguration {

    public WebMvcAutoConfiguration() {
    }

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

需要满足两个条件,OrderedHiddenHttpMethodFilter实例才会添加到容器中 。
1)@ConditionalOnMissingBean({HiddenHttpMethodFilter.class}) ,条件:类路径下有HiddenHttpMethodFilter。
Ctrl+N,输入OrderedHiddenHttpMethodFilter,可找到,所以满足条件。
2) @ConditionalOnProperty( prefix = "spring.mvc.hiddenmethod.filter", name = {"enabled"} ),条件:配置文件中需要配置spring.mvc.hiddenmthod.filter.enable,且为true或者on。

最后,重启应用,查看效果。

刚刚提到,表单要发送put或delete请求,发送给服务器的数据必须包括名为_method,值为put或delete的这么一个数据,通常用来实现。其实,不一定非得name="_method",也可以是name="_mymethod或者其他,也就是说,可以自定义。具体怎么自定义,还得回到HiddenHttpMethodFilter的源码。

public class HiddenHttpMethodFilter extends OncePerRequestFilter {
	//...
    private String methodParam = "_method";

    public void setMethodParam(String methodParam) {
        Assert.hasText(methodParam, "'methodParam' must not be empty");
        this.methodParam = methodParam;
    }
    //...
}   

在com.example.boot下新建配置类config.MyConfig,如下,

package com.example.boot.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.HiddenHttpMethodFilter;

@Configuration
public class MyConfig {
    @Bean
    public HiddenHttpMethodFilter hiddenHttpMethodFilter(){
        HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
        hiddenHttpMethodFilter.setMethodParam("_mymethod");
        return hiddenHttpMethodFilter;
    }
}

同时修改index.html,将name="_method"修改为name=_mymethod,如下。


重启应用,访问localhost:8080,验证结果,符合预期。

IDEA模拟HTTP请求

使用IDEA发送HTTP请求,不需要使用HiddenHttpMethodFilter,不信瞧瞧。
首先修改application.yml把HiddenHttpMethodFilter关闭,如下。

spring:
  mvc:
    hiddenmethod:
      filter:
        enabled: off

然后,在demo3项目根目录下新建目录http,在http下新建文件demo3.http,内容如下。

GET http://localhost:8080/user
Content-Type: application/json
###

POST http://localhost:8080/user
Content-Type: application/json
###

PUT http://localhost:8080/user
Content-Type: application/json
###

DELETE http://localhost:8080/user
Content-Type: application/json

最后,重启应用,发送请求。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5684906.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存