JSR303是做服务端校验 参数验证
1.做服务端参数校验 JSR303 的jar包依赖
-
- <groupId>org.hibernategroupId>
- <artifactId>hibernate-validatorartifactId>
- <version>6.0.7.Finalversion>
-
后台
@NotNull :作用于基本数据类型
@NotEmpty 作用于集合
@NotBlank 作用于字符串
实体类
Clazz
@NotNull(message = "cid不能为空") message 提示语句
- package com.ljj.ssm.model;
-
- import javax.validation.constraints.NotBlank;
- import javax.validation.constraints.NotNull;
-
- /**
- * @NotNull :作用于基本数据类型
- * @NotEmpty 作用于集合
- * @NotBlank 作用于字符串
- */
- public class Clazz {
- @NotNull(message = "cid不能为空")
- protected Integer cid;
-
- @NotBlank(message = "班级名称不能为空")
- protected String cname;
-
- @NotBlank(message = "教员老师不能为空")
- protected String cteacher;
-
- protected String pic;
-
- public Clazz(Integer cid, String cname, String cteacher, String pic) {
- this.cid = cid;
- this.cname = cname;
- this.cteacher = cteacher;
- this.pic = pic;
- }
-
- public Clazz() {
- super();
- }
-
- public Integer getCid() {
- return cid;
- }
-
- public void setCid(Integer cid) {
- this.cid = cid;
- }
-
- public String getCname() {
- return cname;
- }
-
- public void setCname(String cname) {
- this.cname = cname;
- }
-
- public String getCteacher() {
- return cteacher;
- }
-
- public void setCteacher(String cteacher) {
- this.cteacher = cteacher;
- }
-
- public String getPic() {
- return pic;
- }
-
- public void setPic(String pic) {
- this.pic = pic;
- }
- }
ClazzController
- /**
- * @Valid 是与实体类中的服务端校验 注解配合使用的
- * BindingResult 存放了所有违背校验的错误信息
- * @param clazz
- * @param bindingResult
- * @return
- */
- @RequestMapping("/valiAdd ")
- public String valiAdd(@Valid Clazz clazz, BindingResult bindingResult){
- if(bindingResult.hasErrors()){
- //违背了规则
- //拿到所有错误
- List
fieldErrors = bindingResult.getFieldErrors(); - for (FieldError fieldError : fieldErrors) {
- // cid : cid不能为空
- System.out.println(fieldError.getField() + ":" + fieldError.getDefaultMessage());
- }
- }else{//反之没有违背
- this.clazzBiz.insertSelective(clazz);
- }
- return "redirect:/clz/list";
- }
界面代码:
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- 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 }/clz/${empty b ? 'valiAdd' : 'edit'}" method="post">
- cid:<input type="text" name="cid" value="${b.cid }"><br>
- cname:<input type="text" name="cname" value="${b.cname }"><br>
- cteacher:<input type="text" name="cteacher" value="${b.cteacher }"><br>
- <input type="submit">
- form>
- body>
- html>
现在我们尝试直接提交:在debug后台会有错误警告
我们需要将后台的错误提示展示到文本框的后面,我们就需要完善ClazzController类 中的valiAdd方法
- /**
- * @Valid 是与实体类中的服务端校验 注解配合使用的
- * BindingResult 存放了所有违背校验的错误信息
- * @param clazz
- * @param bindingResult
- * @return
- */
- @RequestMapping("/valiAdd")
- public String valiAdd(@Valid Clazz clazz, BindingResult bindingResult,HttpServletRequest request){
- if(bindingResult.hasErrors()){//违背了规则
- Map msg=new HashMap();
- //拿到所有错误
- List
fieldErrors = bindingResult.getFieldErrors(); - for (FieldError fieldError : fieldErrors) {
- // cid : cid不能为空
- System.out.println(fieldError.getField() + ":" + fieldError.getDefaultMessage());
- //相当于 msg.put(cid,cid不能为空);
- msg.put(fieldError.getField(),fieldError.getDefaultMessage());
- }
- request.setAttribute("msg",msg);
- //如果出现了错误,应该将提示语显示在表单元素后方
- return "clzEdit";
- }else{//反之没有违背
- this.clazzBiz.insertSelective(clazz);
- }
- return "redirect:/clz/list";
- }
改进前端代码:
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- 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 }/clz/${empty b ? 'valiAdd' : 'edit'}" method="post">
- cid:<input type="text" name="cid" value="${b.cid }"><span style="color: red">${msg.cid}span><br>
- cname:<input type="text" name="cname" value="${b.cname }"><span style="color: red">${msg.cname}span><br>
- cteacher:<input type="text" name="cteacher" value="${b.cteacher }"><span style="color: red">${msg.cteacher}span><br>
- <input type="submit">
- form>
- body>
- html>
此时我们再次尝试直接提交(错误提示展示到了页面中)
总结
1.pom依赖导入
2.在待校验的数据库列段对应的实体属性打上校验标签
3.在controller层,方法上添加@valid注解配合前面的校验标签,添加bindingResult,此对象包含了所有校验未通过的错误信息
4.可以将所有的错误信息以map集合的方式保存,并且传递到前台页面展示
SpringMVC的处理器拦截器,类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理(AOP中的环绕通知)。
依赖于web框架,在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用。由于拦截器是基于
web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个
controller生命周期之内可以多次调用。
依赖于servlet容器。在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。使用过滤器的目的是用来做一些过滤操作,比如:在过滤器中修改字符编码;
在过滤器中修改HttpServletRequest的一些参数,包括:过滤低俗文字、危险字符等
2.2、拦截器与过滤器的区别
过滤器(filter):
1) filter属于Servlet技术,只要是web工程都可以使用
2) filter主要对所有请求过滤
3) filter的执行时机早于Interceptor
拦截器(interceptor):
1) interceptor属于SpringMVC技术,必须要有SpringMVC环境才可以使用
2) interceptor通常对处理器Controller进行拦截
3) interceptor只能拦截dispatcherServlet处理的请求
1)日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等。
2)权限检查:如登录检测,进入处理器检测是否登录,如果没有直接返回到登录页面;
3)性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间(如果有反向代理,如apache可以自动记录);
4)通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个Controller中的处理方法都需要的,我们就可以使用拦截器实现
1、创建HelloController
2、创建自定义拦截器并实现HandlerInterceptor接口
OneHandlerInterceptor:
- package com.ljj.ssm.intercept;
-
- import org.springframework.web.servlet.HandlerInterceptor;
- import org.springframework.web.servlet.ModelAndView;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
-
- /**
- * @author ljj
- * @site https://blog.csdn.net
- * @qq 1828190940
- * @create 2022-08-19 19:04
- */
- public class OneHandlerInterceptor implements HandlerInterceptor {
-
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- //预处理
- System.out.println("[OneHandlerInterceptor] . preHandle"+"---预处理");
- return true;
- }
-
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
- //后处理
- System.out.println("[OneHandlerInterceptor] . postHandle"+"---后处理");
-
- }
-
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
- //完成后执行
- System.out.println("[OneHandlerInterceptor] . afterCompletion"+"---完成后执行");
-
- }
- }
注意,此时preHandle 预处理方法的返回值是true
复制该类全路径进入Spring-servlet.xml进行配置
-
- <mvc:interceptors>
-
- <bean class="com.ljj.ssm.intercept.OneHandlerInterceptor">bean>
- mvc:interceptors>
创建HelloController
- package com.ljj.ssm.controller;
-
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
-
- /**
- * @author ljj
- * @site https://blog.csdn.net
- * @qq 1828190940
- * @create 2022-08-19 19:19
- */
- @Controller
- public class HelloController {
-
- @RequestMapping("/hello")
- public String hello(){
- System.out.println("进入业务方法...");
- return "index";
- }
- }
测试结论:
看向控制台,我们可以看到方法的执行顺序 ,先执行预处理->后处理->完成后执行方法
我们可以看到预处理和后处理相当于前置通知和后置通知,所以就有一个结论我们的拦截器
就相当于AOP处理
我们将preHandle 预处理方法的返回值改成false
运行结果:
控制器打印结果:
TwoHandlerInterceptor
- package com.ljj.ssm.intercept;
-
- import org.springframework.web.servlet.HandlerInterceptor;
- import org.springframework.web.servlet.ModelAndView;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
-
- /**
- * @author ljj
- * @site https://blog.csdn.net
- * @qq 1828190940
- * @create 2022-08-19 19:04
- */
- public class TwoHandlerInterceptor implements HandlerInterceptor {
-
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- //预处理
- System.out.println("[TwoHandlerInterceptor] . preHandle"+"---预处理");
- return true;
- }
-
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
- //后处理
- System.out.println("[TwoHandlerInterceptor] . postHandle"+"---后处理");
-
- }
-
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
- //完成后执行
- System.out.println("[TwoHandlerInterceptor] . afterCompletion"+"---完成后执行");
-
- }
- }
复制该类全路径进入Spring-servlet.xml进行配置
- <mvc:interceptors>
- <mvc:interceptor>
-
- <mvc:mapping path="/**/"/>
- <bean class="com.ljj.ssm.intercept.OneHandlerInterceptor"> bean>
- mvc:interceptor>
- <mvc:interceptor>
- <mvc:mapping path="/clz/**"/>
- <bean class="com.ljj.ssm.intercept.TwoHandlerInterceptor">bean>
- mvc:interceptor>
- mvc:interceptors>
运行预测结果:
当我们输入http://localhost:8080/hello 会执行OneHandle中的三个方法当我们输入http://localhost:8080/Clz/list 会执行One和Two两个接口:
首先One--->prehandle
Two------>prehandle
在执行业务方法
One---->posthandle
Two---->posthandle
One----->aftercomplation
Two------>aftercomplation
运行项目后,输入http://localhost:8080/clz/list
查看控制台: