SpringMvc第五战-【SpringMvcJSR303和拦截器】

news2024/11/25 2:50:28

前言:

小编阐述了springmvc 中的文件下载,以及jrebel的使用和文件下载以及多文件下载!

在本次小编将会介绍JSR303的概念,应用场景和在具体实例的使用;和拦截器的应用

一.JSR303的介绍

1.什么是JSR303?

JSR是Java Specification Requests的缩写,意思是Java 规范提案。是指向JCP(Java Community Process)提出新增一个标准化技术规范的正式请求。任何人都可以提交JSR,以向Java平台增添新的API和服务。JSR已成为Java界的一个重要标准。 JSR-303 是JAVA EE 6 中的一项子规范,叫做Bean Validation,Hibernate Validator 是 Bean Validation 的参考实现 . Hibernate Validator 提供了 JSR 303 规范中所有内置 constraint(约束) 的实现,除此之外还有一些附加的 constraint。

2.为什么要使用JSR303?

前端不是已经校验过数据了吗?为什么我们还要做校验呢,直接用不就好了?草率了,假如说前端代码校验没写好又或者是对于会一点编程的人来说,直接绕过前端发请求(通过类似Postman这样的测试工具进行非常数据请求),把一些错误的参数传过来,你后端代码不就危险了嘛。

并且验证数据是一项常见任务,它发生在从表示层到持久层的所有应用程序层中。通常在每一层都实现相同的验证逻辑,这既耗时又容易出错。为了避免重复这些验证,开发人员经常将验证逻辑直接捆绑到域模型中,将域类与验证代码混在一起,而验证代码实际上是关于类本身的元数据

所以我们一般都是前端一套校验,后端在一套校验,这样安全性就能够大大得到提升了。

3.常用注解

注解说明
@Null用于验证对象为null
@NotNull用于对象不能为null,无法查检长度为0的字符串
@NotBlank只用于String类型上,不能为null且trim()之后的size>0
@NotEmpty用于集合类、String类不能为null,且size>0。但是带有空格的字符串校验不出来
@Size用于对象(Array,Collection,Map,String)长度是否在给定的范围之内
@Length用于String对象的大小必须在指定的范围内
@Pattern用于String对象是否符合正则表达式的规则
@Email用于String对象是否符合邮箱格式
@Min用于Number和String对象是否大等于指定的值
@Max用于Number和String对象是否小等于指定的值
@AssertTrue用于Boolean对象是否为true
@AssertFalse用于Boolean对象是否为false

@Validated与@Valid区别

@Validated:

  • Spring提供的

  • 支持分组校验

  • 可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上

  • 由于无法加在成员属性(字段)上,所以无法单独完成级联校验,需要配合@Valid

@Valid:

  • JDK提供的(标准JSR-303规范)

  • 不支持分组校验

  • 可以用在方法、构造函数、方法参数和成员属性(字段)上

  • 可以加在成员属性(字段)上,能够独自完成级联校验


    4.具体实例展示  

4.1导入依赖(在pom.xml中)

<!-- 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>

4.2配置校验规则

   @NotNull(message = "书籍不能为空")
   // @Size(max = 1000000,min = 1,message = "大小必须在10至100之间")
    protected Integer bid;

    @NotBlank(message = "书籍名不能为空")
    protected String bname;

    @NotBlank(message = "书籍价格不能为空")
    protected Float price;

4.3编写一个新方法用于的校验

  @RequestMapping("/valiAdd")
    public String valiAdd(@Validated Book  book, 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.bookBiz.insertSelective(book);
            return "redirect:list";
        }
        return "book/edit";
    }

4.5修改jsp界面的显示

在其中通过加入一个spa'n标签来进行校验的判断显示

<%@ 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 b ? 'book/valiAdd' : 'book/edit'}" method="post">
    书籍编号:<input type="text" name="bid" value="${b.bid }"><span  style="color: red">${errorMap.bid}</span><br>
    书籍名字:<input type="text" name="bname" value="${b.bname }"><span  style="color: red">${errorMap.bname}</span><br>
    书籍价格:<input type="text" name="price" value="${b.price }"><span  style="color: red">${errorMap.price}</span><br>
    <input type="submit">
</form>
</body>
</html>

4.6效果展示

1.控制台

2.web界面回显

二.拦截器(静态资源不需要)

1.什么是拦截器

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

2.拦截器与过滤器

什么是过滤器(Filter)

依赖于servlet容器。在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。使用过滤器的目的是用来做一些过滤操作,比如:在过滤器中修改字符编码;在过滤器中修改HttpServletRequest的一些参数,包括:过滤低俗文字、危险字符等。

拦截器与过滤器的区别

  • 过滤器(filter)

    1.filter属于Servlet技术,只要是web工程都可以使用

    2.filter主要由于对所有请求过滤

    3.filter的执行时机早于Interceptor

  • 拦截器(interceptor)

    1.interceptor属于SpringMVC技术,必须要有SpringMVC环境才可以使用

    2.interceptor通常由于对处理器Controller进行拦截

    3.interceptor只能拦截dispatcherServlet处理的请求

3.拦截器工作原理

  • preHandle:用于对拦截到的请求进行预处理,方法接收布尔(true,false)类型的返回值,返回true:放行,false:不放行。

    执行时机:在处理器方法执行前执行

    方法参数

    参数说明
    request请求对象
    response响应对象
    handler拦截到的方法处理

  • postHandle:用于对拦截到的请求进行后处理,可以在方法中对模型数据和视图进行修改

    执行时机:在处理器的方法执行后,视图渲染之前

    方法参数

    参数说明
    request请求对象
    response响应对象
    handler拦截到的处理器方法
    ModelAndView处理器方法返回的模型和视图对象,可以在方法中修改模型和视图

  • afterCompletion:用于在整个流程完成之后进行最后的处理,如果请求流程中有异常,可以在方法中获取对象

    执行时机:视图渲染完成后(整个流程结束之后)

    方法参数

    参数说明
    request请求参数
    response响应对象
    handler拦截到的处理器方法
    ex异常对象

4.应用场景

日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等。

权限检查:如登录检测,进入处理器检测是否登录,如果没有直接返回到登录页面;

性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间(如果有反向代理,如apache可以自动记录);

通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个Controller中的处理方法都需要的,我们就可以使用拦截器实现。

5.具体实例

1.创建自定义拦截器

package com.lz.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 {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("【OneInterceptor】:preHandle...");

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("【OneInterceptor】:postHandle...");

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("【OneInterceptor】:afterCompletion...");
    }
}

3 .在sprinig-mvc.xml中配置拦截器 

 <mvc:interceptors>
        <bean class="com.lz.interceptor.OneInterceptor"></bean>
    </mvc:interceptors>

4.没有拦截的情况(默认拦截所有)

6.拦截器链

1.配置拦截器链

  <mvc:interceptors>
    <!--2) 多拦截器(拦截器链)-->
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="com.lz.interceptor.OneInterceptor"/>
    </mvc:interceptor>
    <mvc:interceptor>
        <mvc:mapping path="/book/**"/>
        <bean class="com.lz.interceptor.TwoInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

 2.效果图展示

7.登录的拦截器实例 

1.创建拦截器

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public 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;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

2.配置拦截器(在spring-mvc.xml中)

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

3.创建登录的contorrl

package com.lz.controller;

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 ("zs".equals(uname)){
            session.setAttribute("uname",uname);
        }
        return "redirect:/book/list";
    }

    @RequestMapping("/logout")
    public String logout(HttpServletRequest req){
        req.getSession().invalidate();
        return "redirect:/book/list";
    }
}

4.在创建登录的jsp界面(在jsp的包下面) 

<%--
  Created by IntelliJ IDEA.
  User: lzzxq
  Date: 2023/9/12
  Time: 14:40
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form  action="/login"  method="post">
    用户名<input  name="uname">
    <input  type="submit">
</form>
</body>
</html>

5.展示效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1004202.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

清理不干净等于白清理!如何擦除所有个人数据并擦除iPhone和iPad

我们大多数人每天都在使用iPhone和iPad。在设备的使用寿命中&#xff0c;我们会积累大量敏感数据和信息&#xff0c;包括消息、照片、视频、联系人、信用卡、密码等等。这就是为什么确保你有所有重要物品的备份很重要&#xff0c;这样你就可以在卖掉或交给别人之前把它扔掉。 …

13.6 Production State Awareness (PSA)

1. Introduction UFS设备可以利用有关其生产状态的知识&#xff0c;相应地调整内部操作。 例如&#xff0c;在设备焊接之前加载到存储设备中的内容可能被破坏&#xff0c;其概率高于regular模式。UFS设备可以在设备焊接前使用“Special”内部操作加载内容&#xff0c;这将减少…

返回值加const ,为了不拷贝得到成员的值,但被赋值的左值也要const

1. getA 函数返回值 什么都不加&#xff0c;也改不了c里面a的指针指向 why&#xff1f;返回成员变量时&#xff0c;会复制一下。 返回成员变量时&#xff0c;一般会赋值一下没有RVO_地摊书贩的博客-CSDN博客 2. getA 函数返回值 加了引用&#xff0c; 就没有复制 3. getA 函数…

04JVM_语法糖

一、编译期处理 语法糖java编译器把*.java源码编译为*.class字节码的过程中&#xff0c;自动生成和转换的一些代码&#xff08;添加的class字节码&#xff09;&#xff0c;减轻程序员的负担。 1.默认构造器 默认构造器没有写任何的构造方法&#xff0c;但经过编译器编译成字…

pdfjs解决ie浏览器预览pdf问题

pdfjs是一个js库&#xff0c;可以将pdf文件用canvas重新绘制&#xff0c;从而无需借助pdf读取插件就可以直接预览。 目前chrome内核的浏览器已内置pdf读取插件&#xff0c;但ie浏览器还没有。而我们最近在做的一个项目使用对象是医院&#xff0c;使用的浏览器竟然还是ie。所以我…

@BeforeEach与@AfterEach

BeforeEach 修饰在方法上&#xff0c;在每一个测试方法&#xff08;所有Test、RepeatedTest、ParameterizedTest或者TestFactory注解的方法&#xff09;之前执行一次。 例如&#xff1a;一个测试类有2个测试方法testA()和testB()&#xff0c;还有一个BeforeEach的方法&#x…

安科瑞ADL400产品功能及参数说明,适用于5G基站计量使用

安科瑞虞佳豪壹捌柒陆壹伍玖玖零玖叁 “十四五”以来&#xff0c;重庆新型数字基础设施建设取得明显成效&#xff0c;截至今年6月底&#xff0c;每万人拥有5G基站数24个&#xff0c;5G发展保持在全国第一梯队。 新型数字基础设施包括5G网络、千兆光网、数据中心、工业互联网、…

Mysql高级——存储引擎

存储引擎 1). 连接层 最上层是一些客户端和链接服务&#xff0c;包含本地sock 通信和大多数基于客户端/服务端工具实现的类似于 TCP/IP的通信。主要完成一些类似于连接处理、授权认证、及相关的安全方案。在该层上引入了线程 池的概念&#xff0c;为通过认证安全接入的客户端提…

潍坊学院图书馆藏《乡村振兴战略下传统村落文化旅游设计》许少辉八一新书

潍坊学院图书馆藏《乡村振兴战略下传统村落文化旅游设计》许少辉八一新书

教师必看,如何巧妙告知学生家长成绩分数?

亲爱的教师们&#xff01;今天博主要跟你们分享一个巧妙的方法&#xff0c;帮助你们与学生家长发布成绩分数时让他们更好的了解孩子的学习情况。是不是觉得很有用&#xff1f;那就跟我一起来看看吧。 我们可以借助一个神奇的工具——易查分。它能把成绩分数以在线查询的形式呈现…

AD22使用笔记+积累库

一、前言 使用AD9习惯了&#xff0c;但是需求逐渐上来了就不够用了&#xff0c;好多快捷的新功能要新版本软件才能用&#xff0c;所以升级使用AD22 目录 1.添加层之后中间层无法布线 2.新增快捷方式CtrlW布线&#xff0c;不用点图标了 二、环境 AD22 三、正文 1.添加层之…

软件设计模式(七):适配器、桥梁、命令、原型模式

前言 这是软件设计模式系列的最后一篇文章&#xff0c;对于23种设计模式荔枝梳理了比较重要的几种&#xff0c;剩下的在实际开发中用的也比较少哈哈哈。在这篇文章中荔枝主要梳理软件设计模式中的适配器模式、桥梁模式、命令模式和原型模式的相关知识。希望能帮助到有需要的小伙…

选择器进阶与表单表格

华子目录 选择器并集选择器后代选择器子代选择器伪类选择器伪元素选择器结构选择器属性选择器相邻选择器 表单&#xff08;form&#xff09;label标签 表格&#xff08;table标签&#xff09; 选择器 下面是我们之前学习过的选择器 *{}&#xff1a;通配符选择器&#xff0c;选…

JDK8新特性--函数式接口--(Consumer的概念理解,模拟练习,企业实战)全流程彻底搞懂

背景&#xff0c;起因是因为在项目开发过程中&#xff0c;发现了一处代码的写法觉得很新奇看不懂&#xff0c;了解后发现是用到了函数式接口的知识。特此学习记录&#xff0c;整体过程梳理在本文。如果你不满足就会写个CURD&#xff0c;业务代码只会new来new去&#xff0c;代码…

Spring 中三种 BeanName 生成器!

无论我们是通过 XML 文件&#xff0c;还是 Java 代码&#xff0c;亦或是包扫描的方式去注册 Bean&#xff0c;都可以不设置 BeanName&#xff0c;而 Spring 均会为之提供默认的 beanName&#xff0c;今天我们就来看看 Spring 中三种处理不同情况的 beanName 生成器。 1. BeanN…

零基础Linux_4(权限和初识操作系统)具体用户分类+rwx+umask+粘滞位

目录 1. 操作系统初识 1.1 操作系统的基本概念 1.2 操作系统的意义 1.3 指令操作的意义 2. shell命令及运行原理 2.1 shell的概念 2.2 shell 的意义 3. Linux权限 3.1 Linux 具体用户的分类 3.2 用户管理 adduser 新用户名(添加普通用户) 用户登陆 - SSH 用户名 u…

视频号挂公众号链接没完全堵死,还能加,最新方法教程,玩私域流量的福音来了

视频号挂公众号链接 视频号挂公众号链接&#xff0c;不限号&#xff0c;不限次数&#xff0c;不需要绑定公众号&#xff0c;不需要10000阅读量 视频号评论区能挂链接&#xff0c;对视频号做公转私的人来说&#xff0c;可以说是大惊喜&#xff0c;对公司来讲放上自己的推广链接…

前缀和实例1 (【模板】前缀和 )

题目&#xff1a; 算法原理&#xff1a; 前缀和算法能快速求出某一个区间内所有元素的和 1 预处理出来一个前缀和数组dp dp[i] dp[i-1]v[i] (v数组由输入的数字组成&#xff09;&#xff0c;即区间[1,i]的所有元素的和区间[1,i-1]所有元素的和v数组中i下标的元素 2 使用前缀…

获取1688店铺详情 API接口(获取卖家昵称、店铺类型、公司信息、店铺标题、店铺主页)

seller_info-获得店铺详情 1688.seller_info进入测试 公共参数 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地址中&#xff09;[item_search,item_get,it…

计算机竞赛 大数据商城人流数据分析与可视化 - python 大数据分析

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于大数据的基站数据分析与可视化 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度…