26、请求处理-【源码分析】-Rest映射及源码解析

26、请求处理-【源码分析】-Rest映射及源码解析

# 请求处理 - Rest映射及源码解析

## 一、什么是Restful风格

Restful是一种软件架构风格,它强调使用HTTP协议对资源进行操作,通过不同的HTTP请求方法(如GET、POST、PUT、DELETE等)来表示对资源的不同操作:

- **GET**:获取资源

- **POST**:创建新资源

- **PUT**:更新资源(整体更新)

- **DELETE**:删除资源

相比传统的URL风格,Restful风格更加简洁、清晰,例如:

- 传统风格:

  - `/getUser?id=1`:获取用户信息

  - `/deleteUser?id=1`:删除用户

- Restful风格:

  - `/users/1`:GET表示获取用户信息,DELETE表示删除用户

## 二、Spring Boot中的Rest映射实现

在Spring Boot中,支持Restful风格的请求映射主要依赖于`HiddenHttpMethodFilter`过滤器。

### 1. 原理概述

由于HTML表单仅支持GET和POST请求,为了实现PUT和DELETE等请求,需要采用以下方式:

1. **表单使用POST方法**

2. **添加隐藏域**

   - 在表单中添加一个名为`_method`的隐藏域,其值为实际的请求方法(如PUT、DELETE)。

   - 示例:

     ```html

     

       

       

       

     

     ```

3. **过滤器处理**

   - `HiddenHttpMethodFilter`拦截所有POST请求。

   - 检查请求中是否存在名为`_method`的参数。

   - 如果存在,将请求方法替换为`_method`的值,从而将POST请求转换为PUT或DELETE等请求。

### 2. 源码分析

#### (1)`HiddenHttpMethodFilter`的作用

`HiddenHttpMethodFilter`的核心代码如下:

```java

public class HiddenHttpMethodFilter extends OncePerRequestFilter {

    // ...省略部分代码...

    @Override

    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        HttpServletRequest wrappedRequest = request;

        // 判断请求是否为POST,且存在_method参数

        if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {

            String paramValue = request.getParameter(this.methodParam);

            if (StringUtils.hasLength(paramValue)) {

                // 将请求包装为新的HttpServletRequest对象,重写getMethod方法

                wrappedRequest = new HttpMethodRequestWrapper(request, paramValue);

            }

        }

        // 继续执行过滤器链

        filterChain.doFilter(wrappedRequest, response);

    }

    // ...省略部分代码...

}

```

#### (2)Spring Boot的自动配置

在`WebMvcAutoConfiguration`类中,Spring Boot自动配置了`HiddenHttpMethodFilter`:

```java

@Configuration(proxyBeanMethods = false)

@ConditionalOnWebApplication(type = Type.SERVLET)

@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })

@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)

@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,

        ValidationAutoConfiguration.class })

public class WebMvcAutoConfiguration {

    // ...省略部分代码...

    @Bean

    @ConditionalOnMissingBean(HiddenHttpMethodFilter.class)

    @ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled", matchIfMissing = true)

    public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {

        return new OrderedHiddenHttpMethodFilter();

    }

    // ...省略部分代码...

}

```

- **条件配置**:

  - `@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)`:当容器中不存在`HiddenHttpMethodFilter`时才自动配置。

  - `@ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled", matchIfMissing = true)`:默认开启,可以通过`spring.mvc.hiddenmethod.filter.enabled`配置项关闭。

## 三、使用示例

### 1. 控制器方法

```java

@RestController

@RequestMapping("/users")

public class UserController {

    @GetMapping("/{id}")

    public User getUser(@PathVariable Long id) {

        // 获取用户信息

    }

    @PostMapping

    public User createUser(@RequestBody User user) {

        // 创建新用户

    }

    @PutMapping("/{id}")

    public User updateUser(@PathVariable Long id, @RequestBody User user) {

        // 更新用户信息

    }

    @DeleteMapping("/{id}")

    public void deleteUser(@PathVariable Long id) {

        // 删除用户

    }

}

```

### 2. 表单示例

```html

   

    Restful Form

   

   

   

   

   

   

```

## 四、总结

通过`HiddenHttpMethodFilter`,Spring Boot实现了对Restful风格请求的支持,使得在表单中也能发送PUT、DELETE等请求。理解其原理和配置方式,有助于在实际开发中更好地应用Restful API设计。

你可能感兴趣的:(spring,boot,后端,架构,log4j,java)