认识JSR303
JSR303是一项Java标准规范,也叫做Bean Validation规范,提供了一种JavaBean数据验证的规范方式。在SpringMVC中,可以通过引入JSR303相关的依赖,来实现数据的校验。
在使用JSR303进行校验时,需要在需要校验的JavaBean的属性上添加相应的注解,如@NotNull、@Size等。同时,还需要在需要进行校验的方法中使用@Valid注解进行标注,以通知SpringMVC进行校验操作。
JSR303提供了一些基本的校验注解,如@NotNull、@Size、@Pattern等,还可以通过自定义注解来实现更复杂的校验逻辑。除了基本的校验注解之外,JSR303还提供了一些组合注解,如@Valid、@GroupSequence等,可以更灵活地进行校验。
总的来说,JSR303在SpringMVC中的应用非常广泛,可以有效地提高数据的安全性和可靠性。
为什么要用
认识了JSR303那我们为什么要用他呢?
简单易用:JSR303提供了一些简单明了的注解和API,使得验证输入数据变得非常容易。
代码可读性:使用JSR303注解能让代码更具可读性,因为验证的逻辑可以直接在Java Bean中看到。
减少重复代码:使用JSR303注解可以避免编写重复的验证代码,并降低了维护和测试成本。
标准化:JSR303是Java EE标准之一,使用它可以使得代码更加标准化、可移植。
安全性:使用JSR303注解可以提高代码的安全性,因为可以对输入数据进行有效的验证,从而避免了安全漏洞的出现。
可扩展性:JSR303提供了一种简单的机制来扩展验证规则,从而使其满足应用程序的需求。
注解
给大家解释一下
JSR303的注解主要用于验证Java Bean的属性,以确保属性的有效性和完整性。具体来说,主要有以下作用:
-
更方便地验证输入数据:通过使用JSR303的注解,可以很方便地验证输入数据是否符合要求,从而减少了开发人员的工作量。
-
提高程序的可维护性:通过在Java Bean的属性上定义验证规则,可以将验证逻辑与业务逻辑分离,从而使程序更易于维护和扩展。
-
增加程序的健壮性:通过对Java Bean属性的验证,可以有效地防止非法输入数据对程序的影响,减少程序出错的概率,增加程序的健壮性。
-
提高程序的安全性:通过对Java Bean属性的验证,可以确保输入数据的有效性和完整性,从而减少了程序被攻击的风险。
@NotNull:验证字段不为null。
@NotBlank:验证字段不为空,即长度大于0,去掉空格后长度大于0。
@NotEmpty:验证字段不为空,即长度大于0。
@Min:验证数字字段的最小值。
@Max:验证数字字段的最大值。
@Size:验证字段的大小范围。
@DecimalMin:验证十进制数字段的最小值。
@DecimalMax:验证十进制数字段的最大值。
@Pattern:验证字段匹配正则表达式。
@Email:验证字段为Email格式。
@Length:验证字段的长度。
@Range:验证字段的值在范围内。
@Valid:验证嵌套对象。
@AssertTrue:验证字段为true。
@AssertFalse:验证字段为false。
@Past:验证日期字段在当前时间之前。
@Future:验证日期字段在当前时间之后。
总之,JSR303的注解可以使程序更加健壮、安全、可维护和易于开发。
入门
导入依赖
<!-- 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>
MusicController
在我们的MusicController方法中添加以下代码
// 给数据添加服务端校验
@RequestMapping("/valiAdd")
public String valiAdd(@Validated Music music, 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.musicBiz.insertSelective(music);
return "redirect:list";
}
return "mic/edit";
}
配置校验
制定规则限制他
@NotNull(message = "学生编号不能为空")
private Integer mid;
@NotBlank(message = "学生名称不能为空")
private String mname;
@NotBlank(message = "学生年龄不能为空")
private String mtype;
@NotBlank(message = "学生性别不能为空")
private String minfo;
认识拦截器
Spring拦截器(Interceptor)是Spring MVC框架中的一种机制,用于在请求处理前和请求处理后拦截请求。Spring的拦截器类似于JavaEE中的过滤器(Filter),但是比过滤器更加灵活和强大。
Spring拦截器通过在配置文件中配置拦截器实现类,来将拦截器注入到Spring容器中。拦截器可以对请求进行前置处理(preHandle)、后置处理(postHandle)和完成处理(afterCompletion)。在拦截器中,可以实现很多业务逻辑,比如:日志记录、权限验证、参数验证等。
Spring拦截器可以拦截MVC请求、WebSocket请求、Restful请求等。在拦截器中,可以获取请求的相关参数、请求头等信息,可以对请求参数进行验证和修改,还可以在请求前后记录日志等操作。
使用Spring拦截器可以让我们的代码更加简洁,更加易于维护和扩展。同时,它也提高了代码的可用性和可读性,使我们的应用程序更加健壮和高效。
为什么要用拦截器
拦截器是一种在请求处理前或处理后拦截请求和响应的机制。它可以在请求到达目标之前对请求进行预处理或在目标处理完响应后对响应进行后续处理。拦截器的作用是可以统一处理请求和响应数据,比如请求参数的校验、权限认证、日志记录等,可以减少代码重复、提高代码复用性、增强代码的可维护性和可测试性。此外,拦截器可以对请求和响应数据做出细粒度的控制,可以在某些特定的请求或响应条件下触发特定的处理逻辑,从而满足业务需求。因此,使用拦截器可以让我们更好地控制和管理请求和响应数据,提高应用程序的可靠性和安全性。
拦截器应用的场景
请求参数的校验:可以对请求中的参数进行非空、数据类型、长度等方面的校验,增强应用程序的健壮性。
权限认证:可以对用户的登录状态、权限、角色等方面进行认证和授权,保护应用程序的安全性。
日志记录:可以在请求进入和响应退出时记录相关的系统日志,方便开发人员进行问题排查和性能优化。
缓存处理:可以对某些请求进行缓存,避免重复查询数据库等操作,提高应用程序的性能。
数据加密:可以对请求和响应数据进行加密和解密,保护敏感数据的安全性。
异常处理:可以在请求处理发生异常时进行处理,返回特定的错误信息,避免系统崩溃或返回不友好的错误信息。
总之,拦截器可以应用于几乎所有的 Web 应用程序,可以对请求和响应数据进行各种处理和控制,从而提高应用程序的可靠性、安全性和性能。
过滤器与拦截器的区别
过滤器属于Servlet规范的一部分,拦截器则是SpringMVC框架的一部分。
过滤器的作用范围是Servlet,拦截器的作用范围是方法级别和类级别。
过滤器可以修改HTTP请求和响应,拦截器可以在执行方法之前、之后、异常抛出后等不同的阶段进行处理。
过滤器使用Servlet容器管理,拦截器则使用Spring容器管理。
过滤器可以防止恶意访问和跨站脚本攻击等,拦截器可以实现权限验证、日志记录等。
用户登录权限
Spring-mvc
Spring-mvc.xml中配置多拦截器
<!--<!– 用户权限的请求拦截–>-->
<mvc:interceptors>
<bean class="com.zhanghao.interceptor.LoginInterceptor"></bean>
</mvc:interceptors>
<mvc:interceptors>
<!--2) 多拦截器(拦截器链)-->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.zhanhao.interceptor.OneInterceptor"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/mic/**"/>
<bean class="com.zhanghao.interceptor.TwoInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
LoginInterceptor
创造一个LoginInterceptor拦截器
package com.zhnaghao.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 mname = (String) request.getSession().getAttribute("mname");
if (mname == null || "".equals(mname)){
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 {
}
}
OneInterceptor
package com.zhanghao.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...");
}
}
TwoInterceptor
package com.zhanghao.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...");
}
}
jsp
接着创造一个新的jsp,用来写我们的登入页面代码如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>用户登入</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/login" method="post" enctype="multipart/form-data">
<label>用户名称:</label><br/>
<input type="text" name="mname"/><br/>
<input type="submit" value="登入"/>
</form>
</body>
</html>
今天的分享就到这了