文章目录
01-表单校验概述(掌握)
- 概述
- 我们在JavaWeb阶段已经学习过如何在客户端做表单校验,但是仅仅只有客户端表单校验还是不够 的,很多时候,可以绕过客户端,直接向服务器发起请求,所以这个时候就需要服务器端的表单校 验。
- 客户端校验
- 客户端,使用js技术,利用正则表达式校验
- 服务器校验
- 服务端,使用校验框架,完成逻辑校验
02-表单校验框架常用注解(掌握)
- 常用注解
- @Valid : 标注对象是否开启表单校验
- @NotBlank : 校验String字符串是否为空
- @NotNull : 校验引用数据类型是否为空
- @NotEmpty : 校验集合中的元素长度是否为0
- @Min : 限制最小值
- @Max : 限制最大值
- @Email : 规定是邮箱格式
- @Pattern : 指定使用自定义的正则表达式
03-表单校验框架基本使用(掌握)
-
概述
- 使用hibernate-validator完成表单校验.
-
开发步骤
- ①引入依赖
- ②编写前端代码
- ③编写JavaBean实体类
- ④编写ValidatorController
-
①引入依赖
<dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.17.Final</version> </dependency>
-
②编写前端代码
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>03-表单校验框架基本使用</title> </head> <body> <form th:action="@{/validator/test1}"> 账户:<input type="text" name="userName"><br> 密码:<input type="text" name="userPwd"><br> 金额:<input type="text" name="money"><br> 生日:<input type="text" name="birthday"><br> 邮箱:<input type="text" name="email"><br> 电话:<input type="text" name="phoneNum"><br> <button type="submit">提交</button> </form> </body> </html>
-
③编写JavaBean实体类
@Data @NoArgsConstructor @AllArgsConstructor public class User { @NotBlank(message = "账户不能为空!") private String userName; @NotBlank(message = "密码不能为空!") private String userPwd; @NotNull(message = "金额不能为空!") @Min(value = 0, message = "金额不能低于0元!") @Max(value = 5000,message = "金额不能高于5000元!") private Double money; @NotNull(message = "生日不能为空!") @DateTimeFormat(pattern = "yyyy-MM-dd") private Date birthday; @NotBlank(message = "邮箱不能为空!") @Email private String email; @NotBlank(message = "手机号不能为空!") @Pattern(regexp = "[1]{1}[356789]{1}[0-9]{9}",message = "手机号格式错误!") private String phoneNum; }
-
④编写ValidatorController
@Controller public class ValidatorController { /** * 03-表单校验框架基本使用 * @param user * @return */ @RequestMapping("/validator/test1") public String test1(@Valid User user){ System.out.println("user = " + user); return "index"; } }
-
存在问题
- 当校验不通过时,默认会跳转到400错误页面,体验不好.
04-表单校验框架使用优化(掌握)
-
概述
- 使用BindingResult接口获取错误信息,并展示到错误页面.
-
代码实现
@RequestMapping("/validator/test1") public String test1(@Valid User user, BindingResult result, Model model) { if (result.hasErrors()) { //有错,获取所有错误信息 List<FieldError> fieldErrorList = result.getFieldErrors(); for (FieldError fieldError : fieldErrorList) { String errorMsg = fieldError.getDefaultMessage(); model.addAttribute(fieldError.getField() + "ErrorMsg", errorMsg); } return "demo01"; } System.out.println("user = " + user); return "index"; }
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>03-表单校验框架基本使用</title> </head> <body> <form th:action="@{/validator/test1}"> 账户: <input type="text" name="userName"> <span style="color: red" th:text="${userNameErrorMsg}"></span> <br> 密码: <input type="text" name="userPwd"> <span style="color: red" th:text="${userPwdErrorMsg}"></span> <br> 金额: <input type="text" name="money"> <span style="color: red" th:text="${moneyErrorMsg}"></span> <br> 生日: <input type="text" name="birthday"> <span style="color: red" th:text="${birthdayErrorMsg}"></span> <br> 邮箱: <input type="text" name="email"> <span style="color: red" th:text="${emailErrorMsg}"></span> <br> 电话: <input type="text" name="phoneNum"> <span style="color: red" th:text="${phoneNumErrorMsg}"></span> <br> <button type="submit">提交</button> </form> </body> </html>
-
存在问题
- ①表单校验失败,数据回显问题
- ②生日格式不对,错误提示信息问题
05-表单校验框架使用完整版(掌握)
-
代码实现
@RequestMapping("/validator/test1") public String test1(@Valid User user, BindingResult result, Model model) { if (result.hasErrors()) { model.addAttribute("user", user); //有错,获取所有错误信息 List<FieldError> fieldErrorList = result.getFieldErrors(); for (FieldError fieldError : fieldErrorList) { String errorMsg = fieldError.getDefaultMessage(); String fieldName = fieldError.getField(); if (fieldName.equals("birthday")) { //birthday字段 if (errorMsg.startsWith("Failed to")) { //格式错误 , 使用自定义的错误提示信息 model.addAttribute("birthdayErrorMsg","生日格式错误!"); }else { model.addAttribute( fieldName + "ErrorMsg", errorMsg); } } else { //其他字段 model.addAttribute( fieldName + "ErrorMsg", errorMsg); } } return "demo01"; } System.out.println("user = " + user); return "index"; }
06-拦截器概述(掌握)
- 概述
- 在程序中,使用拦截器在请求到达具体 handler 方法前,统一执行检测。
- 拦截器 VS 过滤器
- 相同点
- 都可以执行过滤
- 不同点
- 工作平台不同
- 拦截器工作在Spring容器
- 过滤器工作在Servlet容器
- 拦截范围不同
- 拦截器只能拦截Spring容器中的资源
- 过滤器可以拦截所有资源
- IOC容器支持不同
- 拦截器可以直接使用IOC容器中的资源
- 过滤器只能间接使用IOC容器中的资源
- 工作平台不同
- 相同点
07-拦截器入门案例(掌握)
-
常用方法
- preHandle
- 在处理器方法之前执行,如果返回值为true就放行,否则就不放行.
- postHandle
- 在处理器方法之后执行,在渲染视图之前执行.
- afterCompletion
- 在处理器方法之后执行,在渲染视图之后执行.
- preHandle
-
开发步骤
- ①自定义HandlerInterceptor类实现HandlerInterceptor接口
- 重写方法
- ②编写spring-mvc.xml
- 配置HandlerInterceptor类
- ①自定义HandlerInterceptor类实现HandlerInterceptor接口
-
执行流程
-
①自定义HandlerInterceptor类实现HandlerInterceptor接口
public class MyInterceptor1 implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("MyInterceptor1 preHandle"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("MyInterceptor1 postHandle"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("MyInterceptor1 afterCompletion"); } }
-
②编写spring-mvc.xml
<mvc:interceptors> <bean class="com.panghu.interceptor.MyInterceptor1"></bean> </mvc:interceptors>
08-拦截器拦截路径(掌握)
-
精确拦截
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/interceptor/test1"/> <bean class="com.panghu.interceptor.MyInterceptor2"></bean> </mvc:interceptor> </mvc:interceptors>
-
单级路径
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/interceptor/*"/> <bean class="com.panghu.interceptor.MyInterceptor2"></bean> </mvc:interceptor> </mvc:interceptors>
-
多级路径
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/interceptor/**"/> <bean class="com.panghu.interceptor.MyInterceptor2"></bean> </mvc:interceptor> </mvc:interceptors>
-
不拦截路径
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <mvc:exclude-mapping path="/interceptor/test2"/> <bean class="com.panghu.interceptor.MyInterceptor2"></bean> </mvc:interceptor> </mvc:interceptors>
09-多拦截器配置(掌握)
-
概述
- 先配置,先拦截,后放行.
-
代码实现
<!-- <mvc:interceptors> <bean class="com.atguigu.interceptor.MyInterceptor3"></bean> <bean class="com.panghu.interceptor.MyInterceptor4"></bean> </mvc:interceptors> --> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.panghu.interceptor.MyInterceptor3"></bean> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.panghu.interceptor.MyInterceptor4"></bean> </mvc:interceptor> </mvc:interceptors>
10-多拦截器工作原理(掌握)
- 工作原理
11-文件上传(掌握)
-
概述
- 将本地电脑中的文件传输到服务器中.
-
开发步骤
- ①引入依赖
- ②编写前端代码
- 2.1,请求方式=post
- 2.2,enctype=“multipart/form-data”
- 2.3,文件上传项
- ③编写spring-mvc.xml
- 配置文件上传解析器
- ④定义FileController
- 完成文件上传功能
-
①引入依赖
<dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency>
-
②编写前端代码
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>11-文件上传</title> </head> <body> <form th:action="@{/file/upload}" method="post" enctype="multipart/form-data"> 图片:<input type="file" name="myPic"><br> <button type="submit">提交</button> </form> </body> </html>
-
③编写spring-mvc.xml
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!--上传文件最大10M--> <property name="maxUploadSize" value="10485760"></property> </bean>
-
④定义FileController
@RequestMapping("/file/upload") public String upload(MultipartFile myPic) throws IOException { System.out.println("myPic = " + myPic); File dirFile = new File(servletContext.getRealPath("upload")); System.out.println("dirFile = " + dirFile); if (!dirFile.exists()) { //创建upload文件夹 dirFile.mkdir(); } String fileName = myPic.getOriginalFilename(); File destFile = new File(dirFile, fileName); myPic.transferTo(destFile); return "index"; }
12-文件上传优化(掌握)
-
概述
- ①上传文件中文乱码
- ②上传文件名称重复覆盖
-
代码实现
<filter> <filter-name>encoding</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> <init-param> <param-name>forceRequestEncoding</param-name> <param-value>true</param-value> </init-param> </filter>
@RequestMapping("/file/upload") public String upload(MultipartFile myPic) throws IOException { System.out.println("myPic = " + myPic); File dirFile = new File(servletContext.getRealPath("upload")); System.out.println("dirFile = " + dirFile); if (!dirFile.exists()) { //创建upload文件夹 dirFile.mkdir(); } //String fileName = myPic.getOriginalFilename(); String[] split = myPic.getOriginalFilename().split("\\."); String fileName = UUID.randomUUID().toString().replace("-", "") + "." + split[1]; File destFile = new File(dirFile, fileName); myPic.transferTo(destFile); return "index"; }
13-文件下载(掌握)
-
概述
- 将服务器中的文件传输到本地电脑中.
-
开发步骤
- ①获取下载文件的名称
- ②告诉浏览器下载文件的mimeType
- 设置Content-Type响应头
- ③告诉浏览器弹出下载窗口
- 设置Content-Disposition响应头
- ④IO流读写
-
代码实现
@RequestMapping("/file/download") public ResponseEntity<byte[]> download(String fileName) throws Exception { //①body : 下载文件的数据 HttpHeaders headers = new HttpHeaders(); String filePath = servletContext.getRealPath("upload/" + fileName); FileInputStream fis = new FileInputStream(filePath); int fileSize = fis.available(); byte[] body = new byte[fileSize]; new BufferedInputStream(fis).read(body); //②headers : 设置响应头 //设置mimeType headers.add("Content-Type",servletContext.getMimeType(fileName)); //弹出下载窗口 String newFile = URLEncoder.encode(fileName,"UTF-8"); headers.add("Content-Disposition","attachement;filename=" + newFile); //③status : 下载文件状态 HttpStatus ok = HttpStatus.OK; return new ResponseEntity<>(body, headers, ok); }
14-Restful风格介绍(掌握)
-
WebAPI
- 如果一个URL返回的不包含HTML,而是数据,那么这个URL就是一个WebAPI(web接口)
-
Restful风格
http://localhost:8080/day22/user/selectUserById?id=1 http://localhost:8080/day22/user/deleteUserById?id=2 http://localhost:8080/day22/user/1(GET) http://localhost:8080/day22/user/2(DELETE)
- 查询=GET,添加=POST,删除=DELETE,修改=PUT
- 返回的数据是json
15-HiddenHttpMethodFilter过滤器(掌握)
-
概述
- 默认情况下,form表单支持get和post请求,如果需要增加请求方式,需要使用HiddenHttpMethodFilter
-
代码实现
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>15-HiddenHttpMethodFilter过滤器</title> </head> <body> <form th:action="@{/restful/test1}" method="get"> 账户:<input type="text" name="userName"><br> <button type="submit">get请求</button> </form> <form th:action="@{/restful/test2}" method="post"> 账户:<input type="text" name="userName"><br> <button type="submit">post请求</button> </form> <form th:action="@{/restful/test3}" method="post"> <input type="hidden" name="_method" value="delete"> 账户:<input type="text" name="userName"><br> <button type="submit">delete请求</button> </form> <form th:action="@{/restful/test4}" method="post"> <input type="hidden" name="_method" value="put"> 账户:<input type="text" name="userName"><br> <button type="submit">put请求</button> </form> </body> </html>
@Controller public class RestfulController { /** * get请求 * @return */ @GetMapping("/restful/test1") public String test1(String userName){ System.out.println("get userName = " + userName); return "index"; } @PostMapping("/restful/test2") public String test2(String userName){ System.out.println("post userName = " + userName); return "index"; } @DeleteMapping("/restful/test3") public String test3(String userName){ System.out.println("delete userName = " + userName); return "index"; } @PutMapping("/restful/test4") public String test4(String userName){ System.out.println("put userName = " + userName); return "index"; } }
-
注意事项
- 必须使用post模拟delete,put请求