“JSR303和拦截器在Java Web开发中的应用与实践“
目录
- 引言
- JSR303
- 什么是JSR303?
- 为什么要使用JSR303?
- 常用注解
- 快速入门JSR303
- 拦截器
- 什么是拦截器
- 拦截器与过滤器
- 应用场景
- 快速入门拦截器
- 总结
引言
在Java Web开发过程中,我们经常会遇到需要对输入数据进行验证和处理,同时需要对请求进行拦截与控制的需求。为了方便实现这些功能,我们可以使用JSR303验证框架和拦截器技术。本篇博客将介绍JSR303和拦截器的基本概念,并探讨它们在Java Web开发中的应用与实践。
JSR303
什么是JSR303?
JSR303是一项Java标准规范,也被称为Bean Validation,它提供了一组注解和API用于对JavaBean属性进行验证。通过使用JSR303,我们可以在不编写繁琐的验证逻辑代码的情况下,实现对表单数据的验证和处理。JSR303使得验证过程更加简单和可读,并且是一种广泛应用于Java Web开发中的验证框架。
为什么要使用JSR303?
使用JSR303可以提供以下好处:
- 简化验证逻辑:通过使用JSR303的注解,我们可以直接在JavaBean属性上添加验证规则,使得验证逻辑更加清晰和简洁。
- 提高可维护性:将验证规则与业务逻辑分离,使得验证规则可以独立于业务逻辑进行修改和扩展,提高了代码的可维护性。
- 提供统一验证框架:JSR303是Java标准规范,被广泛应用于Java Web框架中,使用JSR303可以使得不同的Web框架之间的验证方式保持一致,提高了协作的效率。
常用注解
在JSR303中,有许多常用的注解用于实现验证功能,包括:
- @NotNull:用于标记属性不能为空。
- @Size:用于指定属性的长度范围。
- @Pattern:用于指定属性的正则表达式验证规则。
- @Min:用于指定属性的最小值。
- @Max:用于指定属性的最大值。
其他还有很多注解,可以根据具体需求选择合适的注解进行使用。
快速入门JSR303
以下是使用JSR303进行表单验证的快速入门示例:
实体类
package com.yuan.model;import lombok.ToString;import javax.validation.constraints.NotBlank;@ToString
public class Student {@NotBlank(message = "编号不能为空")private String sid;@NotBlank(message = "名字不能为空")private String sname;@NotBlank(message = "年龄不能为空")private String sage;@NotBlank(message = "性别不能为空")private String ssex;public Student(String sid, String sname, String sage, String ssex) {this.sid = sid;this.sname = sname;this.sage = sage;this.ssex = ssex;}public Student() {super();}public String getSid() {return sid;}public void setSid(String sid) {this.sid = sid;}public String getSname() {return sname;}public void setSname(String sname) {this.sname = sname;}public String getSage() {return sage;}public void setSage(String sage) {this.sage = sage;}public String getSsex() {return ssex;}public void setSsex(String ssex) {this.ssex = ssex;}
}
}
后台校验
// 给数据添加服务端校验@RequestMapping("/valiAdd")public String valiAdd(@Validated Student student, BindingResult result, HttpServletRequest req){
// 如果服务端验证不通过,有错误if(result.hasErrors()){
// 服务端验证了实体类的多个属性,多个属性都没有验证通过List<FieldError> fieldErrors = result.getFieldErrors();Map<String,Object> map = new HashMap<>();for (FieldError fieldError : fieldErrors) {
// 将多个属性的验证失败信息输送到控制台System.out.println(fieldError.getField() + ":" + fieldError.getDefaultMessage());map.put(fieldError.getField(),fieldError.getDefaultMessage());}req.setAttribute("errorMap",map);}else {this.studentBiz.insertSelective(student);return "redirect:list";}return "stu/edit";}
JSP页面
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title></title>
</head>
<body>
<form action="${pageContext.request.contextPath }/${empty s ? 'student/valiAdd' : 'student/edit'}" method="post">学生编号:<input type="text" name="sid" value="${s.sid }"><span style="color: red">${errorMap.sid}</span><br>学生姓名:<input type="text" name="sname" value="${s.sname }"><span style="color: red">${errorMap.sname}</span><br>学生年龄:<input type="text" name="sage" value="${s.sage }"><span style="color: red">${errorMap.sage}</span><br>学生性别:<input type="text" name="ssex" value="${s.ssex }"><span style="color: red">${errorMap.ssex}</span><br><input type="submit">
</form>
</body>
</html>
页面效果

通过在JavaBean的属性上添加注解,我们可以指定验证规则。在上述示例中,使用了注解表示该属性不能为空,注解表示该属性的长度范围是2到20之间,注解表示该属性的值必须符合正则表达式"[a-zA-Z0-9]+"。在实际使用中,我们可以通过调用验证器来验证数据是否符合规则。@NotNull@Size@Pattern
拦截器
什么是拦截器
拦截器是Java Web开发中常见的一种技术,它允许在请求到达目标资源之前或之后对请求进行处理。拦截器可以拦截请求和响应,并在处理过程中对它们进行修改和控制。拦截器在开发过程中具有广泛的应用,用于实现身份验证、日志记录、性能监控等功能。
拦截器与过滤器
虽然拦截器和过滤器在功能上有一些相似之处,但它们在实现方式和应用场景上有所不同。
- 过滤器是基于Servlet规范的,它通过在web.xml文件中配置,并作用于整个应用或者特定的URL模式。过滤器可以在请求到达目标资源之前或之后进行处理,但其处理方式是基于Servlet API的。过滤器通常用于请求和响应的预处理和后处理。
- 拦截器是基于Java反射机制的,它通常与特定的框架或技术相关联,比如Spring框架。拦截器可以更加细粒度地进行控制,可以通过在配置文件或注解中添加拦截器的方式来指定拦截的目标资源。
应用场景
拦截器在Java Web开发中具有广泛的应用场景,包括但不限于以下几个方面:
- 身份验证和权限控制:拦截器可以用于验证用户的身份,并对用户的访问权限进行控制,以确保只有具备相应权限的用户可以访问受限资源。
- 日志记录:拦截器可以用于记录请求和响应的日志信息,包括请求参数、处理时间、返回结果等,便于后期的问题排查和系统分析。
- 参数处理和转换:拦截器可以在请求到达目标资源之前对请求参数进行处理和转换,使得目标资源能够更加方便地获取到需要的数据。
- 性能监控:拦截器可以用于统计和监控系统的性能指标,例如请求处理时间、访问频率等,以便及时发现潜在的性能问题。
快速入门拦截器
以下是使用拦截器进行身份验证和权限控制的快速入门示例:
- 1.拦截器链
package com.yuan.interceptor;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;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...");}
}
package com.yuan.interceptor;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class TwoInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("【TwoInterceptor】:preHandle...");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("【TwoInterceptor】:postHandle...");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("【TwoInterceptor】:afterCompletion...");}
}
<mvc:interceptors><!--2) 多拦截器(拦截器链)--><mvc:interceptor><!--这个是拦截所有的--><mvc:mapping path="/**"/><bean class="com.yuan.interceptor.OneInterceptor"/></mvc:interceptor><mvc:interceptor><!--这个是只拦截/studnt路径下所有的--><mvc:mapping path="/student/**"/><bean class="com.yuan.interceptor.TwoInterceptor"/></mvc:interceptor></mvc:interceptors>
- 2.登录
登录拦截器
package com.yuan.interceptor;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("【implements】:preHandle...");StringBuffer url = request.getRequestURL();if (url.indexOf("/login") > 0 || url.indexOf("/logout") > 0){// 如果是 登录、退出 中的一种return true;}
// 代表不是登录,也不是退出
// 除了登录、退出,其他操作都需要判断是否 session 登录成功过String uname = (String) request.getSession().getAttribute("uname");if (uname == null || "".equals(uname)){response.sendRedirect("/page/login");return false;}return true;}@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 {}
}
Login Web层
package com.yuan.web;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;@Controller
public class LoginController {@RequestMapping("/login")public String login(HttpServletRequest req){String uname = req.getParameter("uname");HttpSession session = req.getSession();if ("yh".equals(uname)){session.setAttribute("uname",uname);}return "redirect:/student/list";}@RequestMapping("/logout")public String logout(HttpServletRequest req){req.getSession().invalidate();return "redirect:/student/list";}
}
login.jsp
<%--Created by IntelliJ IDEA.User: yuanhDate: 2023/9/11Time: 18:38To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
<a href="/login?uname=yh">登录</a>
</body>
</html>
配置拦截器
<mvc:interceptors><bean class="com.yuan.interceptor.LoginInterceptor"></bean></mvc:interceptors>
以我的代码为例,如果登录点击进去携带的参数不为空并且为yh就可以进入主界面,如果不是就会被拦截一直在登录界面
总结
本篇博客介绍了JSR303在这里插入代码片验证框架和拦截器技术在Java Web开发中的应用与实践。通过使用JSR303,我们可以简化表单验证逻辑,并提高代码的可维护性。拦截器则可以用于实现身份验证、日志记录、性能监控等功能,提升系统的安全性和可观测性。通过深入掌握和灵活应用JSR303和拦截器,我们可以更好地开发出高质量的Java Web应用。
希望本篇博客能够帮助你对JSR303和拦截器有更深入的理解,并能在实际项目中应用它们来提升开发效率和代码质量。
相关文章:
“JSR303和拦截器在Java Web开发中的应用与实践“
目录 引言JSR303什么是JSR303?为什么要使用JSR303?常用注解快速入门JSR303 拦截器什么是拦截器拦截器与过滤器应用场景快速入门拦截器 总结 引言 在Java Web开发过程中,我们经常会遇到需要对输入数据进行验证和处理,同时需要对请求进行拦截与控制的需…...
第六章 图 六、最小生成树(Prim算法、Kruskal算法)
一、定义 对于一个带权连通无向图G(V,E),生成树不同,每棵树的权(即树中所有边上的权值之和)也可能不同。设R为G的所有生成树的集合,若T为R中边的权值之和最小的生成树,则T称为G的最小生成树(Minimum-Spanning-Tree, MST)。 二、手…...
机器学习笔记 - 什么是 MLOps?
什么是 MLOps? Machine learning operations (MLOps) 作为一个新兴领域,MLOps 在数据科学家、机器学习工程师和人工智能爱好者中迅速崛起。MLOps 代表机器学习操作。MLOps 是机器学习工程的核心功能,专注于简化将机器学习模型投入生产、然后维护和监控的过程。MLOps 是一种…...
初阶扫雷(超详解)
✨博客主页:小钱编程成长记 🎈博客专栏:C语言小游戏 🎈推荐相关博文:初阶三子棋(超详解) 初阶扫雷 1.游戏介绍2.基本思路3.实现前的准备4.实现步骤4.1 打印菜单4.2 初始化扫雷棋盘4.3 打印扫雷棋…...
计算机视觉CV:1000字总结介绍
目录 1.CV计算机视觉 2.计算机视觉的应用 3.计算机视觉的基本技术 4.计算机视觉的发展趋势 1.CV计算机视觉 计算机视觉(Computer Vision, CV)是指通过计算机技术模拟人类视觉,让计算机能够“看”懂和理解图像和视频。计算机视觉发展了多…...
JavaScript 之 Symbol 数据类型
一、简介 symbol类型是ES6新引入的一种基本数据类型,该类型具有静态属性和静态方法。其中静态属性暴露了几个内建的成员对象,静态方法暴露了全局的symbol注册。 symbol类型具有以下特点:① 唯一性:每个symbol值都是唯一的…...
在Docker中运行PostgreSQL数据库
1.下载Docker 2.设置DockerHub账号 3.运行Docker并下载Image 4.启动PostgreSQL Image 5.连接到数据库运行SQL docker run --name some-postgres -p 5432:5432 -e POSTGRES_PASSWORDmysecretpassword -d postgres 开放端口从Docker容器到主操作系统,这将允许我们…...
实现Spring Boot集成MyBatis
引言 在Java开发中,Spring Boot和MyBatis是非常常用的框架。Spring Boot是一个快速开发应用程序的框架,而MyBatis是一个持久化框架,可以方便地操作数据库。本文将介绍如何使用Idea集成Spring Boot和MyBatis,并创建一个简单的示例…...
关于算法的时间复杂度(度量算法执行时间的两种方法、渐进时间复杂度、时间复杂度的几个性质、渐进估算、常见的渐进时间复杂度排序)
目录 度量算法执行时间的两种方法 事后统计法(Post Hoc Analysis): 事前统计法(Pre Hoc Analysis): 渐进时间复杂度 时间复杂度的几个性质 渐进估算 常见的渐进时间复杂度排序 度量算法执行时间的两…...
SpringBoot项目--电脑商城【显示商品详情功能】
1.持久层[Mapper] 1规划需要执行的SQL语句 根据商品id显示商品详情的SQL语句 SELECT * FROM t_product WHERE id?2 设计接口和抽象方法 在ProductMapper接口中添加抽象方法 /*** 根据商品id查询商品详情* param id 商品id* return 匹配的商品详情,如果没有匹配…...
VLAN笔记
虚拟VLAN 什么是VLAN VLAN的作用 VLAN的优缺点 VLAN的配置方法 VLAN有哪些接口模式 access与trunk接口的区别 Hybrid接口 拓扑实验enspCiscoH3C 什么是VLAN VLAN(Virtual Local Area Network)又称虚拟局域网,是指在交换局域网的基础上&a…...
分类算法系列⑤:决策树
目录 1、认识决策树 2、决策树的概念 3、决策树分类原理 基本原理 数学公式 4、信息熵的作用 5、决策树的划分依据之一:信息增益 5.1、定义与公式 5.2、⭐手动计算案例 5.3、log值逼近 6、决策树的三种算法实现 7、API 8、⭐两个代码案例 8.1、决策树…...
前端面试(基础)
一、CSS 1.说一下CSS的盒模型。 在HTML页面中的所有元素都可以看成是一个盒子 盒子的组成:内容content、内边距padding、边框border、外边距margin 盒模型的类型: 标准盒模型 margin border padding content IE盒模型 margin content(border…...
element-ui switch开关组件二次封装,添加loading效果,点击时调用接口后改变状态
先看效果: element-ui中的switch开关无loading属性(在element-plus时加入了),而且点击时开关状态就会切换,这使得在需要调用接口后再改变开关状态变得比较麻烦。 思路:switch开关外包一层div,给…...
【GAN小白入门】Semi-Supervised GAN 理论与实战
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊🚀 文章来源:K同学的学习圈子论文原文:Semi-Supervised Learning with Generative Adversarial Networks.pdf在学习GAN的时候你有没有想过这样一个问题呢,如果我们生成的图像是带有标签的,例如数…...
Python自动化测试(1)-自动化测试及基本技术手段概述
生产力概述 在如今以google为首的互联网时代,软件的开发和生产模式都已经发生了变化, 在《参与感》一书提到:某位从微软出来的工程师很困惑,微软在google还有facebook这些公司发展的时候,为何为感觉没法有效还击&…...
小程序中如何查看会员的余额和变更记录
通过查看会员的余额和变更记录,可以帮助商家更好地管理会员资金,提供更好的服务和用户体验。下面将介绍小程序中如何查看会员的余额以及余额的变更记录。 1. 找到指定的会员卡。在管理员后台->会员管理处,找到需要查看余额和记录的会员…...
【项目经验】elementui--table表格自定义表头及bug
一.思路 首先我们肯定得循环表头,我们原生js封装的表格的实现原理就是这样。其次我们要把自己循环的label显示出来,对应的prop也要和表格数据相对应。用div标签循环都会出现错误(div里面套column),大家不要踩坑。第一…...
flink实现kafka、doris精准一次说明
前言说明:本文档只讨论数据源为kafka的情况实现kafka和doris的精准一次写入 flink的kafka连接器已经实现了自动提交偏移量到kafka,当flink中的数据写入成功后,flink会将这批次数据的offset提交到kafka,程序重启时,kafka中记录了当前groupId消费的offset位置,开始消费时将…...
【git】git commit、push之前自动执行脚本
可以使用 Git 的钩子(hooks)功能。Git 钩子是在特定事件发生时执行自定义脚本的方式。 下面是一个使用 pre-commit 钩子的例子,用于在执行 git commit 之前自动执行脚本: 进入你的 Git 仓库的根目录。进入 .git/hooks 目录&…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...
【Kafka】Kafka从入门到实战:构建高吞吐量分布式消息系统
Kafka从入门到实战:构建高吞吐量分布式消息系统 一、Kafka概述 Apache Kafka是一个分布式流处理平台,最初由LinkedIn开发,后成为Apache顶级项目。它被设计用于高吞吐量、低延迟的消息处理,能够处理来自多个生产者的海量数据,并将这些数据实时传递给消费者。 Kafka核心特…...
