欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 手游 > Spring Boot 整合 Spring MVC /(整合Web)笔记

Spring Boot 整合 Spring MVC /(整合Web)笔记

2025/3/1 2:06:17 来源:https://blog.csdn.net/m0_65324703/article/details/145824462  浏览:    关键词:Spring Boot 整合 Spring MVC /(整合Web)笔记

1. Spring Boot 整合 Web 功能

Spring Boot 通过自动配置简化了 Spring MVC 的集成。只需在 pom.xml 中添加 spring-boot-starter-web 依赖,Spring Boot 就会自动配置 Spring MVC 的相关组件。

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

2. Spring MVC 常用注解

2.1 控制器注解

  • @Controller: 标识一个类为 Spring MVC 控制器。

  • @RestController: 组合了 @Controller 和 @ResponseBody,用于返回 JSON或 XML 数据。

    @RestController //定义这个表示这个class是一个Controller
    public class MyController {// 方法定义
    }

2.2请求映射注解

  • 一、@RequestMapping: 用于映射 HTTP 请求到控制器方法。可以指定请求方法、路径等。

  • 1. 作用

    @RequestMapping是Spring MVC中用于映射HTTP请求到控制器方法的核心注解。它允许开发者指定请求的路径、方法类型、请求头、参数等条件,从而精确地匹配请求到特定的处理方法。

    2. 常用属性
    (1)valuepath属性
  • 作用:指定请求的路径。可以是一个字符串或字符串数组,支持路径变量和通配符。

  • 示例

    @RequestMapping("/home")
    public String home() {return "Home Page";
    }//或者@RequestMapping(path = {"/home", "/index"})
    public String home() {return "Home Page";
    }
    (2)method属性
  • 作用指定允许的HTTP请求方法(如GETPOSTPUTDELETE等)。如果不指定,默认支持所有HTTP方法。

  • 示例

    @RequestMapping(value = "/user", method = RequestMethod.GET)
    public String getUser() {return "Get User";
    }
  • (3)params属性
  • 作用:指定请求必须包含的参数。可以用于限制请求的条件。

  • 示例

    @RequestMapping(value = "/user", params = "id")
    public String getUser(@RequestParam String id) {return "User ID: " + id;
    }
    3. @RequestMapping:使用场景

    @RequestMapping是一个通用的注解,适用于需要同时支持多种HTTP方法的场景。例如:

  • @RequestMapping("/user")
    public String user(@RequestParam String action) {if ("create".equals(action)) {return "Create User";} else if ("delete".equals(action)) {return "Delete User";}return "Unknown Action";
    }

    二、@GetMapping@PostMapping@PutMapping@DeleteMapping

    这些注解是@RequestMapping的衍生注解,专门用于处理特定的HTTP方法。它们是@RequestMapping的简化形式,使代码更清晰、更易读。

  • @GetMapping: 专门用于处理 GET 请求。 等价于:@RequestMapping(method = RequestMethod.GET)

  • @PostMapping: 专门用于处理 POST 请求。等价于:@RequestMapping(method = RequestMethod.POST)

  • @PutMapping: 专门用于处理 PUT 请求。等价于:@RequestMapping(method = RequestMethod.PUT)

  • @DeleteMapping: 专门用于处理 DELETE 请求。等价于:@RequestMapping(method = RequestMethod.DELETE)

  • 例如

    @RestController
    @RequestMapping("/api/user")
    public class UserController {@GetMapping("/{id}")public User getUser(@PathVariable Long id) {return new User(id, "John Doe");}@PostMappingpublic User createUser(@RequestBody User user) {return user;}@PutMapping("/{id}")public User updateUser(@PathVariable Long id, @RequestBody User user) {user.setId(id);return user;}@DeleteMapping("/{id}")public String deleteUser(@PathVariable Long id) {return "User with ID " + id + " deleted";}
    }

  • 2.3  参数绑定注解

  • @RequestParam:绑定查询参数

    @GetMapping("/user")
    public String getUserByName(@RequestParam String name) {// 根据名称获取用户return "User Name: " + name;
    }
  • @PathVariable:绑定路径参数

    @GetMapping("/user/{id}")
    public String getUser(@PathVariable Long id) {// 根据 ID 获取用户return "User ID: " + id;
    }
  • @RequestBody:绑定请求体(JSON/XML)

    @PostMapping("/user")
    public String createUser(@RequestBody User user) {// 处理用户创建逻辑return "User created";
    }
  • @RequestHeader:获取请求头

    @GetMapping("/headers")
    public Map<String, String> getAllHeaders(@RequestHeader Map<String, String> headers) {return headers.entrySet().stream() .filter(entry -> !entry.getKey().startsWith("sec-")) .collect(Collectors.toMap(Map.Entry::getKey,  Map.Entry::getValue));
    }
  • @CookieValue:获取Cookie值

    @GetMapping("/cookie")
    public String readCookie(@CookieValue(name = "SESSION_ID", defaultValue = "guest") String sessionId,@CookieValue(value = "USER_THEME", required = false) String theme) {String response = "当前会话ID:" + sessionId;if (theme != null) {response += "<br>主题偏好:" + theme;}return response;
    }
  • 数组/集合接收:

    @PostMapping("/batchDelete")
    public void batchDelete(@RequestParam("ids") List<Long> idList) {// 接收ids=1,2,3 或 ids=1&ids=2
    }// 示例请求:/batch/1001,1002,1003 
    @GetMapping("/batch/{ids}")
    public String processBatchIds(@PathVariable("ids") List<String> idList) {return "接收ID数量:" + idList.size(); 
    }

    JSON参数绑定:

  • @PostMapping("/createUser")
    public User createUser(@RequestBody @Valid UserDTO userDTO) {// 自动将JSON转换为UserDTO对象
    }// 请求体示例:[{"name":"手机"},{"name":"电脑"}]
    @PostMapping("/products")
    public void createProducts(@RequestBody List<ProductDTO> productList) {productService.batchCreate(productList); 
    }public class OrderRequest {private List<OrderItem> items;// getter/setter 
    }@PostMapping("/orders")
    public void createOrder(@RequestBody OrderRequest request) {processItems(request.getItems()); 
    }

    多维数组参数:

    // 请求示例:/matrix;categories=手机,电脑;brands=华为,苹果 
    @GetMapping("/matrix")
    public String processMatrix(@MatrixVariable(pathVar = "matrix") Map<String, List<String>> params) {return "分类:" + params.get("categories"); 
    }

    自定义格式转换:

    @GetMapping("/custom")
    public void processCustomFormat(@RequestParam("codes") @DateTimeFormat(pattern = "yyyyMMdd") List<Date> dateList) {// 接收形如?codes=20230201,20230202的参数 
    }

    @ModelAttribute 模型数据注解:

    @PostMapping("/user")
    public String createUser(@ModelAttribute User user) {// 处理用户创建逻辑return "User created";
    }

    使用 IO 读取 POST 请求体(可以通过 HttpServletRequest 对象手动读取 POST 请求体。)

    @PostMapping("/upload")
    public String upload(HttpServletRequest request) throws IOException {InputStream inputStream = request.getInputStream();// 处理输入流return "Upload successful";
    }//读取字符串
    @PostMapping("/param/json2")
    public String p6(Reader reader) {StringBuilder content = new StringBuilder("");try (BufferedReader bin = new BufferedReader(reader)) {var line = "";while ((line = bin.readLine()) != null) {content.append(line);}} catch (IOException e) {e.printStackTrace();}return "p7, reader=" + content.toString();
    }//读取字符串
    @PostMapping("/upload")
    public String upload(HttpServletRequest request) throws IOException {StringBuilder stringBuilder = new StringBuilder();try (BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()))) {String line;while ((line = reader.readLine()) != null) {stringBuilder.append(line);}}String requestBody = stringBuilder.toString(); // 获取请求体内容System.out.println("Request Body: " + requestBody);return "Upload successful";
    }//读取二进制数据
    @PostMapping("/upload")
    public String upload(HttpServletRequest request) throws IOException {ByteArrayOutputStream buffer = new ByteArrayOutputStream();byte[] data = new byte[1024];int bytesRead;try (InputStream inputStream = request.getInputStream()) {while ((bytesRead = inputStream.read(data, 0, data.length)) != -1) {buffer.write(data, 0, bytesRead);}}byte[] requestBody = buffer.toByteArray(); // 获取请求体的字节数组System.out.println("Request Body Size: " + requestBody.length);return "Upload successful";
    }
    

2.4 请求路径设置

Spring Boot 中可以通过 application.properties 或 application.yml 文件配置应用的根路径。

#application.propertiesserver.servlet.context-path=/myapp#application.yml server:servlet:context-path: /myapp

2.5、路径通配符 

在 Spring Boot 中,使用 Spring MVC 处理 Web 请求时,确实可以通过多种方式设置请求的路径,包括使用通配符和正则表达式,下面为你详细介绍相关内容。

25.1. 通配符的使用

Spring MVC 支持两种通配符:? 和 *,另外还有一种更强大的 ** 通配符。

2.5.1.1 ? 通配符 

  ? 通配符用于匹配单个字符。示例代码:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class WildcardController {@GetMapping("/user?")public String handleUserPath() {return "This path matches URLs like /user1, /userA etc.";}
}//在上述代码中,/user? 可以匹配 /user1、/userA 等路径,
//但不能匹配 /user 或 /user12 等路径,因为 ? 只能匹配单个字符。

在上述代码中,/user? 可以匹配 /user1、/userA 等路径,但不能匹配 /user 或 /user12 等路径,因为 ? 只能匹配单个字符。

2.5.1.2 * 通配符   

 * 通配符用于匹配零个或多个字符,但不包括路径分隔符 /示例代码

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class SingleAsteriskController {@GetMapping("/user/*")public String handleUserPathWithSingleAsterisk() {return "This path matches URLs like /user/profile, /user/info etc.";}
}//这里 /user/* 可以匹配 /user/profile、/user/info 等路径,
//但不能匹配 /user/profile/subprofile,
//因为 * 不会跨路径分隔符 / 进行匹配。

这里 /user/* 可以匹配 /user/profile/user/info 等路径,但不能匹配 /user/profile/subprofile,因为 * 不会跨路径分隔符 / 进行匹配。 

2.51.3 ** 通配符 

** 通配符用于匹配零个或多个路径片段,也就是可以跨路径分隔符 / 进行匹配。示例代码

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class DoubleAsteriskController {@GetMapping("/user/**")public String handleUserPathWithDoubleAsterisk() {return "This path matches URLs like /user/profile, /user/profile/subprofile etc.";}
}// /user/** 可以匹配 /user/profile、/user/profile/subprofile 
//等任意以 /user/ 开头的路径。

 /user/** 可以匹配 /user/profile/user/profile/subprofile 等任意以 /user/ 开头的路径。

2.6. 路径正则表达式的使用

在Spring MVC中,路径变量的正则约束通过`{变量名:正则表达式}`语法实现,支持标准Java正则表达式语法。以下为典型应用场景:示例代码

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;@RestController
public class RegexController {@GetMapping("/users/{id:\\d+}")public String getUserById(@PathVariable("id") String id) {return "User ID: " + id;}
}//在上述代码中,{id:\\d+} 表示 id 这个路径变量必须是一个或多个数字。
//因此,像 /users/123 这样的请求可以匹配该方法,但 /users/abc 则无法匹配。// UUID格式验证 
@GetMapping("/documents/{uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}}")
public String getDocument(@PathVariable String uuid) {return "Document UUID: " + uuid;
}// 十六进制颜色代码 
@GetMapping("/colors/{hex:#[0-9a-fA-F]{6}}")
public String getColor(@PathVariable String hex) {return "Color code: " + hex;
}// 日期+序列号格式:20230224-ABC123 
@GetMapping("/orders/{code:\\d{8}-[A-Z]{3}\\d{3}}")
public String getOrder(@PathVariable String code) {return "Order Code: " + code;
}// 排除特殊字符的路径参数 
@GetMapping("/search/{query:[^/?*:;{}]+}")
public String search(@PathVariable String query) {return "Searching: " + query;
}// 长度+字符类型双重约束 
@GetMapping("/products/{sku:[A-Z]{2}-\\d{4}-[a-z]{3}}")
public String getProduct(@PathVariable String sku) {return "Product SKU: " + sku;
}

 在上述代码中,{id:\\d+} 表示 id 这个路径变量必须是一个或多个数字。因此,像 /users/123 这样的请求可以匹配该方法,但 /users/abc 则无法匹配。

2.7、Spring Boot 返回内容详解

在 Spring Boot 中,控制器方法的返回值决定了客户端接收到的响应内容。Spring Boot 支持多种返回类型,包括 JSON、视图、文件、重定向等。以下是对 Spring Boot 返回内容的详细说明。

1. 返回 JSON 数据

Spring Boot 默认使用 Jackson 库将 Java 对象序列化为 JSON 数据。如果控制器方法返回一个对象,Spring Boot 会自动将其转换为 JSON 格式并返回。

1.1 使用 @RestController

@RestController 是 @Controller 和 @ResponseBody 的组合注解,表示该控制器中的所有方法返回值都会直接作为响应体返回(通常是 JSON 格式)。

@RestController
public class UserController {@GetMapping("/user/{id}")public User getUser(@PathVariable Long id) {User user = new User();user.setId(id);user.setName("John");user.setAge(30);return user; // 自动转换为 JSON}
}

响应示例:

{"id": 1,"name": "John","age": 30
}
1.2 使用 @ResponseBody

如果使用 @Controller 而不是 @RestController,可以在方法上添加 @ResponseBody 注解,表示返回值直接作为响应体返回。

@Controller
public class UserController {@GetMapping("/user/{id}")@ResponseBodypublic User getUser(@PathVariable Long id) {User user = new User();user.setId(id);user.setName("John");user.setAge(30);return user; // 自动转换为 JSON}
}

2. 返回视图

Spring Boot 支持多种视图技术(如 Thymeleaf、JSP、Freemarker 等)。如果控制器方法返回一个字符串,Spring Boot 会将其解析为视图名称,并渲染对应的视图文件。

2.1 使用 @Controller

@Controller 注解表示该类是一个控制器,方法返回值会被解析为视图名称。

@Controller
public class UserController {@GetMapping("/user/{id}")public String getUser(@PathVariable Long id, Model model) {User user = new User();user.setId(id);user.setName("John");user.setAge(30);model.addAttribute("user", user); // 将数据传递给视图return "userDetail"; // 返回视图名称}
}

视图文件(userDetail.html):

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><title>User Detail</title>
</head>
<body><h1>User Information</h1><p>ID: <span th:text="${user.id}"></span></p><p>Name: <span th:text="${user.name}"></span></p><p>Age: <span th:text="${user.age}"></span></p>
</body>
</html>

 2.2 使用 ModelAndView

ModelAndView 是一个包含模型数据和视图名称的对象。

@Controller
public class UserController {@GetMapping("/user/{id}")public ModelAndView getUser(@PathVariable Long id) {User user = new User();user.setId(id);user.setName("John");user.setAge(30);ModelAndView modelAndView = new ModelAndView();modelAndView.addObject("user", user); // 添加模型数据modelAndView.setViewName("userDetail"); // 设置视图名称return modelAndView;}
}

3. 返回文件

Spring Boot 支持直接返回文件内容。可以通过 ResponseEntity 或 HttpServletResponse 实现。

 3.1 使用 ResponseEntity
@RestController
public class FileController {@GetMapping("/download")public ResponseEntity<Resource> downloadFile() throws IOException {File file = new File("path/to/file.txt");InputStreamResource resource = new InputStreamResource(new FileInputStream(file));return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getName() + "\"").contentLength(file.length()).contentType(MediaType.APPLICATION_OCTET_STREAM).body(resource);}
}
 3.2 使用 HttpServletResponse
@RestController
public class FileController {@GetMapping("/download")public void downloadFile(HttpServletResponse response) throws IOException {File file = new File("path/to/file.txt");response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getName() + "\"");Files.copy(file.toPath(), response.getOutputStream());}
}

4. 返回重定向

Spring Boot 支持通过返回 redirect: 前缀实现重定向。

@Controller
public class UserController {@PostMapping("/user")public String createUser(@ModelAttribute User user) {// 处理用户创建逻辑return "redirect:/user/" + user.getId(); // 重定向到用户详情页}
}

5. 返回自定义响应

可以通过 ResponseEntity 返回自定义的 HTTP 状态码和响应体。

@RestController
public class UserController {@GetMapping("/user/{id}")public ResponseEntity<User> getUser(@PathVariable Long id) {User user = new User();user.setId(id);user.setName("John");user.setAge(30);if (user == null) {return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null); // 返回 404}return ResponseEntity.ok(user); // 返回 200 和用户数据}
}

6. 返回纯文本

可以直接返回字符串作为纯文本响应。

@RestController
public class UserController {@GetMapping("/hello")public String sayHello() {return "Hello, World!"; // 返回纯文本}
}

 7. 返回 XML 数据

如果客户端请求的是 XML 格式,Spring Boot 会自动将对象序列化为 XML。

@RestController
public class UserController {@GetMapping(value = "/user/{id}", produces = MediaType.APPLICATION_XML_VALUE)public User getUser(@PathVariable Long id) {User user = new User();user.setId(id);user.setName("John");user.setAge(30);return user; // 返回 XML 数据}
}

 响应示例:

<user><id>1</id><name>John</name><age>30</age>
</user>

8. 返回二进制数据

可以返回字节数组或 Resource 对象作为二进制数据。

@RestController
public class ImageController {@GetMapping(value = "/image", produces = MediaType.IMAGE_JPEG_VALUE)public byte[] getImage() throws IOException {File file = new File("path/to/image.jpg");return Files.readAllBytes(file.toPath());}
}

9. 跨域支持

可以通过 @CrossOrigin 注解或在配置类中配置跨域支持。

@RestController
@CrossOrigin(origins = "http://example.com") //允许跨域请求。origins属性指定了允许发起请求的源(域)。这里只允许http://example.com域的请求访问该控制器的方法。
//如果需要允许所有域,可以设置为origins = "*",但出于安全考虑,建议限制为特定域。
public class MyController {// 方法定义
}//或者在配置类中全局配置:// 使用 @Configuration 注解标记该类为 Spring 配置类
// Spring Boot 在启动时会加载该配置类
@Configuration
public class CorsConfig implements WebMvcConfigurer {// 重写 WebMvcConfigurer 接口中的 addCorsMappings 方法// 该方法用于配置 CORS(跨域资源共享)规则@Overridepublic void addCorsMappings(CorsRegistry registry) {// 调用 registry.addMapping 方法,指定哪些路径启用 CORS 配置// "/**" 表示对所有路径启用 CORSregistry.addMapping("/**")// 设置允许跨域请求的源(域名)// 这里只允许来自 "http://example.com" 的请求跨域访问.allowedOrigins("http://example.com")// 设置允许的 HTTP 方法// 这里允许 GET、POST、PUT 和 DELETE 方法.allowedMethods("GET", "POST", "PUT", "DELETE");// 还可以继续链式调用其他方法,例如:// .allowedHeaders("*") // 允许所有请求头// .allowCredentials(true) // 允许携带凭证(如 Cookie)// .maxAge(3600); // 预检请求的缓存时间(单位:秒)}
}

 10. 总结

Spring Boot 支持多种返回类型,包括:

  • JSON 数据:通过 @RestController 或 @ResponseBody 返回。

  • 视图:通过 @Controller 返回视图名称或 ModelAndView 对象。

  • 文件:通过 ResponseEntity 或 HttpServletResponse 返回文件内容。

  • 重定向:通过 redirect: 前缀实现重定向。

  • 自定义响应:通过 ResponseEntity 返回自定义状态码和响应体。

  • 纯文本:直接返回字符串。

  • XML 数据:通过设置 produces 属性返回 XML 格式数据。

  • 二进制数据:返回字节数组或 Resource 对象。

根据业务需求选择合适的返回类型,可以极大地简化开发工作并提高代码的可读性。

2.8、数据验证与异常处理

在Spring Boot中,Java Bean Validation是一种强大的工具,用于验证域模型的属性值是否符合预期。它通过将验证规则集中到Bean对象中,实现了在一处统一控制所有验证逻辑,从而简化了Controller和Service层的代码。

注解描述
@NotNull验证元素值不为null
@Size验证字符串、集合等的大小是否在指定范围内
@Min 和 @Max验证数值是否在指定范围内
@Email验证字符串是否为合法的电子邮件地址
@Valid用于方法参数或返回值,启用级联验证
@Validated@Valid类似,但支持分组验证

1. 添加依赖 

如果使用Spring Boot Starter Web,验证依赖已经默认包含。否则,需要手动添加以下依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId>
</dependency>

 2. 定义验证规则

在Bean的属性上添加注解来定义验证规则。例如:

public class User {@NotNull(message = "用户ID不能为空") //可以在注解中直接定义错误信息:private Long id;@NotBlank(message = "用户名不能为空")@Size(min = 2, max = 20, message = "用户名长度必须在2到20之间")private String name;@Min(value = 18, message = "年龄必须大于或等于18")@Max(value = 100, message = "年龄必须小于或等于100")private int age;@Email(message = "邮箱格式不正确")private String email;// Getters and Setters
}

3. 在 Controller 中使用验证

在 Controller 中,可以通过 @Valid 注解触发 Bean 的验证逻辑。如果验证失败,Spring Boot 会自动返回错误信息。

@RestController
@RequestMapping("/users")
public class UserController {@PostMappingpublic ResponseEntity<?> createUser(@Valid @RequestBody User user, BindingResult result) {// 如果验证失败,收集错误信息到Map中if (result.hasErrors()) {Map<String, List<String>> errors = new HashMap<>();for (FieldError error : result.getFieldErrors()) {// 如果字段已经存在于Map中,追加错误信息;否则创建新的列表errors.computeIfAbsent(error.getField(), k -> new ArrayList<>()).add(error.getDefaultMessage());}return ResponseEntity.badRequest().body(errors);}// 验证通过,处理业务逻辑return ResponseEntity.ok("用户创建成功");}
}

示例:验证路径参数和查询参数

@RestController
@RequestMapping("/users")
public class UserController {@GetMapping("/{id}")public ResponseEntity<String> getUser(@PathVariable @Min(value = 1, message = "用户ID必须大于0") Long id,@RequestParam @NotBlank(message = "用户名不能为空") String name) {// 处理业务逻辑return ResponseEntity.ok("用户ID: " + id + ", 用户名: " + name);}
}

使用国际化消息 

 可以通过 messages.properties 文件定义错误信息,并支持国际化:

# messages.properties
NotEmpty.user.name=用户名不能为空
Size.user.name=用户名长度必须在2到20之间

在注解中引用消息:

@NotBlank(message = "{NotEmpty.user.name}")
@Size(min = 2, max = 20, message = "{Size.user.name}")
private String name;

分组验证

分组验证允许我们根据不同的场景应用不同的验证规则。例如,创建用户和更新用户可能需要不同的验证规则。

定义分组接口:

public interface CreateGroup {}
public interface UpdateGroup {}

在 Bean 中指定分组

public class User {@NotNull(message = "用户ID不能为空", groups = UpdateGroup.class)private Long id;@NotBlank(message = "用户名不能为空", groups = {CreateGroup.class, UpdateGroup.class})@Size(min = 2, max = 20, message = "用户名长度必须在2到20之间", groups = {CreateGroup.class, UpdateGroup.class})private String name;// Getters and Setters
}

在 Controller 中使用分组

@PostMapping("/create")
public ResponseEntity<String> createUser(@Validated(CreateGroup.class) @RequestBody User user) {// 处理业务逻辑return ResponseEntity.ok("用户创建成功");
}@PostMapping("/update")
public ResponseEntity<String> updateUser(@Validated(UpdateGroup.class) @RequestBody User user) {// 处理业务逻辑return ResponseEntity.ok("用户更新成功");
}

在 IntelliJ IDEA 中使用 HTTP 文件测试接口

IntelliJ IDEA 提供了一个非常方便的功能,可以通过编写 .http 文件来测试 RESTful 接口。这种方式非常适合在开发过程中快速验证接口的正确性,而无需依赖 Postman 或其他工具。本文将详细介绍如何在 IDEA 中使用 HTTP 文件测试接口。

1. 创建 HTTP 文件

在 IntelliJ IDEA 中,可以直接创建一个 .http 文件来编写 HTTP 请求。

1.1 创建步骤
  1. 在项目中右键点击目标目录(例如 src/test/http)。

  2. 选择 New -> File

  3. 输入文件名,例如 test-api.http

2. 编写 HTTP 请求

在 .http 文件中,可以编写多个 HTTP 请求,每个请求以 ### 分隔。以下是一个示例:

### 获取用户列表
GET http://localhost:8080/api/users
Accept: application/json### 创建用户
POST http://localhost:8080/api/users
Content-Type: application/json{"name": "John Doe","age": 30,"email": "john.doe@example.com"
}### 获取单个用户
GET http://localhost:8080/api/users/1
Accept: application/json### 更新用户
PUT http://localhost:8080/api/users/1
Content-Type: application/json{"name": "Jane Doe","age": 25,"email": "jane.doe@example.com"
}### 删除用户
DELETE http://localhost:8080/api/users/1

3. 运行 HTTP 请求

在 .http 文件中,每个请求旁边都会有一个绿色的运行按钮。点击按钮即可发送请求并查看响应。

3.1 查看响应

发送请求后,IDEA 会在右侧的 Run 工具窗口中显示响应结果,包括状态码、响应头和响应体。

例如,运行 GET http://localhost:8080/api/users 后,可能会看到如下响应:

HTTP/1.1 200 OK
Content-Type: application/json[{"id": 1,"name": "John Doe","age": 30,"email": "john.doe@example.com"},{"id": 2,"name": "Jane Doe","age": 25,"email": "jane.doe@example.com"}
]

3.Spring Boot 结合过滤器的用法

在 Spring Boot 中,过滤器(Filter)是 Java Servlet 规范的一部分,用于在请求到达 Controller 之前或响应返回客户端之前对请求和响应进行处理。过滤器通常用于实现一些通用的功能,例如日志记录、权限验证、字符编码设置等。本文将详细介绍如何在 Spring Boot 中使用过滤器。

1. 什么是过滤器?

过滤器是 Java Web 应用中的一种组件,它可以对 HTTP 请求和响应进行预处理和后处理。过滤器的主要特点包括:

  • 链式调用:多个过滤器可以形成一个过滤器链,按顺序依次处理请求和响应。

  • 灵活配置:可以指定过滤器拦截的 URL 路径。

  • 生命周期:过滤器的生命周期由 Servlet 容器管理,包括初始化、执行和销毁。

2. 实现一个简单的过滤器

在 Spring Boot 中,可以通过实现 javax.servlet.Filter 接口来创建自定义过滤器。

2.1 创建过滤器类

以下是一个简单的过滤器示例,用于记录请求的 URL 和耗时:

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;// 使用 @WebFilter 注解标记该类为过滤器
// urlPatterns 指定过滤器拦截的 URL 路径    这里的/*表示拦截所有的路径
@WebFilter(urlPatterns = "/*")
public class RequestLogFilter implements Filter {//init() 方法:在过滤器初始化时被调用,通常用于加载资源或初始化配置。
//FilterConfig 参数:提供了过滤器的初始化参数,可以通过它获取在 web.xml 或注解中配置的参数。@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// 过滤器初始化时调用System.out.println("RequestLogFilter initialized");}//doFilter() 方法:是过滤器的核心逻辑,每次请求都会调用该方法。@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {// 记录请求开始时间long startTime = System.currentTimeMillis();System.out.println("Request URL: " + request.getServletContext().getContextPath());// 继续执行过滤器链chain.doFilter(request, response);// 记录请求耗时long endTime = System.currentTimeMillis();System.out.println("Request processed in " + (endTime - startTime) + " ms");}//destroy() 方法:在过滤器销毁时被调用,通常用于清理资源。@Overridepublic void destroy() {// 过滤器销毁时调用System.out.println("RequestLogFilter destroyed");}
}

2.2 启用过滤器

如果使用 @WebFilter 注解,需要在 Spring Boot 启动类上添加 @ServletComponentScan 注解,以扫描并注册过滤器:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;@SpringBootApplication
@ServletComponentScan // 扫描并注册 @WebFilter、@WebServlet 等注解
public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);}
}

3. 使用 FilterRegistrationBean 注册过滤器

除了使用 @WebFilter 注解,还可以通过 FilterRegistrationBean 手动注册过滤器。这种方式更加灵活,可以动态配置过滤器的顺序和 URL 映射。

3.1 创建过滤器类

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;public class AuthFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("AuthFilter initialized");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {System.out.println("AuthFilter: Checking authentication");// 模拟权限验证String token = request.getParameter("token");if ("valid-token".equals(token)) {chain.doFilter(request, response); // 验证通过,继续执行过滤器链} else {response.getWriter().write("Unauthorized"); // 验证失败,返回未授权信息}}@Overridepublic void destroy() {System.out.println("AuthFilter destroyed");}
}

3.2 注册过滤器

在 Spring Boot 配置类中,使用 FilterRegistrationBean 注册过滤器:

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class FilterConfig {@Beanpublic FilterRegistrationBean<AuthFilter> authFilter() {FilterRegistrationBean<AuthFilter> registrationBean = new FilterRegistrationBean<>();registrationBean.setFilter(new AuthFilter()); // 设置过滤器实例registrationBean.addUrlPatterns("/secure/*"); // 设置拦截的 URL 路径registrationBean.setOrder(1); // 设置过滤器执行顺序return registrationBean;}
}

4. 过滤器的执行顺序

如果有多个过滤器,可以通过 FilterRegistrationBean 的 setOrder 方法设置执行顺序。值越小,优先级越高。

4.1 示例:多个过滤器的执行顺序

@Configuration
public class FilterConfig {@Beanpublic FilterRegistrationBean<RequestLogFilter> requestLogFilter() {FilterRegistrationBean<RequestLogFilter> registrationBean = new FilterRegistrationBean<>();registrationBean.setFilter(new RequestLogFilter());registrationBean.addUrlPatterns("/*");registrationBean.setOrder(2); // 第二个执行  这里的数值越小就越先执行return registrationBean;}@Beanpublic FilterRegistrationBean<AuthFilter> authFilter() {FilterRegistrationBean<AuthFilter> registrationBean = new FilterRegistrationBean<>();registrationBean.setFilter(new AuthFilter());registrationBean.addUrlPatterns("/secure/*");registrationBean.setOrder(1); // 第一个执行 这里的数值越小就越先执行return registrationBean;}
}

5. 过滤器的常见应用场景

5.1 日志记录

记录请求的 URL、参数、耗时等信息,便于调试和监控。

5.2 权限验证

在请求到达 Controller 之前,验证用户的权限或 Token。

5.3 字符编码设置

统一设置请求和响应的字符编码,避免乱码问题。

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {request.setCharacterEncoding("UTF-8");response.setCharacterEncoding("UTF-8");chain.doFilter(request, response);
}

5.4 跨域处理

在过滤器中设置响应头,支持跨域请求。

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {HttpServletResponse httpResponse = (HttpServletResponse) response;httpResponse.setHeader("Access-Control-Allow-Origin", "*");httpResponse.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");httpResponse.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");chain.doFilter(request, response);
}

6. 过滤器高级用法

6.1 使用 @Order 注解设置过滤器顺序

除了使用 FilterRegistrationBean,还可以通过 @Order 注解设置过滤器的执行顺序。 

import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;@Component
@Order(1) // 设置过滤器执行顺序
public class CustomFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("CustomFilter initialized");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {System.out.println("CustomFilter: Before chain.doFilter");chain.doFilter(request, response);System.out.println("CustomFilter: After chain.doFilter");}@Overridepublic void destroy() {System.out.println("CustomFilter destroyed");}
}

6.2 使用 OncePerRequestFilter

OncePerRequestFilter 是 Spring 提供的一个抽象类,用于确保每个请求只被过滤器处理一次。它解决了在过滤器链中可能因为请求被多次处理而导致的问题,例如在请求被转发或包含时,过滤器逻辑被重复执行。

import org.springframework.web.filter.OncePerRequestFilter;import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class CustomOncePerRequestFilter extends OncePerRequestFilter {@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {// 在调用下一个过滤器或目标资源之前执行的逻辑System.out.println("CustomOncePerRequestFilter: Before doFilter");// 调用下一个过滤器或目标资源filterChain.doFilter(request, response);// 在调用下一个过滤器或目标资源之后执行的逻辑System.out.println("CustomOncePerRequestFilter: After doFilter");}
}

 注册 OncePerRequestFilter

@Bean
public FilterRegistrationBean<CustomOncePerRequestFilter> customOncePerRequestFilter() {FilterRegistrationBean<CustomOncePerRequestFilter> registrationBean = new FilterRegistrationBean<>();registrationBean.setFilter(new CustomOncePerRequestFilter());registrationBean.addUrlPatterns("/*");return registrationBean;
}

在 Spring Boot 中使用过滤器,可以实现对请求和响应的统一处理。本文介绍了以下内容:

  • 如何通过 @WebFilter 注解创建过滤器。

  • 如何使用 FilterRegistrationBean 注册过滤器。

  • 如何设置过滤器的执行顺序。

  • 过滤器的常见应用场景。

Spring Boot 整合 Web 功能总结:

一、Spring Boot 整合 Web 功能

通过在pom.xml添加spring-boot-starter-web依赖,Spring Boot 自动配置 Spring MVC 相关组件,极大简化了 Spring MVC 的集成过程。

二、Spring MVC 常用注解

  1. 控制器注解@RestController 是 @Controller 和 @ResponseBody 的组合,用于创建返回 JSON 或其他内容的 RESTful 风格控制器。
  2. 请求映射注解
    • @RequestMapping:可指定请求方法、路径、参数等,valuepath指定路径,method指定请求方法,params根据请求参数匹配。
    • 快捷请求映射注解@GetMapping@PostMapping@PutMapping@DeleteMapping 分别对应 GET、POST、PUT、DELETE 请求,使用更简洁。
  3. 参数绑定注解
    • @RequestParam:绑定查询参数。
    • @PathVariable:绑定路径参数。
    • @RequestBody:绑定请求体(如 JSON/XML)。
    • @RequestHeader:获取请求头。
    • @CookieValue:获取 Cookie 值。
    • 数组 / 集合接收:可接收多个同名参数或 JSON 数组。
    • JSON 参数绑定:自动将 JSON 转换为对象。
    • 多维数组参数:使用@MatrixVariable处理矩阵变量。
    • 自定义格式转换:通过@DateTimeFormat等注解实现。
    • @ModelAttribute:用于将请求参数绑定到 Java 对象,并添加到模型中。
  4. 请求路径设置:在application.propertiesapplication.yml中通过server.servlet.context-path配置应用根路径。
  5. 路径通配符
    • ?通配符:匹配单个字符。
    • *通配符:匹配零个或多个字符,但不跨路径分隔符/
    • **通配符:匹配零个或多个路径片段,可跨路径分隔符/
  6. 路径正则表达式:通过{变量名:正则表达式}语法对路径变量进行正则约束,如{id:\d+}表示路径变量必须是数字。

三、Spring Boot 返回内容

  1. 返回 JSON 数据:使用@RestController@Controller + @ResponseBody,Spring Boot 默认用 Jackson 将 Java 对象序列化为 JSON。
  2. 返回视图:使用@Controller,返回字符串作为视图名,结合视图技术(如 Thymeleaf)渲染视图,也可使用ModelAndView
  3. 返回文件:通过ResponseEntityHttpServletResponse返回文件内容。
  4. 返回重定向:返回redirect:前缀实现重定向。
  5. 返回自定义响应:使用ResponseEntity返回自定义 HTTP 状态码和响应体。
  6. 返回纯文本:直接返回字符串作为纯文本响应。
  7. 返回 XML 数据:请求为 XML 格式时,Spring Boot 自动将对象序列化为 XML。
  8. 返回二进制数据:返回字节数组或Resource对象作为二进制数据。
  9. 跨域支持:通过@CrossOrigin注解或在配置类中配置跨域规则。

四、数据验证与异常处理

  1. 验证注解@NotNull@Size@Min@Max@Email@Valid@Validated等。
  2. 添加依赖:使用spring-boot-starter-validation
  3. 定义验证规则:在 Bean 属性上添加注解定义规则。
  4. 在 Controller 中使用验证:通过@Valid@Validated触发验证,用BindingResult处理错误。
  5. 国际化消息:通过messages.properties文件定义错误信息并支持国际化。
  6. 分组验证:定义分组接口,在 Bean 和 Controller 中指定分组。

五、测试接口

在 IntelliJ IDEA 中,可通过创建.http文件编写 HTTP 请求来测试 RESTful 接口,方便快捷。

六、Spring Boot 结合过滤器

  1. 过滤器概念:在请求到达 Controller 之前或响应返回客户端之前处理请求和响应,用于日志记录、权限验证等。
  2. 实现过滤器:实现javax.servlet.Filter接口,使用@WebFilter注解并在启动类添加@ServletComponentScan,或通过FilterRegistrationBean注册。
  3. 执行顺序:通过FilterRegistrationBeansetOrder方法或@Order注解设置,值越小优先级越高。
  4. 应用场景:日志记录、权限验证、字符编码设置、跨域处理等。
  5. 高级用法:使用OncePerRequestFilter确保每个请求只被过滤器处理一次。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词