目录
一、JSR303
1、服务端验证
1.1 导入pom依赖
<!--做服务端参数校验 JSR303的jar包依赖-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.7.Final</version>
</dependency>
1.2 对实体类进行约束
package com.zxw.ssm.model;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
/**
* @NotNull :作用于基本数据类型
* @NotEmpty 作用于集合
* @NotBlank 作用于字符串
*/
public class Clazz {
@NotNull(message = "cid不能为空")
protected Integer cid;
@NotBlank(message = "班级名称不能为空")
protected String cname;
@NotBlank(message = "教员老师不能为空")
protected String cteacher;
protected 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;
}
}
注:
@NotNull :作用于基本数据类型 @NotEmpty 作用于集合 @NotBlank 作用于字符串
1.3 ClazzController:
package com.zxw.ssm.controller;
import com.zxw.ssm.biz.ClazzBiz;
import com.zxw.ssm.model.Clazz;
import com.zxw.ssm.model.dto.ClazzDto;
import com.zxw.ssm.util.PageBean;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import javax.xml.ws.Dispatch;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author zxw
* @site ......
* @company 好男人
* @create 2022-08-17 20:54
*/
@Controller
@RequestMapping("/clz")
public class ClazzController {
@Autowired
private ClazzBiz ClazzBiz;
//list->clzList
//toList->重定向list->"redircect:/clz/list"
//toEdit->跳转到编辑页面->clzEdit
//Clazz : 以前是通过模型驱动接口封装、现在是直接在方法中接受参数即可
@RequestMapping("/list")
public String list(Clazz clazz, HttpServletRequest request){
PageBean pageBean = new PageBean();
pageBean.setRequest(request);
List<Clazz> lst = this.ClazzBiz.listPager(clazz, pageBean);
request.setAttribute("lst",lst);
request.setAttribute("pageBean",pageBean);
return "clzList";
}
@RequestMapping("/toEdit")
public String toEdit(Clazz clazz, HttpServletRequest request){
Integer cid = clazz.getCid();
//传递的id代表了修改、没法代表新增
if(cid != null){
List<Clazz> lst = this.ClazzBiz.listPager(clazz, null);
request.setAttribute("b",lst.get(0));
}
return "clzEdit";
}
@RequestMapping("/add")
public String add(Clazz clazz){
this.ClazzBiz.insertSelective(clazz);
return "redirect:/clz/list";
}
/**
* 是与实体类中 的 服务端效验 注解配合使用
* BindingResult 存放了所有违背 校验的错误信息
* @param clazz
* @param bindingResult
* @return
*/
@RequestMapping("/valiAdd")
public String valiAdd(@Valid Clazz clazz, BindingResult bindingResult,HttpServletRequest request) {
if (bindingResult.hasErrors()) {
Map msg = new HashMap();
// 违背规则
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
for (FieldError fieldError : fieldErrors) {
//cid : cid不能为空
System.out.println(fieldError.getField() + ":" + fieldError.getDefaultMessage());
msg.put(fieldError.getField(), fieldError.getDefaultMessage());
}
// 如果出现了错误、应该提示语音显示在 表单提交元素后方
request.setAttribute("msg", msg);
return "clzEdit";
}else{
this.ClazzBiz.insertSelective(clazz);
}
return "redirect:/clz/list";
}
@RequestMapping("/edit")
public String edit(Clazz clazz){
this.ClazzBiz.updateByPrimaryKeySelective(clazz);
return "redirect:/clz/list";
}
@RequestMapping("/del")
public String del(Clazz clazz){
this.ClazzBiz.deleteByPrimaryKey(clazz.getCid());
return "redirect:/clz/list";
}
// 文件上传
@RequestMapping("/upload")
public String upload(ClazzDto clazzDto){
try {
// 前台上传文件
MultipartFile picFile = clazzDto.getPicFile();
//实际配置到 resource.properties
String dispatch = "D:/path";//图片的存放地址
// http://localhost:8080/upload/mvc/1.png
String RequestPath = "/upload/mvc/";//数据库保存的地址 也是我们的访问地址
// 拿到文件上传的名字
String filename = picFile.getOriginalFilename();
FileUtils.copyInputStreamToFile(picFile.getInputStream(),new File(dispatch+filename));
Clazz clazz = new Clazz();
clazz.setCid(clazzDto.getCid());
clazz.setPic(RequestPath+filename);
// 将图片上传之后、并且将图片地址更新到数据库中
this.ClazzBiz.updateByPrimaryKeySelective(clazz);
}catch (Exception e){
e.printStackTrace();
}
return "redirect:/clz/list";
}
// 文件下载
@RequestMapping("/download")
public ResponseEntity download(ClazzDto clazzDto){
try {
// 1.点击瞎子啊传递文件的ID、通过文件的ID查询出文件的路径
Clazz clazz = this.ClazzBiz.selectByPrimaryKey(clazzDto.getCid());
String pic = clazz.getPic();//
//实际配置到 resource.properties
String dispatch = "D:/path";//图片的存放地址
// http://localhost:8080/upload/mvc/1.png
String RequestPath = "/upload/mvc/";//数据库保存的地址 也是我们的访问地址
//
// 2.通过文件的请求地址、转换成文件存放的硬盘地址
String realPath = pic.replace(RequestPath,dispatch);
String fileName = realPath.substring(realPath.lastIndexOf("/")+1);
// 3.将硬盘中文件下载下来 -> 固定代码
//下载关键代码
File file=new File(realPath);
HttpHeaders headers = new HttpHeaders();//http头信息
String downloadFileName = new String(fileName.getBytes("UTF-8"),"iso-8859-1");//设置编码
headers.setContentDispositionFormData("attachment", downloadFileName);
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
//MediaType:互联网媒介类型 contentType:具体请求中的媒体类型信息
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers, HttpStatus.OK);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
1.4 clzEdit
<%@ 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 }/clz/${empty b ? 'add' : 'edit'}" method="post">
--%>
<form action="${pageContext.request.contextPath }/clz/${empty b ? 'valiAdd' : 'edit'}" method="post">
cid:<input type="text" name="cid" value="${b.cid }"><span style="color: pink;">${msg.cid}</span><br>
cname:<input type="text" name="cname" value="${b.cname }"><span style="color: pink;">${msg.cname}</span><br>
cteacher:<input type="text" name="cteacher" value="${b.cteacher }"><span style="color: pink;">${msg.cteacher}</span><br>
<input type="submit">
</form>
</body>
</html>
测试:
若没有任何信息 点击提交 我们的验证就会提示
若填写了 则相反
二、拦截器
2.1什么是拦截器?
SpringMVC的处理器拦截器,类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。
依赖于web框架,在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用。由于拦截器是基于
web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个
controller生命周期之内可以多次调用。
2.2 拦截器与过滤器的区别
过滤器(filter):
1、filter属于Servlet技术,只要是web工程都可以使用
2、filter主要对所有请求过滤
3、filter的执行时机早于Interceptor拦截器(interceptor)
1、interceptor属于SpringMVC技术,必须要有SpringMVC环境才可以使用
2、interceptor通常对处理器Controller进行拦截
3、interceptor只能拦截dispatcherServlet处理的请求
2.3 拦截器说明方法
preHandle方法
作用:用于对拦截到的请求进行预处理,方法接收布尔(true,false)类型的返回值,返回true:放行,false:不放行。
执行时机:在处理器方法执行前执行
方法参数:
1)request请求对象
2)response响应对象
3)handler拦截到的方法处理postHandle方法
作用:用于对拦截到的请求进行后处理,可以在方法中对模型数据和视图进行修改
执行时机:在处理器的方法执行后,视图渲染之前
方法参数:
1)request请求对象
2)response响应对象
3)handler拦截到的处理器方法
4)ModelAndView处理器方法返回的模型和视图对象,可以在方法中修改模型和视图afterCompletion方法
作用:用于在整个流程完成之后进行最后的处理,如果请求流程中有异常,可以在方法中获取对象
执行时机:视图渲染完成后(整个流程结束之后)
方法参数:
1)request请求参数
2)response响应对象
3)handler拦截到的处理器方法
4)ex异常对象
2.4 拦截器使用步骤
1、实现HandlerInterceptor接口 对应实现三个方法
2、完成springmvc.xml中的配置
2.5 应用场景
1、日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等。
2、权限检查:如登录检测,进入处理器检测是否登录,如果没有直接返回到登录页面;
3、性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间(如果有反向代理,如apache可以自动记录);
4、通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个Controller中的处理方法都需要的,我们就可以使用拦截器实现。
OneHandlerInterceptor:
package com.zxw.ssm.intercept;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author zxw
* @site ......
* @company 好男人
* @create 2022-08-20 9:19
*/
public class OneHandlerInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 预处理
System.out.println("[OneHandlerInterceptor] . preHandle");
// 如果login/logout 这个请求、就直接放行
String url = request.getRequestURL().toString();
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("login.jsp");
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// 后处理
System.out.println("[OneHandlerInterceptor] . postHandle...");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 完成后执行
System.out.println("[OneHandlerInterceptor] . afterCompletion...");
}
}
springmvc.xml配置:
<mvc:interceptors> <!– 针对于所有的请求进行拦截–> <bean class="com.zxw.ssm.intercept.OneHandlerInterceptor"></bean> </mvc:interceptors>
测试类HelloController:
二、拦截器链
创建另一个拦截器
package com.zxw.ssm.intercept;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author zxw
* @site ......
* @company 好男人
* @create 2022-08-20 9:19
*/
public class TwoHandlerInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 预处理
System.out.println("[TwoHandlerInterceptor] . preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// 后处理
System.out.println("[TwoHandlerInterceptor] . postHandle...");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 完成后执行
System.out.println("[TwoHandlerInterceptor] . afterCompletion...");
}
}
springmvc.xml配置:
<!-- 配置拦截器链-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.zxw.ssm.intercept.OneHandlerInterceptor"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/clz/**"/>
<bean class="com.zxw.ssm.intercept.TwoHandlerInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
测试: