Spring MVC框架


Spring MVC 是 Spring 框架中用于构建 Web 应用程序的模块,基于经典的 Model-View-Controller (MVC)设计模式,它提供了灵活、强大的 Web 开发解决方案

MVC 设计模式

Model-View-Controller (MVC)C控制层,M模块层,V显示层
用于实现前端页面的展现与后端业务数据处理的分离
M:model(模型) :封装应用程序数据
V:view(视图) :渲染模型数据(JSP, Thymeleaf, FreeMarker 等)
C:controller(控制器):桥梁 处理请求并返回模型和视图

Spring MVC核心组件

1.DispatcherServlet:前端控制器,接收所有请求并协调处理流程(不需要程序员开发)
2.HandlerMapping:映射请求到对应的处理器(控制器)(不需要程序员开发)
3.Controller:处理请求并返回模型和视图(要程序员开发)
4.ViewResolver:将逻辑视图名解析为实际视图实现 (不需要程序员开发)
5.Model:封装应用程序数据(不需要程序员开发)
6.View:渲染模型数据(JSP, Thymeleaf, FreeMarker 等)(需要程序员开发 如jsp)

我从别处找了一张比较清晰的流程图
在这里插入图片描述
对应后端开发者而言,需要后端控制层的Hander的开发,古老的基于配置文件的MVC模式 现在不使用了,但是那种更直观的学习

Spring MVC 后端伪代码示例

控制器层 Controller

// ================== 控制器层 ==================
@RestController // 声明为 REST 控制器,自动将返回值转为 JSON
@RequestMapping("/api/users") // 基础路径映射
public class UserController {
	//...请求...//
}

GET 请求

1.数据传输方式:GET请求将参数包含在URL中
2.安全性:GET请求的参数暴露在URL中,容易被截获和篡改,因此安全性较低
3.数据大小限制:GET请求的参数长度通常受限于URL长度限制(通常为2048个字符)
4.缓存和历史记录处理:GET请求会被浏览器缓存,并且请求的参数会被保存在浏览器的历史记录中
5.TCP数据包数量:GET请求通常产生一个TCP数据包

    /** 获取所有用户 - GET 请求
     * @RequestParam 获取查询参数,name defaultValue 键值对的参数值
     * required=false 表示非必需
     */
    @GetMapping //get请求的注解
    public List<UserDTO> getAllUsers(
            @RequestParam(name = "page", defaultValue = "1") int page,
            @RequestParam(name = "size", defaultValue = "10") int size) {
        // 实现逻辑: 调用服务层获取分页用户列表
        return List.of(new UserDTO());
    }

@RequestParam:将请求参数绑定到controller的方法参数上,name defaultValue 键值对的参数值,可以设置required=false 表示非必需,可以同时有多个

POST 请求

1.数据传输方式:而POST请求将参数放在请求体(request body)
2.安全性:POST请求的参数在请求体中,更安全
3.数据大小限制:请求的数据大小可以通过设置Content-Length头部来控制,可以处理更大量的数据
4.缓存和历史记录处理:OST请求则不会被缓存,也不会在浏览器历史记录中保存请求参数
5.TCP数据包数量:POST请求在某些情况下可能会产生两个TCP数据包,因为POST请求需要先发送请求头,服务器响应后再发送请求体

   /**创建用户 - POST 请求
     * @RequestBody 从请求体中获取 JSON 数据并转换为 UserDTO 对象
     */
    @PostMapping
    @ResponseStatus(HttpStatus.CREATED) // 设置响应状态码为 201 Created
    public UserDTO createUser(@RequestBody UserDTO userDTO) {
        // 实现逻辑: 调用服务层创建用户
        return new UserDTO(); // 实际返回创建的用户对象
    }

@RequestBody: 限定了前端传递的参数必须为json格式,并且前端不能使用GET方式提交数据,而是用POST方式进行提交,而且@RequestBody 只能有一个。

PUT 请求

更新需要:PUT请求用于向服务器存储一个资源,如果这个资源已经存在,则替换旧文档

    /**
     * 更新用户 - PUT 请求
     * 组合使用 @PathVariable 和 @RequestBody
     */
    @PutMapping("/{id}")
    public UserDTO updateUser(
            @PathVariable Long id, 
            @RequestBody UserDTO userDTO) {
        // 实现逻辑: 调用服务层更新用户信息
        return new UserDTO();
    }

@PathVariable:用于将URL中的模板变量绑定到方法的参数上

DELETE 请求

删除需要:DELETE请求用于请求服务器删除URL指定资源

    /**删除用户 - DELETE 请求
     * 返回 ResponseEntity 可自定义响应状态
     */
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        // 实现逻辑: 调用服务层删除用户
        return ResponseEntity.noContent().build(); // 204 No Content
    }

数据传输对象层 (DTO)

// ================== 数据传输对象 (DTO) ==================
class UserDTO {
    // 使用 Lombok 的 @Data 可简化 getter/setter
    @Data
    private Long id;
    @Data
    private String username;
    @Data
    private String email;
}

@Data 注解相当于 @Getter@Setter@RequiredArgsConstructor、@ToString @EqualsAndHashCode

服务层( Service )

由Conrtoller分发到服务层 调用具体的也从场景实现业务逻辑

// ================== 服务层 ==================
@Service // 标记为 Spring 服务组件
class UserService {
    /**
     * 业务逻辑实现
     * 在这个实现过程可能需要访问数据库
     */
}

数据访问层 (Repository )

// ================== 数据访问层 ==================
@Repository // 标记为数据访问组件
interface UserRepository extends JpaRepository<User, Long> {
    // Spring Data JPA 会自动实现基本方法
    
    // 比如 自定义查询方法
    List<User> findByUsernameContaining(String keyword);
}

全局处理的控制层

上面都是正常的业务分发处理流程,但是还有日志啊 异常处理 监听啊这些和业务逻辑无关的

异常处理

@ControllerAdvice // 全局控制器增强
class GlobalExceptionHandler {
    /**处理特定异常
     * @ExceptionHandler 声明处理的异常类型
     */
    @ExceptionHandler(ResourceNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ErrorResponse handleNotFound(ResourceNotFoundException ex) {
        return new ErrorResponse(ex.getMessage());
    }

    /**
     * 处理验证异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ErrorResponse handleValidationException(MethodArgumentNotValidException ex) {
        // 处理参数验证错误
        return new ErrorResponse("Validation failed");
    }
}

@ExceptionHandler注解:使用他定义方法上,该方法用于处理特定类型的异常,这个可以处理多个
@ResponseStatus注解用于标记控制器方法或异常类,以指示HTTP响应的状态码和理由短语

自定义注解

// ================== 自定义注解 ==================
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentUser {
    // 自定义注解示例:用于获取当前登录用户
}

元注解:@Target @Retention @Documented @Inherited
元注解:注解的注解,即java为注解开发特准备的注解
@Targe表示该注解用于什么地方
@Retention :表示该注解可以保存的范围
@Documented:拥有这个注解的元素可以被javadoc此类的工具文档化
@Inherited:允许子类继承父类中的注解

但是自定义注解需要自行提供该注解的作用功能逻辑,实现机制是反射应用

自定义注解的使用样例比如

class UserDTO {
    @Data
    @CurrentUser
    private User currentUser;
} 

其余场景注解

@RequestHeader:获取请求头信息

public void process(@RequestHeader("User-Agent") String userAgent)

@Valid / @Validated:参数验证(需配合 JSR-303 验证注解)

public UserDTO create(@Valid @RequestBody UserDTO userDTO)

@CookieValue:获取 Cookie 值

public void auth(@CookieValue("sessionId") String sessionId)

顺便简单说下cookie和session 区别
存储位置Cookie的数据信息存放在客户端浏览器上。Session的数据信息存放在服务器
存储容量:单个Cookie保存的数据<=4KB,一个站点最多保存20个Cookie。对于Session来说,并没有上限,但出于对服务器端的性能考虑,Session内不要存放过多内容,并且要设置Session删除机制
安全性:Cookie对客户端是可见的,别有用心的人可以分析存放在本地的Cookie并进行Cookie欺骗,所以Cookie不安全。Session存储在服务器上,不存在敏感信息泄漏的风险,所以Session安全

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值