“JSR303和拦截器在Java Web开发中的应用与实践“

news2024/11/19 23:18:14

目录

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

        return true;
    }

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

    }

    @Override
    public 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 {
    @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 {

    }
}

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: yuanh
  Date: 2023/9/11
  Time: 18:38
  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>
<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和拦截器有更深入的理解,并能在实际项目中应用它们来提升开发效率和代码质量。

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

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

相关文章

纷享销客受邀出席CDIE2023数字化创新博览会 助力大中型企业增长

2023年&#xff0c;穿越周期&#xff0c;用数字化的力量重塑企业经营与增长的逻辑&#xff0c;再次成为企业数字化技术应用思考的主旋律&#xff0c;以数字经济为主线&#xff0c;数字技术融入产业发展与企业增长为依据&#xff0c;推动中国企业数字化升级。 9月5日&#xff0c…

Git多人开发解决冲突案例

准备工作&#xff1a; 1.创建一个gitee远程仓库https://gitee.com/xxxxxxx.git 2.初始化两个本地git仓库用户&#xff0c;目的是模拟多人协作开发时提交代码发生冲突的场景 3.解决冲突并提交。 进入正题&#xff1a; lisi 通过vim指令修改readme.md文件内容&#xff0c;推送到…

合宙Air724UG LuatOS-Air LVGL API控件-表格(Table)

表格&#xff08;Table&#xff09; 示例代码 --创建表格Table1 lvgl.table_create(lvgl.scr_act(),nil)--设置表格为4行5列lvgl.table_set_row_cnt(Table1,4)lvgl.table_set_col_cnt(Table1,5)--给每个单元格赋值lvgl.table_set_cell_value(Table1, 0, 0, "选手")l…

QT生成ICO文件

生成ICO文件 #include <QApplication> #include <QImage> #include <QIcon> #include <QFile> #include <QDebug> #include <QPixmap>int main(int argc, char* argv[]) {QApplication app(argc, argv);// 读取图片文件QImage image(&quo…

Python类的概念

类 类的技术名词解释 ● 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。 ● 类变量&#xff1a;类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用…

功率放大器的定义详解

功率放大器是一种电子放大器&#xff0c;主要用于将输入信号的功率放大到足以驱动负载或输出器件所需的水平。通常&#xff0c;功率放大器会将低电平高电流的输入信号转换成高电平低电流的输出信号&#xff0c;以便给负载提供足够的功率。 功率放大器广泛应用于各种应用场合&am…

(Note)中文EI检索期刊目录

ei和sci、ssci一样是国际知名的期刊数据库&#xff0c;ei不仅收录国际知名的刊物&#xff0c;也收录了一些国内期刊&#xff0c;为方便投稿选刊&#xff0c;Elsevier官网更新了的EI Compendex期刊目录&#xff0c;那么 国内ei期刊有哪些? 经查询共有250余种期刊&#xff0c;新…

【LeetCode-面试经典150题-day23】

目录 108. 将有序数组转换为二叉搜索树 148.排序链表 427.建立四叉树 23.合并K个升序链表 108. 将有序数组转换为二叉搜索树 题意&#xff1a; 给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 高度平衡 二叉搜索树。 高度平衡 二…

如何实现自己在家搭建全端口P2P穿透?快解析内网穿透

对于有公网主机&#xff0c;有一定的操作能力&#xff0c;需要独立资源配置使用的&#xff0c;可以选择自行搭建内网映射服务。那么如何实现自己搭建全端口P2P穿透呢&#xff1f;下面为大家提供了不同场景下的不同方法&#xff0c;供大家使用时参考。 SSH是一种安全的远程登录…

一个方法用js生成随机双色球、大乐透

代码如下&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><s…

【C++】构造函数分类 ① ( 构造函数分类简介 | 无参构造函数 | 有参构造函数 | 拷贝构造函数 | 代码示例 - 三种类型构造函数定义与调用 )

文章目录 一、构造函数分类1、构造函数分类简介2、构造函数分类代码分析无参构造函数有参构造函数拷贝构造函数 二、代码示例 - 三种类型构造函数定义与调用 一、构造函数分类 1、构造函数分类简介 C 构造函数可以分为以下几类 : 无参构造函数 : 最简单也是默认的构造函数 , 函…

gitlab在项目中创建自己的分支的顺序操作,一整套流程

gitlab在项目中创建自己的分支的顺序操作&#xff0c;一整套流程 目录概述需求&#xff1a; 设计思路实现思路分析 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better…

【C++】day4学习成果:仿写string类等等

1.仿照string类&#xff0c;完成myString 类 代码&#xff1a; #include <iostream> #include <cstring>using namespace std;class myString {private:char *str; //记录c风格的字符串int size; //记录字符串的实际长度public://无参构造myS…

C++学习之list的实现

在了解学习list实现之前我们首先了解一下关于迭代器的分类&#xff1a; 按功能分类&#xff1a; 正向迭代器 反向迭代器 const正向迭代器 const反向迭代器 按性质分类&#xff1a; 单向迭代器 只能 例如单链表 双向迭代器 可&#xff0c;也可-- 例如双…

酒店固定资产管理怎么分类

在酒店业中&#xff0c;固定资产的管理是至关重要的一环。它不仅影响到企业的运营效率和盈利能力&#xff0c;而且直接影响到客户体验和品牌形象。因此&#xff0c;对于酒店管理者来说&#xff0c;合理、有效地进行固定资产管理是一项必不可少的任务。本文将探讨酒店固定资产的…

Spring系列文章:Bean的获取⽅式

一、简介 Spring为Bean提供了多种实例化⽅式&#xff0c;通常包括4种⽅式。&#xff08;也就是说在Spring中为Bean对象的创建准 备了多种⽅案&#xff0c;⽬的是&#xff1a;更加灵活&#xff09; 第⼀种&#xff1a;通过构造⽅法实例化 第⼆种&#xff1a;通过简单⼯⼚模式…

c++day4---9.11

1.思维导图&#xff1a; 2.myString: #include <iostream> #include <cstring> #include <cstdlib>using namespace std;class myString { private:char *str; //记录c风格的字符串int size; //记录字符串的实际长度 public://无参构造m…

springboot之二:整合junit进行单元测试+整合redis(本机、远程)+整合mybatis

资源地址&#xff1a; 整合junit的代码&#xff1a;https://download.csdn.net/download/zhiaidaidai/88291527 整合redis的代码&#xff1a;https://download.csdn.net/download/zhiaidaidai/88291536 整合mybatis的代码&#xff1a;https://download.csdn.net/download/zh…

科研绘图,别忘Origin!

公众号&#xff1a;尤而小屋作者&#xff1a;Peter编辑&#xff1a;Peter 大家好&#xff0c;我是Peter~ 科研绘图&#xff0c;你一般用什么软件&#xff1a; Python&#xff1f;R&#xff1f;MATLAB&#xff1f;GraphPad Prism&#xff1f;Matplotlib&#xff1f; 但&#…

案例:实现TodoLis(尚硅谷)

是做完后再记录的&#xff0c;前端我主要是要了解下&#xff0c;所以这里记录的比较浅 由于是做完后记录&#xff0c;所以你cv后的代码的效果并不一定和我展示的效果图一样 静态页面 先来实现静态页面&#xff0c;再考虑动态页面 组件拆分 说明(实际的组件名不是和下面一样的…