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

news2025/2/25 15:44:30

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");
        }
    
        @PostMapping
        public 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.properties

server.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}")
    @ResponseBody
    public 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(跨域资源共享)规则
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // 调用 registry.addMapping 方法,指定哪些路径启用 CORS 配置
        // "/**" 表示对所有路径启用 CORS
        registry.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 {

    @PostMapping
    public 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 或注解中配置的参数。

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 过滤器初始化时调用
        System.out.println("RequestLogFilter initialized");
    }

//doFilter() 方法:是过滤器的核心逻辑,每次请求都会调用该方法。
    @Override
    public 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() 方法:在过滤器销毁时被调用,通常用于清理资源。
    @Override
    public 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 {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("AuthFilter initialized");
    }

    @Override
    public 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"); // 验证失败,返回未授权信息
        }
    }

    @Override
    public 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 {

    @Bean
    public 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 {

    @Bean
    public FilterRegistrationBean<RequestLogFilter> requestLogFilter() {
        FilterRegistrationBean<RequestLogFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new RequestLogFilter());
        registrationBean.addUrlPatterns("/*");
        registrationBean.setOrder(2); // 第二个执行  这里的数值越小就越先执行
        return registrationBean;
    }

    @Bean
    public 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 {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("CustomFilter initialized");
    }

    @Override
    public 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");
    }

    @Override
    public 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 {
    @Override
    protected 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确保每个请求只被过滤器处理一次。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2304946.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[特殊字符]清华大学:DeepSeek从入门到精通.pdf(清华领航,驾驭DeepSeek,开启AI新境界)

不愧是清华大学出品的deepseek手册&#xff0c;简直是新手 福音&#xff0c;非常实用&#xff01; 这份《DeepSeek&#xff1a;从入门到精通》手册从基础到高 阶&#xff0c;手把手教你玩转DeepSeek&#xff0c;特别适合刚入门的小白&#xff0c;拿来就能用&#xff01; 1.Deep…

深度学习技术全景图:从基础架构到工业落地的超级进化指南

&#x1f50d; 目录导航 基础架构革命训练优化秘技未来战场前瞻 &#x1f9e9; 一、基础架构革命 1.1 前馈神经网络&#xff08;FNN&#xff09; ▍核心结构 import torch.nn as nnclass FNN(nn.Module):def __init__(self):super().__init__()self.fc1 nn.Linear(784, 25…

PyTorch-基础(CUDA、Dataset、transforms、卷积神经网络、VGG16)

PyTorch-基础 环境准备 CUDA Toolkit安装&#xff08;核显跳过此步骤&#xff09; CUDA Toolkit是NVIDIA的开发工具&#xff0c;里面提供了各种工具、如编译器、调试器和库 首先通过NVIDIA控制面板查看本机显卡驱动对应的CUDA版本&#xff0c;如何去下载对应版本的Toolkit工…

IO/网络IO基础全览

目录 IO基础CPU与外设1. 程序控制IO&#xff08;轮询&#xff09;2. 中断中断相关知识中断分类中断处理过程中断隐指令 3. DMA&#xff08;Direct Memory Access&#xff09; 缓冲区用户空间和内核空间IO操作的拷贝概念传统IO操作的4次拷贝减少一个CPU拷贝的mmap内存映射文件(m…

【DeepSeek-R1背后的技术】系列十一:RAG原理介绍和本地部署(DeepSeekR1+RAGFlow构建个人知识库)

【DeepSeek-R1背后的技术】系列博文&#xff1a; 第1篇&#xff1a;混合专家模型&#xff08;MoE&#xff09; 第2篇&#xff1a;大模型知识蒸馏&#xff08;Knowledge Distillation&#xff09; 第3篇&#xff1a;强化学习&#xff08;Reinforcement Learning, RL&#xff09;…

鸿蒙开发深入浅出04(首页数据渲染、搜索、Stack样式堆叠、Grid布局、shadow阴影)

鸿蒙开发深入浅出04&#xff08;首页数据渲染、搜索、Stack样式堆叠、Grid布局、shadow阴影&#xff09; 1、效果展示2、ets/pages/Home.ets3、ets/views/Home/SearchBar.ets4、ets/views/Home/NavList.ets5、ets/views/Home/TileList.ets6、ets/views/Home/PlanList.ets7、后端…

【数据结构】B树家族详解:B树、B+树、B*

一、B树(B-Tree) 1. 定义 B树是一种平衡多路查找树,自平衡的树,能够保持数据有序,设计目标是为减少磁盘I/O次数。适用于需要频繁读写磁盘的场景(如数据库、文件系统)。 2、B树基本性质 节点键值数量限制: 对于 m 阶 B 树,根节点至少有 1 个键值,最多有 m - 1 个…

C语言数据结构—二叉树的链式结构实现

目录 1、建立二叉树 1.1 二叉树的结构 1.2 手动建立二叉树 2、二叉树的遍历 2.1 二叉树的三种遍历方式 2.1.1 前序遍历 2.1.2 中序遍历 2.1.2 后序遍历 3、求二叉树的结点数和二叉树的高度 3.1 求二叉树结点数 3.2 求二叉树叶子结点 3.3 求二叉树第k层结点的个数 …

Java 大视界 —— Java 大数据在智能零售动态定价策略中的应用实战(98)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

危化品经营单位安全管理人员的职责及注意事项

危化品经营单位安全管理人员肩负着保障经营活动安全的重要责任&#xff0c;以下是其主要职责及注意事项&#xff1a; 职责 1. 安全制度建设与执行&#xff1a;负责组织制定本单位安全生产规章制度、操作规程和生产安全事故应急救援预案&#xff0c;确保这些制度符合国家相关法…

Day 49 卡玛笔记

这是基于代码随想录的每日打卡 1143. 最长公共子序列 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 &#xff0c;返回 0 。 一个字符串的 子序列 是指这样一个新的字符串&#xff1a;它是由原字符串在不改变…

WebXR教学 01 基础介绍

什么是WebXR&#xff1f; 定义 XR VR AR Web上使用XR技术的API WebXR 是一组用于在 Web 浏览器中实现虚拟现实&#xff08;VR&#xff09;和增强现实&#xff08;AR&#xff09;应用的技术标准。它由 W3C 的 Immersive Web 工作组开发&#xff0c;旨在提供跨设备的沉浸式体验…

DeepSeek+Kimi生成高质量PPT

DeepSeek与Kimi生成PPT全流程解析 一、工具分工原理 DeepSeek核心作用&#xff1a;生成结构化PPT大纲&#xff08;擅长逻辑构建与内容优化&#xff09;Kimi核心作用&#xff1a;将文本转换为视觉化PPT&#xff08;提供模板库与排版引擎&#xff09; 二、操作步骤详解 1. 通…

clickhouse--表引擎的使用

表引擎决定了如何存储表的数据。包括&#xff1a; 数据的存储方式和位置&#xff0c;写到哪里以及从哪里读取数据。(默认是在安装路径下的 data 路径)支持哪些查询以及如何支持。&#xff08;有些语法只有在特定的引擎下才能用&#xff09;并发数据访问。索引的使用&#xff0…

tauri输入js脚本的方法和注意事项initialization_script

注入js脚本最常用的就是initialization_script&#xff0c;通过这个方法注入的js脚本在页面每个页面都会执行&#xff0c;这个在tauri文档也可以搜到&#xff1a;WebviewWindowBuilder in tauri::webview - Rust&#xff0c;但是请注意&#xff0c;这个方法只能用在WindowBuild…

基于springboot的学习社区博客

一、系统架构 前端&#xff1a;html | bootstarp | jquery | css | ajax 后端&#xff1a;springboot | mybatis 环境&#xff1a;jdk1.8 | mysql | maven 二、代码及数据 三、功能介绍 01. web端-注册 02. web端-登录 03. web端-首页 04. web端-文章明…

python-leetcode 42.验证二叉搜索树

题目&#xff1a; 给定二叉树的根节点root,判断是否是一个有效二叉搜索树 有效二叉搜索树&#xff1a; 1.节点的左子树只包含小于当前节点的树 2.节点的右子树只包含大于当前节点的树 3.所有左子树和右子树自身必须也是二叉搜索树 方法一&#xff1a;递归 如果该二叉树的…

基于PSO-LSTM长短期记忆神经网络的多分类预测【MATLAB】

一、研究背景与意义 在时间序列分类、信号识别、故障诊断等领域&#xff0c;多分类预测任务对模型的时序特征捕捉能力提出了极高要求。传统LSTM网络虽能有效建模长程依赖关系&#xff0c;但其性能高度依赖超参数的选择&#xff0c;例如隐含层神经元数量、学习率、迭代次数等。…

拓扑排序的核心算法:BFS应用与实践

目录 一、拓扑排序简介 二、BFS解决拓扑排序的步骤 三、C实现 四、代码解释 五、总结 一、拓扑排序简介 拓扑排序是对有向无环图&#xff08;DAG&#xff09;进行排序的一种方法&#xff0c;使得对于图中的每一条有向边 (u, v)&#xff0c;u 在排序中总是位于 v 的前面。拓…

Cocos Creator Shader入门实战(一):材质和Effect的了解

引擎版本&#xff1a;3.8.5 环境&#xff1a; Windows 简介 在Cocos Creator中&#xff0c;游戏炫彩缤纷的效果是借助着色器(Shader)来实现的。 Cocos主要基于OpenGL ES&#xff0c;而Shader的编写则是在可编程渲染管线中基于修改&#xff1a;顶点着色器(Vertex) 和 片段着色…