超快速上手基于SpringMVC的JSR303和拦截器

2023-10-29

目录

一、JSR303

二、拦截器


一、JSR303

        ①JSR303介绍

        JSR303的作用其实就是类似于验证作用,只是和我们一般的不一样点在于,JSR303是基于服务端的验证,目的在于就是放置客户端的验证被绕过!

现在我们用一个例子:基于之前创建的CRUD的增加,实现JSR303验证,我们想要达到的效果就是我们在输入空的内容时,我们不能向数据库添加数据,并且给出相应的非空提示!

         ②实现非空验证

2.1导入POM依赖

 <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>6.0.7.Final</version>
</dependency>

2.2添加非空注释

这一步我们需要在对应的实体类判断的属性上方添加非空注释

@NotNull(message = "提示语句")

比如我们举例的例子Clazz对应的属性加上注释

package com.zq.ssm.model;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

/**
 * @NotNull :作用于基本数据类型
 * @NotEmpty    作用于集合
 * @NotBlank    作用于字符串
 */
public class Clazz {
    @NotNull(message = "班级id不能为空")
    private Integer cid;

    @NotBlank(message = "班级名字不能为空")
    private String cname;

    @NotBlank(message = "教师名字不能为空")
    private String cteacher;

    private 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;
    }
}

 2.3后端编码

既然是服务端的验证,那么和后端的方法判断就息息相关,我们就需要在后端进行判断,我们直接在Clazz的web层加入方法:

ClazzController:

    @RequestMapping("/valiadd")
    public String valiadd(HttpServletRequest req, @Validated Clazz clazz, BindingResult result){
        if(result.hasErrors()){
            List<FieldError> fieldErrors = result.getFieldErrors();
            Map<String,Object> map = new HashMap<>();
            for (FieldError fieldError : fieldErrors) {
                map.put(fieldError.getField(),fieldError.getDefaultMessage());
                System.out.println(fieldError.getField());
            }
            req.setAttribute("eMap",map);
        }else{
            this.clazzBiz.insertSelective(clazz);
            return "redirect:/clz/list";
        }
        return "clzEdit";
    }

2.4前端编码

然后就是我们的前端的代码了,我们需要做的就是加入提示语句的位置放置,通过作用域的显示因为我们在后端进行了判断,如果非空的话就会将提示语句存入Session中。
jsp:

<body>
<form action="${pageContext.request.contextPath }/clz/${empty b ? 'valiadd' : 'edit'}" method="post">
    id:<input type="text" name="cid" value="${b.cid }"><span style="color: red;">${eMap.cid}</span><br>
    cname:<input type="text" name="cname" value="${b.cname }"><span style="color: red;">${eMap.cname}</span><br>
    cteacher:<input type="text" name="cteacher" value="${b.cteacher }"><span style="color: red;">${eMap.cteacher}</span><br>
    <input type="submit">
</form>
</body>

 2.5效果显示:

 


二、拦截器

        ①什么是拦截器?

其实拦截器和过滤器是有点相似的只不过:

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

         ②拦截器与过滤器的区别

过滤器(filter):

    1) filter属于Servlet技术,只要是web工程都可以使用
    2) filter主要对所有请求过滤
    3) filter的执行时机早于Interceptor

拦截器(interceptor)

    1) interceptor属于SpringMVC技术,必须要有SpringMVC环境才可以使用
    2) interceptor通常对处理器Controller进行拦截
    3) interceptor只能拦截dispatcherServlet处理的请求

         ③案例实现拦截器

我们在这使用一个简单的案例来实现一下拦截器的功能,并且分析一下拦截器的使用

3.1创建一个web层用来跳转页面

package com.zq.ssm.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author张强
 * @site www.zq.com
 * @create  2022-08-19 19:49
 */
@Controller
public class HelloController  {
    @RequestMapping("/hello")
    public String hello(){
        System.out.println("进入了web层");
        return "index";
    }
}

3.2创建拦截器对象,实现接口,实现接口方法

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...");
    }
}

在这里就是主要是第一个方法,返回值为true则代表通过拦截,为false则进行拦截,然后在第一个方法中进行添加逻辑语句进行我们的拦截判断。

3.3在SpringMVC配置文件中添加配置:

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

3.4运行结果查看拦截的逻辑顺序:

 这时我们运行我的web层对应的界面向中央控制器发送请求,然后看一下控制台的打印结果:

 我们发现我们在发送请求后,顺序就是:
进入拦截器第一个方法——>通过拦截则进入web层——>第二个方法——>第三个方法       

        ④拦截器链 

什么是拦截器链?大致的理解就是多重拦截,针对不同的请求进行层层拦截

比如这样的配置文件:

 <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.zq.ssm.interceptor.OneInterceptor"></bean>
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/clz/**"/>
            <bean class="com.zq.ssm.interceptor.TwoInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

这个配置就可以是对待请求是clz/**的进行双重拦截

第一个是无论什么请求都会进入到 OneInterceptor的拦截器

而第二个是只有以clz/开头的请求才会进入到TwoInterceptor的拦截器

然后当我们请求以clz/开头的请求时,他们的拦截顺序为:

        ⑤拦截器实际运用:必须登录才能进入主界面

我们将第一个拦截器进行修改作为我们判断我们的用户发送的请求是否是登录之后的,因为实际的项目开发中,这个拦截是必不可少的,我们想要展示主界面的东西那么就得登录,所以我们需要拦截器进行拦截判断。

5.1拦截器配置:

<!--配置拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.zq.ssm.interceptor.OneInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

5.2OneInterceptor业务编写

package com.zq.ssm.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author张强
 * @site www.zq.com
 * @create  2022-08-19 19:51
 */
public class OneInterceptor implements HandlerInterceptor {

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

5.3请求业务(web)编写:

package com.zq.ssm.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * @author张强
 * @site www.zq.com
 * @create  2022-08-19 20:05
 */
@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:/clz/list";
    }

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

5.4案例分析

这个案例就是拦截器的一个应用:

我们必须要先登录才能够进入到主界面list.jsp。否则我们直接请求主界面是不会显示主界面的内容的。接下来我们看一下效果输入:

http://localhost:8080/clz/list 不能访问,因为session被过滤掉

http://localhost:8080/login  不能访问,因为用户未成功登录被过滤掉

http://localhost:8080/login?uname=zs 可以访问

http://localhost:8080/logout 清除掉session

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

超快速上手基于SpringMVC的JSR303和拦截器 的相关文章

随机推荐

  • 基于 webpack 5 实现自定义 loader

    前面的话 基于 webpack 5 创建自定义 同步 异步loader 在此基础上实现一个简易的渲染 markdown 的 loader 和 合成雪碧图的 loader 代码地址 自定义loader 准备工作 我们先创建一个 webpack
  • MacOS无法使用arduinoIDE解决方法

    1 当arduino ide版本过低时m1mac可能无法使用 出现可能是因为版本过低 Arduino 1 8 8 Mac OS X 开发板 Arduino Genuino Mega or Mega 2560 ATmega2560 Mega
  • 不能使用QtCreator debug Qt代码思路之一

    不能使用QtCreator debug Qt代码思路之一 在工程文件 pro中查找是否有 CONFIG release这样的配置 将它注释掉就可以开始debug了
  • ping www.baidu.com,显示name or service is not know

    相信许多网友都遇到过 前一天使用centos 还没有问题 第二天打开是 突然发现ping www baidu com 显示name or service is not know 大家可以打开windows任务管理器 找到服务 确保NAT正在
  • 类模板的特化

    你可以用模板实参来特化类模板 和函数模板的重载类似 通过特化类模板 你可以优化基于某种特定类型的实现 或者克服某种特定类型在实例化类模板时所出现的不足 另外 如果要特化一个类模板 你还要特化该类模板的所有成员函数 虽然也可以只特化某个成员函
  • Spring-@Value用法介绍

    Value在开发中最常使用的几个注解之一 通常用来获取配置文件中的属性 不过除了从配置文件中获取值 Value还支持使用默认值 表达式等方式为变量设置值 本文就针对 Value的使用进行分享 Value用法 Value中直接设置值 顾名思义
  • 【目标检测-YOLO】YOLOv5-v6.0-yolov5s网络架构详解(第一篇)

    1 准备工作 趁热打铁 上节分析了 v5 0 的 yolov5s 模型架构 本节顺便把 v6 0的图也画下 官方代码中贴心的给提供了 onnx 文件 如下图 但是 当我打开 onnx 的时候 我麻了 所以 还是需要自己生成下 onnx 文件
  • LIVE555研究之三:LIVE555基础

    LIVE555基础 LIVE555是为流媒体提供解决方案的跨平台C 开源项目 从今天起我们将正式开始深入LIVE555代码 一 各库简要介绍 LIVE555下包含LiveMedia UsageEnvironment BasicUsageEn
  • HTML——前端实时可视化开发工具

    前端实时可视化开发工具 liveStyle liveReload Broswer Sync 一 liveStyle 如图 liveStyle支持三种文件 需要安装两个插件 浏览器的插件 sublime编辑器中的livestyle插件 浏览器
  • 给定一个二叉树, 找到该树中两个指定节点p和q(数值唯一)的最近公共祖先

    递归思想 判断p和q是否分别根结点的左右两侧 如果在左右两侧那么直接返回根结点即可 不失一般性 假设p和q分别均在根结点的左侧 那么按照分治的思想 此时继续往左子树找即可 问题规模已经缩小 那么依旧还是上面的操作划分 故可以采用递归的思想
  • 力扣第48天--- 第739题、第496题

    力扣第48天 第739题 第496题 文章目录 一 第739题 每日温度 二 第496题 下一个更大元素 I 一 第739题 每日温度 单调栈里放的是下标 适用场景 对于数组中某一元素 寻找右边 左边第一个大于或者小于这个元素的位置 单调栈
  • flutter - 点击事件(二) - 给图片增加点击UI效果

    上一篇 介绍了如何便利的构造一个自己的点击控件 flutter 中 如果给图片外面套 InkWell 你会发现点击的逻辑生效了 但是 UI 上没反应 备注 图片来源 违反版权请联系我 删除 代码如下 import package flutt
  • 51单片机——串口通信

    51单片机 串口通信 串口通信 串口通信的原理 串口的配置 定时器的配置 c源代码 netty源代码 结果 本篇博客的最终效果是实现51单片机用串口发送Hello World netty监听串口读到Hello World后回发给51单片机
  • 【Device Tree】Android DTS 加载流程

    前言 在之前的文章中已经对设备树的基本概念作了讲解 操作系统 例如在 Android 中使用的 Linux 内核 会使用 DT 来支持 Android 设备使用的各种硬件配置 硬件供应商 ODM 会提供自己的 DT 源文件 接下来 Linu
  • sql server: 数据库备份时出现-operating-system-error-5拒绝访问

    sql server 数据库备份时出现 operating system error 5拒绝访问 一般备份文件选择的目录为磁盘根目录或备份所选分区未授予sqlserver用户读写权限时会出现此错误 解决办法就是给sqlserver用户授予权
  • 排序算法(5)----堆排序

    这篇博客从以下几个方面来说 什么是最大堆以及代码实现 堆排序基础代码 一次优化 提高效率 二次优化 原地堆排序 无需额外空间 1 什么是最大堆以及代码实现 这里可以参考言简意赅的博客 堆与最大堆 2 堆排序基础代码 import com h
  • JavaScript中的事件委托

    今天 我们来讨论一下JavaScript中的事件委托 JavaScript事件委托是一种优化代码的技术 它允许我们在DOM树中注册一个事件处理程序 并通过冒泡机制处理多个元素的事件 事件委托是一个强大的技术 它可以极大地提高代码性能和可维护
  • Cpolar+Tipas:在Ubuntu上搭建私人问答网站,为您提供专业的问题解答

    文章目录 前言 2 Tipask网站搭建 2 1 Tipask网站下载和安装 2 2 Tipask网页测试 2 3 cpolar的安装和注册 3 本地网页发布 3 1 Cpolar临时数据隧道 3 2 Cpolar稳定隧道 云端设置 3 3
  • 10 个 Python 自动探索性数据分析神库!

    转自 公众号丨数据STUDIO 永久免费 扫码加入 探索性数据分析是数据科学模型开发和数据集研究的重要组成部分之一 在拿到一个新数据集时首先就需要花费大量时间进行EDA来研究数据集中内在的信息 自动化的EDA Python包可以用几行Pyt
  • 超快速上手基于SpringMVC的JSR303和拦截器

    目录 一 JSR303 二 拦截器 一 JSR303 JSR303介绍 JSR303的作用其实就是类似于验证作用 只是和我们一般的不一样点在于 JSR303是基于服务端的验证 目的在于就是放置客户端的验证被绕过 现在我们用一个例子 基于之前