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

目录

引言

在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进行表单验证的快速入门示例:

实体类

java 复制代码
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;
    }
}
}

后台校验

java 复制代码
    //    给数据添加服务端校验
    @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页面

html 复制代码
<%@ 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.拦截器链
java 复制代码
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...");
    }
}
java 复制代码
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...");
    }
}
xml 复制代码
    <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.登录

登录拦截器

java 复制代码
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层

java 复制代码
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

html 复制代码
<%--
  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>

配置拦截器

xml 复制代码
   <mvc:interceptors>
        <bean class="com.yuan.interceptor.LoginInterceptor"></bean>
    </mvc:interceptors>

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

总结

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

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

相关推荐
侠客行03176 小时前
Mybatis连接池实现及池化模式
java·mybatis·源码阅读
蛇皮划水怪6 小时前
深入浅出LangChain4J
java·langchain·llm
子兮曰6 小时前
OpenClaw入门:从零开始搭建你的私有化AI助手
前端·架构·github
吴仰晖6 小时前
使用github copliot chat的源码学习之Chromium Compositor
前端
1024小神6 小时前
github发布pages的几种状态记录
前端
老毛肚8 小时前
MyBatis体系结构与工作原理 上篇
java·mybatis
风流倜傥唐伯虎8 小时前
Spring Boot Jar包生产级启停脚本
java·运维·spring boot
不像程序员的程序媛8 小时前
Nginx日志切分
服务器·前端·nginx
Yvonne爱编码8 小时前
JAVA数据结构 DAY6-栈和队列
java·开发语言·数据结构·python
Re.不晚8 小时前
JAVA进阶之路——无奖问答挑战1
java·开发语言