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

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: “JSR303和拦截器在Java Web开发中的应用与实践“

引言

在Java Web开发过程中,我们经常会遇到需要对输入数据进行验证和处理,同时需要对请求进行拦截与控制的需求。为了方便实现这些功能,我们可以使用JSR303验证框架和拦截器技术。本篇博客将介绍JSR303和拦截器的基本概念,并探讨它们在Java Web开发中的应用与实践。

什么是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;
    }
}
}
• 1
• 2
• 3
• 4
• 5
• 6
• 7
• 8
• 9
• 10
• 11
• 12
• 13
• 14
• 15
• 16
• 17
• 18
• 19
• 20
• 21
• 22
• 23
• 24
• 25
• 26
• 27
• 28
• 29
• 30
• 31
• 32
• 33
• 34
• 35
• 36
• 37
• 38
• 39
• 40
• 41
• 42
• 43
• 44
• 45
• 46
• 47
• 48
• 49
• 50
• 51
• 52
• 53
• 54
• 55
• 56
• 57
• 58
• 59
• 60
• 61

后台校验

//    给数据添加服务端校验
    @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";
    }
• 1
• 2
• 3
• 4
• 5
• 6
• 7
• 8
• 9
• 10
• 11
• 12
• 13
• 14
• 15
• 16
• 17
• 18
• 19
• 20

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>
• 1
• 2
• 3
• 4
• 5
• 6
• 7
• 8
• 9
• 10
• 11
• 12
• 13
• 14
• 15
• 16
• 17
• 18

页面效果

通过在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...");
    }
}
• 1
• 2
• 3
• 4
• 5
• 6
• 7
• 8
• 9
• 10
• 11
• 12
• 13
• 14
• 15
• 16
• 17
• 18
• 19
• 20
• 21
• 22
• 23
• 24
• 25
• 26
• 27
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...");
    }
}
• 1
• 2
• 3
• 4
• 5
• 6
• 7
• 8
• 9
• 10
• 11
• 12
• 13
• 14
• 15
• 16
• 17
• 18
• 19
• 20
• 21
• 22
• 23
• 24
• 25
• 26
• 27
<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>
• 1
• 2
• 3
• 4
• 5
• 6
• 7
• 8
• 9
• 10
• 11
• 12
• 13
  • 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 {
    }
}
• 1
• 2
• 3
• 4
• 5
• 6
• 7
• 8
• 9
• 10
• 11
• 12
• 13
• 14
• 15
• 16
• 17
• 18
• 19
• 20
• 21
• 22
• 23
• 24
• 25
• 26
• 27
• 28
• 29
• 30
• 31
• 32
• 33
• 34
• 35
• 36
• 37

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";
    }
}
• 1
• 2
• 3
• 4
• 5
• 6
• 7
• 8
• 9
• 10
• 11
• 12
• 13
• 14
• 15
• 16
• 17
• 18
• 19
• 20
• 21
• 22
• 23
• 24
• 25
• 26

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>
• 1
• 2
• 3
• 4
• 5
• 6
• 7
• 8
• 9
• 10
• 11
• 12
• 13
• 14
• 15
• 16
• 17

配置拦截器

<mvc:interceptors>
        <bean class="com.yuan.interceptor.LoginInterceptor"></bean>
    </mvc:interceptors>
• 1
• 2
• 3
• 4

以我的代码为例,如果登录点击进去携带的参数不为空并且为yh就可以进入主界面,如果不是就会被拦截一直在登录界面

总结

本篇博客介绍了JSR303在这里插入代码片验证框架和拦截器技术在Java Web开发中的应用与实践。通过使用JSR303,我们可以简化表单验证逻辑,并提高代码的可维护性。拦截器则可以用于实现身份验证、日志记录、性能监控等功能,提升系统的安全性和可观测性。通过深入掌握和灵活应用JSR303和拦截器,我们可以更好地开发出高质量的Java Web应用。

希望本篇博客能够帮助你对JSR303和拦截器有更深入的理解,并能在实际项目中应用它们来提升开发效率和代码质量。


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
4天前
|
Java
Java开发实现图片URL地址检验,如何编码?
【10月更文挑战第14天】Java开发实现图片URL地址检验,如何编码?
17 4
|
3天前
|
监控 Java 测试技术
Java开发现在比较缺少什么工具?
【10月更文挑战第15天】Java开发现在比较缺少什么工具?
14 1
|
4天前
|
Java
Java开发实现图片地址检验,如果无法找到资源则使用默认图片,如何编码?
【10月更文挑战第14天】Java开发实现图片地址检验,如果无法找到资源则使用默认图片,如何编码?
18 2
|
1天前
|
开发框架 自然语言处理 PHP
PHP在Web开发中的持久魅力与创新实践###
【10月更文挑战第17天】 本文探讨了PHP作为一门老牌却充满活力的编程语言,在现代Web开发中的独特优势和未来趋势。通过分析其简洁性、灵活性、强大生态系统及不断创新的特性,本文旨在揭示PHP为何能持续吸引开发者,并在技术快速迭代的时代保持竞争力。同时,文章也展望了PHP在未来Web开发领域的发展潜力,强调其在技术创新和社区支持下,依然能够引领Web开发的新潮流。 ###
14 9
|
3天前
|
Java 关系型数据库 API
介绍一款Java开发的企业接口管理系统和开放平台
YesApi接口管理平台Java版,基于Spring Boot、Vue.js等技术,提供API接口的快速研发、管理、开放及收费等功能,支持多数据库、Docker部署,适用于企业级PaaS和SaaS平台的二次开发与搭建。
|
3天前
|
Java 测试技术 程序员
💡Java 零基础 | 深入理解注释的重要性与应用
【10月更文挑战第10天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
10 5
|
1天前
|
设计模式 算法 Java
Java中的多态性:深入理解与应用
【10月更文挑战第16天】 在Java编程的广阔天地中,多态性作为一种强大的面向对象特性,扮演着至关重要的角色。它允许我们以统一的方式处理不同类型的对象,极大地提高了程序的灵活性和可扩展性。本文将深入浅出地探讨Java中多态性的概念、实现机制以及在实际开发中的应用,帮助读者更好地理解和运用这一特性。
|
2天前
|
前端开发 安全 关系型数据库
PHP在Web开发中的应用及其优势###
【10月更文挑战第16天】 — 本文探讨了PHP在现代Web开发中的广泛应用及其显著优势。通过分析PHP的核心特性,如灵活性、易用性和广泛的应用支持,阐述了为何PHP成为众多开发者和公司的首选技术。文章还介绍了PHP与其他编程语言的比较,并展望了其未来的发展趋势。 ###
12 2
|
3天前
|
开发框架 Java 程序员
揭开Java反射的神秘面纱:从原理到实战应用!
本文介绍了Java反射的基本概念、原理及应用场景。反射允许程序在运行时动态获取类的信息并操作其属性和方法,广泛应用于开发框架、动态代理和自定义注解等领域。通过反射,可以实现更灵活的代码设计,但也需注意其性能开销。
12 1
|
4天前
|
Java 测试技术 程序员
💡 Java 零基础 | 探索 if 条件语句的应用与技巧
【10月更文挑战第9天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
11 2