当前位置: 首页 > news >正文

【SpringMVC】JSR303与拦截器的使用

文章目录

  • 一、JSR303
    • 1.1 JSR303是什么
    • 1.2 JSR 303的好处包括
    • 1.3 常用注解
    • 1.4 实例
      • 1.4.1 导入JSR303依赖
      • 1.4.2 规则配置
      • 1.4.3 编写校验方法
      • 1.4.4 编写前端
  • 二、拦截器
    • 2.1 拦截器是什么
    • 2.2 拦截器与过滤器的区别
    • 2.3.应用场景
    • 2.4 快速入门
    • 2.5.拦截器链
    • 2.6 登录拦截权限案例
      • 2.6.1 LoginController.java
      • 2.6.2 配置拦截器
      • 2.6.3 创建拦截器
      • 2.6.4 测试

一、JSR303

1.1 JSR303是什么

JSR 303是Java规范请求(Java Specification Request)的编号,它定义了Java Bean验证的标准规范。JSR 303的全称是Bean Validation,它提供了一种在Java应用程序中进行数据验证的机制。

Bean Validation是一种基于注解的验证框架,它允许开发人员在Java Bean的属性上添加验证规则,以确保数据的合法性和完整性。通过使用Bean Validation,开发人员可以在数据输入阶段就捕获错误,避免后续可能出现的潜在问题。

1.2 JSR 303的好处包括

  1. 简化验证逻辑:通过使用注解,开发人员可以在Java Bean的属性上直接添加验证规则,而不需要编写繁琐的验证代码。
  2. 统一验证规范:JSR303定义了一组常用的验证注解,使得不同的开发人员在验证过程中可以使用相同的规范,提高了代码的可读性和可维护性。
  3. 提高代码质量:通过在Java Bean中添加验证规则,可以在数据输入阶段就捕获错误,避免了后续可能出现的潜在问题。
  4. 可扩展性:JSR303提供了自定义注解的能力,开发人员可以根据自己的需求定义新的验证注解。

1.3 常用注解

  1. @NotNull:用于验证属性值不能为null。
  2. @Size:用于验证字符串、集合或数组的大小是否在指定范围内。
  3. @Min:用于验证数字属性的最小值。
  4. @Max:用于验证数字属性的最大值。
  5. @Pattern:用于验证字符串属性是否符合指定的正则表达式。
  6. @Email:用于验证字符串属性是否符合电子邮件格式。
  7. @NotBlank:用于验证字符串属性是否非空且长度大于0。
  8. @NotEmpty:用于验证字符串、集合或数组属性是否非空。
  9. @Range:用于验证数字属性是否在指定范围内。
  10. @Valid:用于嵌套验证,验证关联对象。

1.4 实例

1.4.1 导入JSR303依赖

<!-- JSR303 -->
<hibernate.validator.version>6.0.7.Final</hibernate.validator.version><!-- JSR303 -->
<dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>${hibernate.validator.version}</version>
</dependency>

1.4.2 规则配置

package com.xqx.model;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;@Data//相当于set get toString方法
@AllArgsConstructor //有参构造器
@NoArgsConstructor //无参构造器
public class Book{@NotBlank(message = “书本信息不能为空!")private String bookName;@NotNull(message = “书本价格不能为空!")private Float bookPrice:private String bookType;}

1.4.3 编写校验方法

  /*** 书本新增* 请求路径 SSM/book/editBook* @param book* @return*/@RequestMapping("/addBook")public String addBook(@Validated Book book, BindingResult bindingResult){System.out.println("进入新增方法");//判断是否验证成功if(bindingResult.hasErrors()){System.out.println("验证失败");//验证失败return "book/addBook";}else {//验证成功bookService.insert(book);return "redirect:queryBookPage";}}/***  @ModelAttribute: 所标记的方法为非请求处理方法,在所有请求方法之前被调用*  @odelAttribute 在所有的@RequestMapping的方法之前被调用!**  作用:数据预加载*  特点:无返回值*/@ModelAttributepublic void init(Model model){System.out.println("非请求处理方法");//必须操作model.addAttribute("book",new Book());}

1.4.4 编写前端

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="fmt" uri="http://www.springframework.org/tags/form" %>
<html>
<head><%@include file="/common/head.jsp"%><title>Title</title>
</head>
<style>.cl{color: red;}</style>
<body>
<h1>书本新增</h1><fmt:form modelAttribute="book"  action="${ctx}/book/addBook" method="post"><label>书本名称:</label><input type="text" name="bookName"><fmt:errors cssClass="cl" path="*"/><br/><label>书本价格:</label><input type="text" name="bookPrice"><%--<fmt:errors cssClass="cl"  path="bookPrice"/>--%><br/><label>书本类型:</label><select name="bookType"><option value="神话">神话</option><option value="教育">教育</option><option value="文学">文学</option><option value="玄幻">玄幻</option></select><br/><input type="submit" value="添加"></fmt:form></body>
</html>

在这里插入图片描述

二、拦截器

2.1 拦截器是什么

SpringMVC的处理器拦截器,类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。依赖于web框架,在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用。由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。

2.2 拦截器与过滤器的区别

拦截器(Interceptor)通常是指一种拦截和处理请求的组件或模块。它可以在请求到达目标之前或之后进行拦截,并对请求进行修改、记录或处理。拦截器通常用于实现横切关注点(cross-cutting concerns),如日志记录、安全认证、性能监控等。拦截器可以在应用程序的不同层级中使用,例如在网络层、业务逻辑层或数据访问层。

过滤器(Filter)则是一种用于过滤和处理数据的组件或模块。它可以在数据流经过时对数据进行过滤、转换或处理。过滤器通常用于对数据进行预处理或后处理,以满足特定的需求或要求。常见的应用包括数据清洗、数据转换、数据压缩等。过滤器可以在不同的数据处理环节中使用,例如在输入输出流、数据库查询、图像处理等。

2.3.应用场景

  • 日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等。
  • 权限检查:如登录检测,进入处理器检测是否登录,如果没有直接返回到登录页面;
  • 性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间(如果有反向代理,如apache可以自动记录);
  • 通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个Controller中的处理方法都需要的,我们就可以使用拦截器实现。

2.4 快速入门

创建拦截器

package com.xqx.interceptor;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*
1. 定义拦截器类,实现HandlerInterceptor接口
2. 注意当前类必须受Spring容器控制*/
public class OneInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("【OneInterceptor】:preHandle...");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("【OneInterceptor】:postHandle...");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("【OneInterceptor】:afterCompletion...");}
}

配置拦截器

在spring-mvc.xml中配置:

    <!--配置拦截器--><mvc:interceptors><bean class="com.xqx.interceptor.OneInterceptor"></bean></mvc:interceptors>

2.5.拦截器链

如果多个拦截器能够对相同的请求进行拦截,则多个拦截器会形成一个拦截器链,主要理解拦截器链中各个拦截器的执行顺序。拦截器链中多个拦截器的执行顺序,根拦截器的配置顺序有关,先配置的先执行。

在spring-mvc.xml中配置多个拦截器

    <!--2) 多拦截器(拦截器链)--><mvc:interceptors><mvc:interceptor><!--拦截所有--><mvc:mapping path="/**"/><bean class="com.xqx.interceptor.OneInterceptor"/></mvc:interceptor><mvc:interceptor><!--拦截users下的controller--><mvc:mapping path="/book/**"/><bean class="com.xqx.interceptor.TwoInterceptor"/></mvc:interceptor></mvc:interceptors>

使用了拦截器链的效果
在这里插入图片描述

2.6 登录拦截权限案例

2.6.1 LoginController.java

package com.xqx.controller;import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpSession;@Controller
public class LoginController {/*** 跳转到登录页面* @return*/@RequestMapping("tologin")public String toLogin(){return "login";}/*** 登录方法* @param username 账号* @param password 密码* @return*/@RequestMapping("/userLogin")public String userLogin(String username, String password, HttpSession session, Model model){if("admin".equals(username)|| password.equals("123")){session.setAttribute("username",username);//这里的"/"是跳转的@RequestMapping配置的值return "redirect:/";}model.addAttribute("msg","账号或者密码错误");return "login";}/*** 安全退出* @param session* @return*/@RequestMapping("/userLogout")public String userLogout(HttpSession session){//清空sessionsession.invalidate();return "redirect:tologin";}}

2.6.2 配置拦截器

<mvc:interceptors><bean class="com.xqx.interceptor.LoginInterceptor"></bean>
</mvc:interceptors>

2.6.3 创建拦截器

package com.xqx.interceptor;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//获取请求路径String url = request.getRequestURI();System.out.println(url);//判断是否是跳转登录页面的请求 放行if(url.indexOf("/tologin")>0)return true;//判断是否是用户登录 放行if(url.indexOf("/userLogin")>0)return true;//获取sessionHttpSession session = request.getSession();//获取session中的用户对象String username = (String) session.getAttribute("username");//判断session中的用户对象是否存在,存在放行,不存在跳转登录页面if(username!=null)return true;request.setAttribute("msg","您还没有登录,请登录!");request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);return false;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
}

2.6.4 测试

账号密码错误的情况下
在这里插入图片描述
在未登录的情况下访问首页
在这里插入图片描述

相关文章:

【SpringMVC】JSR303与拦截器的使用

文章目录 一、JSR3031.1 JSR303是什么1.2 JSR 303的好处包括1.3 常用注解1.4 实例1.4.1 导入JSR303依赖1.4.2 规则配置1.4.3 编写校验方法1.4.4 编写前端 二、拦截器2.1 拦截器是什么2.2 拦截器与过滤器的区别2.3.应用场景2.4 快速入门2.5.拦截器链2.6 登录拦截权限案例2.6.1 L…...

Qt案例-编译阿里云OSS对象存储C++ SDK源码,并进行简单下载,上传数据,显示进度等相关功能

项目中用到了阿里云OSS对象存储来保存数据&#xff0c;由于以前没用过这个库&#xff0c;就下载了C版的sdk源码重新编译了一次&#xff0c;并使用Qt调用&#xff1b;不得不说这可能是我编译源码最轻松的一次。 目录标题 简述OSS图形化管理工具编译源码Qt 添加引用常用 Endpoint…...

JAVA异常输出到控制台

在处理异常时&#xff0c;可以根据情况选择使用 e.getMessage()、e.toString() 或 e.printStackTrace() 来获得或打印异常相关信息。 e.printStackTrace() 是 Java 中用于打印异常堆栈跟踪信息的方法。当出现异常时&#xff0c;可以调用 e.printStackTrace() 将异常信息输出到控…...

html5学习笔记23-vue 简略学习,未完

https://www.runoob.com/vue3/vue3-tutorial.html Vue.js是一套构建用户界面的渐进式框架。Vue 只关注视图层&#xff0c; 采用自底向上增量开发的设计。 https://unpkg.com/vuenext https://unpkg.com/vue3.2.36/dist/vue.global.js <script src"https://cdn.staticf…...

【Fiddler】mac m1 机器上使用 fiddler 抓取接口

mac m1 机器上使用 fiddler 抓取接口&#xff08;非虚拟机模式&#xff09; author: jwensh date:2023.09.12 文章目录 mac m1 机器上使用 fiddler 抓取接口&#xff08;非虚拟机模式&#xff09;1. 环境准备2. 进行配置3. 使用情况 1. 环境准备 想要抓取 mac 上浏览器的接口&a…...

Swift如何使用Vision来识别获取图片中的文字(OCR),通过SwiftUI视图和终端命令行,以及一系列注意事项

在过去的一年里&#xff0c;我发现苹果系统中的“文字搜图片”功能非常好用&#xff0c;这个功能不光 iPhone/iPad&#xff0c;Mac 也有&#xff0c;找一些图片真的很好用。但是遇到了一个问题&#xff1a;这个功能需要一段时间才能找到新的图片&#xff0c;而且没法手动刷新&a…...

c++ 学习 之 常函数 和 常对象

前言 常函数 成员函数后加 const 我们可以称这个函数为 常函数 常函数内不可以修改成员属性 成员属性声明时加关键字 mutable 后&#xff0c;在常函数中依然可以修改 常对象 常对象 声明对象前加 const 称该对象为常对象 常对象只能调用常函数 正文 常函数 class Person…...

LLM - 批量加载 dataset 并合并

目录 一.引言 二.Dataset 生成 1.数据样式 2.批量加载 ◆ 主函数调用 ◆ 基础变量定义 ◆ 多数据集加载 3.数据集合并 ◆ Concat ◆ interleave ◆ stopping_strategy ◆ interleave_probs 三.总结 一.引言 LLM 模型基于 transformer 进行训练&#xff0c;需要先…...

Debian 初始化命令备忘

本文地址&#xff1a;blog.lucien.ink/archives/541 以 Debian 11 为例&#xff0c;主要用于备忘。 deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye main contrib non-free deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-updates main contrib non…...

二维矩阵的DFS算法框架

二维矩阵的DFS算法框架 关于岛屿的相似题目&#xff1a; 岛屿数量 – 二维矩阵的dfs算法封闭岛屿数量 – 二维矩阵的dfs算法统计封闭岛屿的数目统计子岛屿不同岛屿的数量 # 二叉树遍历框架 def traverse(root):if not root:return # 前序遍历traverse(root.left)# 中序遍历t…...

pytest实现日志按用例输出到指定文件中

场景 执行自动化用例时&#xff0c;希望日志按用例生成一个文件&#xff0c;并且按用例所在文件生成目录&#xff0c;用例失败时便于查看日志记录 实现方式 pytest.ini文件 在pytest.ini配置文件中设置配置项&#xff08;定义日志输出级别和格式&#xff09; log_clitrue l…...

程序员面试逻辑题

红白帽子推理 答案&#xff1a; 这个题有点像数学归纳法&#xff0c;就是假设有 A A A和 B B B两个人是黑色的帽子&#xff0c;这样的话第一次开灯&#xff0c; A A A看到 B B B是黑色的&#xff0c;其他人都是白色的&#xff0c;那么 A A A会觉得 B B B是那个黑色的&#xff0…...

自动创建设备节点udev机制实现

自动创建设备节点udev机制实现过程&#xff1a; 1.当插入设备&#xff0c;内核会向udev发送一个事件&#xff0c;其中包含着设备的信息。 2.udev会根据收到的设备信息匹配相应的规则文件。 3.udev会根据规则文件中的配置&#xff0c;创建一个唯一的设备节点文件。通常存储在/d…...

目标检测YOLO实战应用案例100讲-基于小样本学习和空间约束的濒危动物目标检测

目录 前言 相关技术介绍 2.1 卷积神经网络 2.1.1 基本结构 2.1.2 网络训练...

苹果数据恢复软件:Omni Recover Mac

Omni Recover是一款十分实用的Mac数据恢复软件&#xff0c;为用户提供了简单、安全、快速和高效的数据恢复服务。如果您遇到了Mac或iOS设备中的数据丢失和误删情况&#xff0c;不要着急&#xff0c;不妨尝试一下Omni Recover&#xff0c;相信它一定会给您带来惊喜。 首先&…...

树回归CART

之前线性回归创建的模型需要拟合所有的样本点&#xff0c;但数据特征众多&#xff0c;关系复杂时&#xff0c;构建全局模型就很困难。之前构建决策树使用的算法是ID3。 ID3 的做法是每次选取当前最佳的特征来分割数据&#xff0c;并按照该特征的所有可能取值来切分。也就是说&…...

zemax色差与消色差

色差&#xff0c;颜色像差 轴向色差&#xff1a;不同波长的光束通过透镜后焦点位于沿轴的不同位置 垂轴色差&#xff1a;每个波长成像的放大率不同 单透镜为例&#xff1a; 输入需要设置为多波长 观察光线光扇图&#xff1a; 不同波长的光之间差异较大&#xff08;不同颜色…...

成绩定级脚本(Python)

成绩评定脚本 写一个成绩评定的python脚本&#xff0c;实现用户输入成绩&#xff0c;由脚本来为成绩评级&#xff1a; #成绩评定脚本.pyscoreinput("please input your score:") if int(score)> 90:print("A") elif int(score)> 80:print("B&…...

骨传导耳机的危害有哪些?会损害听力吗?

如果正常的使用&#xff0c;骨传导耳机是没有危害的&#xff0c;由于骨传导耳机独特的传声方式&#xff0c;所以并不会对人体造成损伤&#xff0c;还可以在一定程度上保护听力。 如果想更具体知道骨传导耳机有什么危害&#xff0c;就要先了解什么是骨传导耳机&#xff0c;骨传…...

Redis模块二:缓存分类 + Redis模块三:常见缓存(应用)

缓存大致可以分为两大类&#xff1a;1&#xff09;本地缓存 2&#xff09;分布式缓存 目录 本地缓存 分布式缓存 常见缓存的使用 本地缓存&#xff1a;Spring Cache 分布式缓存&#xff1a;Redis 本地缓存 本地缓存也叫单机缓存&#xff0c;也就是说可以应⽤在单机环…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来&#xff0c;实在找不到&#xff0c;希望有大佬教一下我。 还有就会议时间&#xff0c;我感觉不是图片时间&#xff0c;因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...

MySQL 8.0 事务全面讲解

以下是一个结合两次回答的 MySQL 8.0 事务全面讲解&#xff0c;涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容&#xff0c;并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念&#xff08;ACID&#xff09; 事务是…...

Python Einops库:深度学习中的张量操作革命

Einops&#xff08;爱因斯坦操作库&#xff09;就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库&#xff0c;用类似自然语言的表达式替代了晦涩的API调用&#xff0c;彻底改变了深度学习工程…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践

作者&#xff1a;吴岐诗&#xff0c;杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言&#xff1a;融合数据湖与数仓的创新之路 在数字金融时代&#xff0c;数据已成为金融机构的核心竞争力。杭银消费金…...

python打卡第47天

昨天代码中注意力热图的部分顺移至今天 知识点回顾&#xff1a; 热力图 作业&#xff1a;对比不同卷积层热图可视化的结果 def visualize_attention_map(model, test_loader, device, class_names, num_samples3):"""可视化模型的注意力热力图&#xff0c;展示模…...

stm32进入Infinite_Loop原因(因为有系统中断函数未自定义实现)

这是系统中断服务程序的默认处理汇编函数&#xff0c;如果我们没有定义实现某个中断函数&#xff0c;那么当stm32产生了该中断时&#xff0c;就会默认跑这里来了&#xff0c;所以我们打开了什么中断&#xff0c;一定要记得实现对应的系统中断函数&#xff0c;否则会进来一直循环…...