framework学习笔记day11---SpringMVC

8 篇文章 0 订阅
5 篇文章 0 订阅

类型转换概述

  • 概述
    • 请求参数绑定的过程中存在数据类型转换的问题
  • 自动类型转换
    • 比如:客户端发送给服务器的是"100",服务器用int来接收。
  • 手动类型转换
    • 有一些数据类型无法自动类型转换,比如:日期。

日期类型格式转换

  • 概述

    • image-20211231092323714

    • SpringMVC有内置一个DateFormatter,默认格式是"yyyy/MM/dd"

  • 代码实现

    <mvc:annotation-driven conversion-service="formattingConversionService"></mvc:annotation-driven>
    
    <bean id="formattingConversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="formatters">
            <set>
                <!--修改内置DateFormatter的格式-->
                <bean class="org.springframework.format.datetime.DateFormatter">
                    <property name="pattern" value="yyyy-MM-dd"></property>
                </bean>
            </set>
        </property>
    </bean>
    
    public class User {
    
        private Integer userId;
        private String userName;
        private String userPwd;
        private Double money;
    
        @DateTimeFormat(pattern = "yyyy-MM-dd")
        private Date birthday;
    }
    

自定义类型转换器

  • 概述

    • 之前是修改内置日期类型转换器的格式,
    • 现在是自定义日期类型转换器。
  • 加粗样式开发步骤

    • ①自定义Convert类实现Convert接口
    • ②编写spring-mvc.xml
      • 配置自定义Convert类
  • ①自定义Convert类实现Convert接口

    /**
     * <S, T> : S: source,原始数据类型 , T: target , 目标数据类型
     */
    public class MyDateConverter implements Converter<String, Date> {
        @Override
        public Date convert(String source) {
            //source : 原始日期字符串
            try {
                Date date = new SimpleDateFormat("yyyy-MM-dd").parse(source);
                return date;
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    
  • ②编写spring-mvc.xml

    <mvc:annotation-driven conversion-service="formattingConversionService"></mvc:annotation-driven>
    <bean id="formattingConversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="com.atguigu.convert.MyDateConverter"></bean>
            </set>
        </property>
    </bean>
    

类型转换BindingResult接口

  • 概述

    • image-20211231100742731

    • 类型转换失败,跳转到一个400错误页面,体验不好;应该要跳转一个自定义错误页面,并展示合适的错误提示信息。

    • BindingResult包含了错误信息。

  • 代码实现

    @RequestMapping("/convert/testConvert01")
    public String testConvert01( User user  ,BindingResult bindingResult, Model model ){
        //出错时,从BindingResult获取错误信息
        if (bindingResult.hasErrors()) {
            FieldError fieldError = bindingResult.getFieldError();
            //birthday
            String fieldName = fieldError.getField();
            String defaultMessage = "日期格式错误!";
            model.addAttribute(fieldName + "ErrorMsg",defaultMessage);
            //跳转到自定义错误页面,并展示错误提示信息
            return "error";
        }
        System.out.println("user = " + user);
        return "index";
    }
    
  • 注意事项

    • An Errors/BindingResult argument is expected to be declared immediately after the model attribute
    • BindingResult接口必须放在javabean属性后面紧挨着,否则报上述错误!!!

表单校验概述

  • 概述
    • 之前,在javaweb阶段,我们使用javascript+正则表达式完成了客户端的表单校验;但是,可以通过一些方式绕过客户端的表单校验。
    • 现在,也需要在服务器代码中加入表单校验。
  • 客户端校验
    • 使用js+正则表达式
  • 服务器校验
    • 使用校验框架

校验框架入门

  • 常用注解

  • 开发步骤

    • ①引入依赖
      • hibernate-validator
    • ②改造javabean
      • 使用validator注解
    • ③编写前端代码
    • ④编写后台代码
  • ①引入依赖

    <dependency>
        <groupId>org.hibernate.validator</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>6.0.17.Final</version>
    </dependency>
    
  • ②改造javabean

    public class User {
    
        private Integer userId;
    
        @NotBlank(message = "账户不能为空!")
        private String userName;
    
        @NotBlank(message = "密码不能为空!")
        private String userPwd;
    
        @NotNull(message = "金额不能为空!")
        @Min(value = 0 , message = "金额不能低于0元")
        @Max(value = 1000000 ,message = "金额不能高于1000000元")
        private Double money;
    
        @DateTimeFormat(pattern = "yyyy-MM-dd")
        private Date birthday;
    
    
        @NotBlank(message = "邮箱不能为空!")
        @Email(message = "邮箱格式错误!")
        private String email;
    
        @NotBlank(message = "手机号不能为空!")
        @Pattern(regexp = "[1]{1}[356789]{1}[0-9]{9}" ,message = "手机号格式错误!")
        private String phoneNum;
    }
    
  • ③编写前端代码

    <form th:action="@{/validator/testValidator1}">
    
        账户:<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>
    
  • ④编写后台代码

    @RequestMapping("/validator/testValidator1")
    public String testValidator1(@Valid User user){
        System.out.println("user = " + user);
        return "index";
    }
    

校验框架引入BindingResult接口

  • 代码实现

    @RequestMapping("/validator/testValidator2")
    public String testValidator2(@Valid User user , BindingResult bindingResult , Model model){
        System.out.println("user = " + user);
        //有错误时,保存错误提示信息,并跳转页面展示
        if (bindingResult.hasErrors()) {
            List<FieldError> fieldErrorList = bindingResult.getFieldErrors();
            for (FieldError fieldError : fieldErrorList) {
                //获取每一个错误信息
                String fieldName = fieldError.getField();
                String errorMsg = fieldError.getDefaultMessage();
                //错误1 : 生日为空!
                //错误2 : 生日格式错误! 需要处理.
                if ("birthday".equals(fieldName) && errorMsg.startsWith("Failed")) {
                    model.addAttribute(fieldName + "ErrorMsg","生日格式错误!");
    
                } else {
                    model.addAttribute(fieldName + "ErrorMsg",errorMsg);
                }
    
            }
            return "demo02";
        }
        return "index";
    }
    
    <form th:action="@{/validator/testValidator2}">
    
        账户:
        <input type="text" name="userName">
        <span th:text="${userNameErrorMsg}" style="color: red"></span>
        <br>
        密码:
        <input type="text" name="userPwd">
        <span th:text="${userPwdErrorMsg}" style="color: red"></span>
    
        <br>
        薪资:<input type="text" name="money">
        <span th:text="${moneyErrorMsg}" style="color: red"></span>
        <br>
        生日:<input type="text" name="birthday">
        <span th:text="${birthdayErrorMsg}" style="color: red"></span>
    
        <br>
        邮箱:<input type="text" name="email">
        <span th:text="${emailErrorMsg}" style="color: red"></span>
    
        <br>
        电话:<input type="text" name="phoneNum">
        <span th:text="${phoneNumErrorMsg}" style="color: red"></span>
        <br>
        <button type="submit">提交</button>
    
    </form>
    

拦截器概述

  • 概述
    • 就是在Handler方法之前执行的组件。
  • 拦截器VS过滤器
    • 相同点
      • 都需要执行过滤和放行
    • 不同点
      • 所在容器不同
        • 拦截器在Spring容器
        • 过滤器在tomcat容器
      • 作用范围不同
        • 拦截器只能拦截Spring容器中的资源
        • 过滤器可以拦截所有资源
      • IOC容器支持
        • 拦截器可以直接使用IOC容器中的资源
        • 过滤器不能直接使用IOC容器中的资源

拦截器入门

  • 常用方法

    • preHandle : 在Handler方法之前执行,预处理
    • postHandle : 在Handler方法之后执行,在视图渲染之前执行
    • afterCompletion : 在Handler方法之后执行,在视图渲染之后执行
  • 开发步骤

    • ①自定义拦截器类实现HandlerInterceptor接口
    • ②编写spring-mvc.xml
      • 配置自定义拦截器类
    • ③代码测试
  • ①自定义拦截器类实现HandlerInterceptor接口

    public class MyInterceptor1 implements HandlerInterceptor {
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            //在Handler方法之前执行
            System.out.println("MyInterceptor1 preHandle");
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            //在Handler方法之后执行,渲染视图之前执行
            System.out.println("MyInterceptor1 postHandle");
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            //在Handler方法之后执行,渲染视图之后执行
            System.out.println("MyInterceptor1 afterCompletion");
        }
    }
    
  • ②编写spring-mvc.xml

    <mvc:interceptors>
        <bean class="com.atguigu.interceptor.MyInterceptor1"></bean>
    </mvc:interceptors>
    
  • ③代码测试

拦截器拦截路径

  • 概述

    • 默认情况下,拦截器会拦截Spring容器中的所有资源。
  • 代码实现

    <mvc:interceptors>
        <!--精确匹配-->
        <!--
        <mvc:interceptor>
            <mvc:mapping path="/interceptor/testInterceptor1"/>
            <bean class="com.atguigu.interceptor.MyInterceptor1"></bean>
        </mvc:interceptor>
        -->
        <!--匹配单层路径-->
        <!--
        <mvc:interceptor>
            <mvc:mapping path="/interceptor/*"/>
            <bean class="com.atguigu.interceptor.MyInterceptor1"></bean>
        </mvc:interceptor>
        -->
        <!--匹配多层路径-->
        <!--
        <mvc:interceptor>
            <mvc:mapping path="/interceptor/**"/>
            <bean class="com.atguigu.interceptor.MyInterceptor1"></bean>
        </mvc:interceptor>
        -->
        <mvc:interceptor>
            <mvc:mapping path="/interceptor/**"/>
            <mvc:exclude-mapping path="/interceptor/testInterceptor1"/>
            <bean class="com.atguigu.interceptor.MyInterceptor1"></bean>
        </mvc:interceptor>
    
    </mvc:interceptors>
    

多拦截器配置

  • 总结

    • 先配置,先拦截,后放行。
  • 代码实现

    <mvc:interceptors>
    
        <mvc:interceptor>
            <mvc:mapping path="/interceptor/**"/>
            <bean class="com.atguigu.interceptor.MyInterceptor1"></bean>
        </mvc:interceptor>
    
        <mvc:interceptor>
            <mvc:mapping path="/interceptor/**"/>
            <bean class="com.atguigu.interceptor.MyInterceptor2"></bean>
        </mvc:interceptor>
    
    </mvc:interceptors>
    

文件上传

  • 概述

    • 通过浏览器将本地电脑中文件上传到服务器电脑中。
  • 开发步骤

    • ①引入相关依赖
      • fileupload
    • ②编写前端代码(三要素)
      • 请求方式=post
      • enctype=“multipart/form-data”
      • 文件上传项
    • ③编写spring-mvc.xml
      • 配置文件上传解析器
    • ④编写后台代码
      • 编写文件上传逻辑代码
  • ①引入相关依赖

    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.4</version>
    </dependency>
    
  • ②编写前端代码(三要素)

    <form  th:action="@{/file/upload}" enctype="multipart/form-data" method="post">
    
        文件:<input type="file" name="myFile"><br>
        <button type="submit">上传</button>
    
    
    </form>
    
  • ③编写spring-mvc.xml

    <bean id="multipartResolver"
          class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 设置上传文件的最大尺寸为5MB -->
        <property name="maxUploadSize">
            <!--1TB、1GB、1MB、1KB、1byte-->
            <value>5242880</value>
        </property>
    </bean>
    
  • ④编写后台代码

    @Autowired
    private ServletContext servletContext;
    
    @RequestMapping("/file/upload")
    public String upload(MultipartFile myFile) throws IOException {
        //myFile : 浏览器上传文件的信息
        //获取upload目录的真实磁盘路径
        String uploadDirPath = servletContext.getRealPath("upload");
        File uploadDirFile = new File(uploadDirPath);
        if (!uploadDirFile.exists()){
            //创建upload目录
            uploadDirFile.mkdir();
        }
        //girl1.jpg
        String originalFilename = myFile.getOriginalFilename();
        //fdsafadsfdsaf.jpg
        String[] fileNames = originalFilename.split("[\\.]");
        String newFileName = UUID.randomUUID().toString().replaceAll("-","") + "." + fileNames[1];
        File destFile = new File(uploadDirPath + File.separator + newFileName);
        myFile.transferTo(destFile);
    
        return "index";
    }
    

文件下载

  • 开发步骤

    • ①读取下载文件的内容
    • ②设置响应头
      • Content-Type(下载文件类型)
      • Content-Disposition(弹出下载窗口)
    • ③设置下载状态
  • 代码实现

    @RequestMapping("/file/download")
    public ResponseEntity<byte[]> download(String fileName) throws Exception {
    
        //①读取下载文件的内容,bytes : 下载文件的内容
        String downloadPath = servletContext.getRealPath("upload") + File.separator + fileName;
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(downloadPath));
        byte[] bytes = new byte[bis.available()];
        bis.read(bytes);
        //②设置响应头, headers : 设置响应头 , Content-Type(下载文件类型) , Content-Disposition(弹出下载窗口)
        MultiValueMap<String, String> headers = new HttpHeaders();
        headers.add("Content-Type", servletContext.getMimeType(fileName));
        headers.add("Content-Disposition", "attachement;filename=" + fileName);
        //③设置下载状态, status : 下载的状态
        HttpStatus status = HttpStatus.OK;
        return new ResponseEntity<>(bytes, headers, status);
    }
    

ufferedInputStream(new FileInputStream(downloadPath));
byte[] bytes = new byte[bis.available()];
bis.read(bytes);
//②设置响应头, headers : 设置响应头 , Content-Type(下载文件类型) , Content-Disposition(弹出下载窗口)
MultiValueMap<String, String> headers = new HttpHeaders();
headers.add(“Content-Type”, servletContext.getMimeType(fileName));
headers.add(“Content-Disposition”, “attachement;filename=” + fileName);
//③设置下载状态, status : 下载的状态
HttpStatus status = HttpStatus.OK;
return new ResponseEntity<>(bytes, headers, status);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值