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;
    }
}
相关推荐
架构师沉默3 分钟前
程序员如何避免猝死?
java·后端·架构
Zzxy23 分钟前
快速搭建SpringBoot项目并整合MyBatis-Plus
java·spring boot
星如雨グッ!(๑•̀ㅂ•́)و✧27 分钟前
WebFlux onErrorContinue 和 onErrorResume使用详解
java·人工智能
电商API&Tina33 分钟前
电商数据采集API接口||合规优先、稳定高效、数据精准
java·javascript·数据库·python·json
zjjsctcdl1 小时前
springBoot发布https服务及调用
spring boot·后端·https
观测云1 小时前
SpringBootAI 接入观测云 MCP 最佳实践
spring boot·观测云·mcp
zdl6861 小时前
Spring Boot文件上传
java·spring boot·后端
世界哪有真情1 小时前
哇!绝了!原来这么简单!我的 Java 项目代码终于被 “拯救” 了!
java·后端
RMB Player1 小时前
Spring Boot 集成飞书推送超详细教程:文本消息、签名校验、封装工具类一篇搞定
java·网络·spring boot·后端·spring·飞书
重庆小透明2 小时前
【搞定面试之mysql】第三篇 mysql的锁
java·后端·mysql·面试·职场和发展