SpringMVC

组件 作用 在 Spring MVC 中的对应部分
Model(模型) 负责数据处理、业务逻辑 Service 层 + DAO 层(数据库交互)
View(视图) 负责页面显示 HTMLJSPThymeleafJSON(REST API)
Controller(控制器) 负责处理用户请求 @Controller@RestController

SpringMVC

1.请求处理

1.@RequestMapping

作用:将HTTP请求映射到特定的类或方法上,帮助开发者灵活地定义处理HTTP请求的路径和行为

java 复制代码
@RestController
@RequestMapping("/api")
public class MyController {
​
    @GetMapping("/hello")
    public String sayHello() {
        return "Hello, world!";
    }
}
​
请求限定属性:
1.method:

指定支持的HTTP请求方法(GET,POST)等

2.headers:

限制请求头必须包含请求头或请求头的值

java 复制代码
@RequestMapping(value = "/test", headers = "Content-Type=application/json")
public String handleWithHeader() {
    return "Handled request with application/json header";
}
限定请求头包含Content-Type=application/json
3.params:

限定请求参数

2.@RequestBody

是Spring框架中的一个注解,用于将HTTP请求的请求体映射到Java对象中。这个注解通常用于接收客户端发送的JSON或XML数据

java 复制代码
@PostMapping("/example")
public ResponseEntity<String> processRequest(@RequestBody MyRequestBody myRequestBody) {
    // 处理从请求体中获取的数据
    return ResponseEntity.ok("数据处理成功!");
}
@RequestBody注解会自动将请求体中的JSON数据转换成MyRequestBody对象

3.@RequestParam

@RequestParam 是 Spring 框架中的一个注解,用于将 HTTP 请求中的参数绑定到控制器方法的参数上。它是处理 GET 或 POST 请求中请求参数的一种常用方式

java 复制代码
@RequestMapping("/handle02")
    public String handle02(@RequestParam("username") String name, @RequestParam("password") String pwd){
        System.out.println("username = " + name);
        System.out.println("password = " + pwd);
        return "ok";
    }通过注解获取同名参数并返回
请求限定属性:
1.value:

就是默认值,填参数名称

2.required

默认值是true 若填写required = false则是声明参数可以不存在

3.defaultValue:

添加参数的默认值,同样也意味着可以不传参数

4.@RequestHeader

@RequestHeader 是 Spring 框架中的一个注解,用于将 HTTP 请求头中的参数绑定到控制器方法的参数上。从而让我们可以获取请求头的值

请求限定属性和上面的一样

5.@CookieValue:

获取特定Cookie值

使用POJO级联封装请求参数

工作原理:

SpringMVC 会自动从请求参数(如 URL 查询参数 ?name=Wanyan&age=25 或表单提交的数据)中提取值。

如果请求中的参数名称与 POJO 的属性名称一致,SpringMVC 会将这些值绑定到对象的对应属性上。

java 复制代码
写一个POJO类Person 定义属性
@Data//主要依赖Setter和toString方法
public class Person {
    private String username;
    private String password;
    private String cellphone;
    private boolean agreement;
    private String grade;
    private Address address;
    private String[] hobby;
    private String sex;
​
    @Data
    public static
    class Address {
        private String province;
        private String city;
        private String area;
    }
}
@RequestMapping("/handle06")
    public String handle06(Person person){
        System.out.println(person);
        return "ok";
    }

使用@RequestBody封装数据

1.确保前端发送JSON数据
java 复制代码
{
    "name": "Wanyan",
    "age": 25
}
2.创建对应的java类(POJO)
复制代码
   
java 复制代码
 @RequestMapping("/handle07")
    public String handle07(@RequestBody Person person){//将Http请求的参数映射到pojo实体类中
        System.out.println(person);
        return "ok";
    }

@RequestBody主要是用来应对复杂场景,接受客户端发送的JSON格式的请求数据

使用HttpEntity封装原始请求

java 复制代码
@RestController
@RequestMapping("/example")
public class ExampleController {
​
    @PostMapping("/process")
    public ResponseEntity<String> processRequest(HttpEntity<String> httpEntity) {
        // 获取请求头
        HttpHeaders headers = httpEntity.getHeaders();
        System.out.println("Headers: " + headers);
​
        // 获取请求体
        String body = httpEntity.getBody();
        System.out.println("Body: " + body);
​
        return ResponseEntity.ok("Request processed successfully!");
    }
}

2.响应处理

1.返回Json数据

java 复制代码
@RestController
@RequestMapping("/example")
public class ExampleController {
​
    @GetMapping("/person")
    public Person getPerson() {
        Person person = new Person();
        person.setName("Wanyan");
        person.setAge(25);
        return person; // 自动转换为 JSON
    }
}

2.文件下载

java 复制代码
@RequestMapping("/download")
    public ResponseEntity<InputStreamResource> download() throws Exception {
        FileInputStream fileInputStream = new FileInputStream("C:\\Users\\chinaliao\\Documents\\微信图片_20240813134707.jpg");
        byte[] bytes = fileInputStream.readAllBytes();
​
        //1.文件名中文会乱码,解决:
        String encode = URLEncoder.encode("haaj.jpg","UTF-8");
//       2.文件太大会oom(内存溢出)
​
        InputStreamResource resource = new InputStreamResource(fileInputStream);
        return ResponseEntity.ok()
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .contentLength(fileInputStream.available())
                // 告诉浏览器, 下载的文件名
                .header("Content-Disposition", "attachment;filename=haaj.jpg")
                .body(resource);
    }

RESTful案例

CRUD操作(增删改查)

1.创建操作数据库的DAO接口

2.实现DAO接口,执行查询,插入,更新和删除等方法

3.创建Service层,调用DAO层完成数据库操作,可以整合多个DAO

4.创建Controler层,接受用户请求,调用Service层完成具体业务,与前端交互


分层的好处

1.DAO:将数据库操作集中在这一层,可以避免在控制层中编写复杂的擦汗寻SQL与疾病,保持代码的清晰性

2.Service:业务逻辑和数据访问分离,便于业务逻辑的独立开发和测试

3.Controller:接受响应,验证等操作,增强了模块化

4.总结:分层操作实现了松耦合,代码复用,拓展性强等优点

拦截器

1.拦截器的工作流程

拦截器通过实现 Spring 的 HandlerInterceptor 接口,并覆盖以下三个方法来实现:

  1. preHandle():在目标方法执行之前进行处理。如果返回 false,请求将被拦截,不会继续往后执行。

  2. postHandle():在目标方法执行后,但在渲染视图之前执行,用于操作返回数据。

  3. afterCompletion():在完成整个请求后执行(包括视图的渲染),可以进行清理工作等。

preHandle() 按注册顺序执行

postHandle()afterCompletion() 按注册顺序的反向执行

preHandle() 返回 false,后续拦截器和 Controller 不执行

afterCompletion() 总会执行(即使 preHandle() 返回 false

order() 可以调整拦截器的优先级

2.多拦截器的执行顺序

正常执行
拦截器的preHandler()返回false

3.拦截器和过滤器的区别

1.定义方式:

1.过滤器:

要实现Filter接口,在doFilter方法中写过滤操作,用chain.doFilter方法放行请求传递给下一个过滤器或目标资源,要写@WebFilter注解

2.拦截器:

自定义拦截器实现HandlerInterceptor接口,重写三个方法,配置拦截器实现WebMvcConfigurer(),重写addInterceptors()方法,传入自定义的拦截器

2.执行时机不同

过滤器:在请求进入容器后、到达Servlet之前执行;响应时在Servlet处理完后执行。

拦截器:在请求进入框架的控制器之前、之后或渲染视图前后执行,控制更贴近业务逻辑。

异常处理

1.局部异常处理

@ExceptionHandler(局部异常处理)

通常声明在Controller内部

java 复制代码
import org.springframework.web.bind.annotation.*;
​
@RestController
@RequestMapping("/test")
public class TestController {
​
    @GetMapping("/exception")
    public String exceptionTest() {
        if (true) {
            throw new IllegalArgumentException("参数错误");
        }
        return "正常返回";
    }
​
    @ExceptionHandler(IllegalArgumentException.class)
    public String handleIllegalArgumentException(IllegalArgumentException e) {
        return "捕获到异常:" + e.getMessage();
    }
}

2.全局异常处理

@ControllerAdvice+@ExceptionHandler对项目的所有Handler生效

java 复制代码
import org.springframework.web.bind.annotation.*;
​
@RestControllerAdvice
public class GlobalExceptionHandler {
​
    @ExceptionHandler(IllegalArgumentException.class)
    public String handleIllegalArgumentException(IllegalArgumentException e) {
        return "【全局】参数错误:" + e.getMessage();
    }
​
    @ExceptionHandler(Exception.class)
    public String handleException(Exception e) {
        return "【全局】服务器异常:" + e.getMessage();
    }
}

为了让异常信息统一,我们定义一个Common类来返回异常信息

java 复制代码
@Data
public class R<T> {
    private Integer code;
    private String msg;
    private T data;
    public static<T> R<T> ok(T data){
        R r = new R<>();
        r.setCode(200);
        r.setMsg("ok");
        r.setData(data);
        return r;
    }
    public static R ok(){
        R r = new R<>();
        r.setCode(200);
        r.setMsg("ok");
        return r;
    }
    public static<T> R<T> error(Integer code,String msg,Object data){
        R r = new R<>();
        r.setCode(code);
        r.setMsg(msg);
        r.setData(data);
        return r;
    }

把异常处理的返回值变成R就可以返回

SpringMVC - 数据校验

  1. 导入校验包

  2. 编写校验注解

  3. 使用 @Valid 告诉SpringMVC进行校验

  4. 编写一个全局异常处理器来处理校验异常

前端发来的数据,通常不能完全相信,要通过spring-boot-starter-validation中的约束注解来验证字符串或者集合

@NotNull: 用于校验字段是否为空(只有null)

"John"(通过) ❌ null(不通过) ✅ ""(通过)

@NotEmpty: 既用于校验字段是否为空,也检查长度是否大于零

"John"(通过) ❌ null(不通过) ❌ ""(不通过) ✅ " "(通过,因为长度大于 0)

@NotBlank:仅适用于字符串类型,会把空格去掉在判断是否为空

"John"(通过) ❌ null(不通过) ❌ ""(不通过) ❌ " "(不通过,因为去掉空格后为空)

1. 数值约束

约束注解 作用 适用类型
@Positive 必须为正数(>0 intlongdoubleBigDecimal
@PositiveOrZero 必须为正数或零(>=0 同上
@Negative 必须为负数(<0 同上
@NegativeOrZero 必须为负数或零(<=0 同上
@Min(value) 必须 value 数字类型
@Max(value) 必须 value 数字类型
@DecimalMin(value, inclusive = true/false) 必须 大于等于/大于 value BigDecimaldoublefloat
@DecimalMax(value, inclusive = true/false) 必须 小于等于/小于 value 同上
@Digits(integer, fraction) 限制整数和小数的位数 BigDecimaldoublefloat
约束类别 主要注解
通用 @NotNull@NotEmpty@NotBlank
数值 @Min@Max@Positive@Negative
字符串 @Size@Pattern
日期时间 @Past@Future
特殊格式 @Email@UUID

2.自定义校验器

java 复制代码
1.自定义注解
    import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
​
@Documented
@Constraint(validatedBy = {MyCustomValidator.class}) // 指定校验器
@Target({ElementType.FIELD, ElementType.METHOD}) // 作用范围:字段或方法
@Retention(RetentionPolicy.RUNTIME) // 运行时生效
public @interface MyCustomConstraint {
    String message() default "字段不符合要求"; // 自定义错误消息
    Class<?>[] groups() default {}; // 分组校验
    Class<? extends Payload>[] payload() default {}; // 负载信息
}
2. 实现ContraintValidator接口
    import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
​
public class MyCustomValidator implements ConstraintValidator<MyCustomConstraint, String> {
    
    @Override
    public void initialize(MyCustomConstraint constraintAnnotation) {
        // 初始化逻辑(通常不需要)
    }
​
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        // 这里自定义校验逻辑,比如判断字符串是否只包含字母
        return value != null && value.matches("^[a-zA-Z]+$");
    }
}
3. 创建实体类在要校验的数据上写自定义注解
4.在Controller中使用 @Valid 或 @Validated 触发校验。
5.在全局异常中统一处理    

接口文档

1.定义

接口文档 (API 文档)是用于描述系统提供的接口的详细说明文档。它主要用于前后端或系统之间的对接,确保不同团队可以正确理解和调用接口。

2.使用Swagger自动生成API文档

1.添加依赖

XML 复制代码
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    <version>2.5.0</version>  <!-- 适用于 Spring Boot 3.x -->
</dependency>

2.编写controller类

java 复制代码
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
​
@RestController
@RquestMapping("/user")
@Tag(name = "用户管理", description = "用户相关接口") // 分组名称
public class UserController {
​
    @PostMapping("/create")
    @Operation(summary = "创建用户", description = "用于创建新用户")
    public String createUser(@RequestBody UserDTO userDTO) {
        return "用户创建成功:" + userDTO.getUsername();
    }
​
    @GetMapping("/{userId}")
    @Operation(summary = "查询用户", description = "根据用户ID查询用户信息")
    public String getUser(@PathVariable int userId) {
        return "用户:" + userId;
    }
}
相关推荐
奋进的小暄4 分钟前
贪心算法(5)(java)k次取反后最大化的数组和
java·算法·贪心算法
chenchihwen12 分钟前
ITSM统计分析:提升IT服务管理效能 实施步骤与操作说明
java·前端·数据库
小杨4041 小时前
springboot框架项目应用实践六(参数校验validation基础)
spring boot·后端·架构
java技术小馆1 小时前
责任链模式如何减少模块之间的耦合
java·数据库·设计模式·责任链模式
大溪地C1 小时前
Spring Boot3整合Knife4j(4.5.0)
java·数据库·spring boot
Java&Develop1 小时前
java项目springboot 项目启动不了解决方案
java·开发语言·spring boot
飞奔的马里奥2 小时前
30天学习Java第四天——JVM规范
java·jvm·学习
₁ ₀ ₂ ₄3 小时前
深入理解 Reactor Netty 线程配置及启动命令设置
java·开发语言
花千树-0103 小时前
J-LangChain - Agent - 编排一个 ReAct + Function Call 反应链
java·gpt·langchain·prompt·github·aigc·ai编程
m0_663234013 小时前
springboot3整合knife4j详细版,包会!(不带swagger2玩)
java