当前位置: 首页 > ops >正文

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

     <form action="/users/1" method="post">

       <input type="hidden" name="_method" value="PUT">

       <!-- 其他表单内容 -->

       <input type="submit" value="更新用户">

     </form>

     ```

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

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <title>Restful Form</title>

</head>

<body>

<form action="/users/1" method="post">

    <input type="hidden" name="_method" value="PUT">

    <!-- 更新用户信息 -->

    <input type="submit" value="更新用户">

</form>

<form action="/users/1" method="post">

    <input type="hidden" name="_method" value="DELETE">

    <!-- 删除用户 -->

    <input type="submit" value="删除用户">

</form>

</body>

</html>

```

## 四、总结

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

http://www.xdnf.cn/news/9256.html

相关文章:

  • 机器学习知识体系:从“找规律”到“做决策”的全过程解析
  • 走进黑盒:SQL 是如何在数据库中执行的?
  • Linux基础命令掌握-cut命令
  • 0527漏洞原理:SQL注入笔记
  • CSRF和XSS攻击防御指南
  • 院校机试刷题第十三天:代码随想录算法训练营第七天
  • 调不好分布式锁?HarmonyOS + Redis 分布式锁失效排查全路径
  • Oracle20200714GI_PSU补丁流程及问题收集
  • 一种比较精简的协议
  • python学习day30
  • SSTable(Sorted String Table)结构与用途详解
  • 数据类型(基本类型)day2
  • C-内存函数,动态内存
  • Qt布局连续添加控件
  • Web3怎么本地测试连接以太坊?
  • 封装文档核心知识点总结(通俗版)
  • 利用 MkDocs 和 GitHub 部署个人博客网页
  • LINUX安装运行jeelowcode后端项目(命令行)
  • 【运维自动化-标准运维】如何实现在不同步骤间传递参数
  • 人该怎样活着呢?54
  • 随机模拟专题:第一课
  • 5G网络切片技术:开启网络服务定制化新时代
  • SpringMVC注解、@Controller注解和@RestController注解的区别、@RequestMapper、@PathVariable
  • 制作一款打飞机游戏59:子弹生成
  • DeepSeek 赋能智能安防:从算法革新到场景落地的全解析
  • 4月报 | SeaTunnel支持TDengine的多表Sink功能
  • 机器学习算法-- K 近邻算法(KNN)
  • Linux 资源限制(进程级,用户级,系统级)
  • Debian 11 之使用hostapd与dnsmasq进行AP设置
  • 欧拉定理:若 gcd(a,n)=1,则 a^φ(n)≡1(mod n)。