Day_10 SpringMVC

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
      • 在处理器方法之后执行,在渲染视图之后执行.
  • 开发步骤

    • ①自定义HandlerInterceptor类实现HandlerInterceptor接口
      • 重写方法
    • ②编写spring-mvc.xml
      • 配置HandlerInterceptor类
  • 执行流程

    • image-20220402104750701
  • ①自定义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请求
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值