类型转换器

SpringMVC实际上自带了一些简单的类型转换器:

 String---->int/float/double

 String------>boolean类型

全局类型转换器

全局类型转换器:在springmvc.xml配置一次,在任意controller层都可以使用。

1.在springmvc的配置文件中配置一个FormattingConversionServiceFactoryBean

2.Mvc:annotation-driven标签配置一个converservice-service属性

 3.自定义一个类实现converter<S,T>接口

例子1:通过form表单获取数据

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <a href="user/test03?birth=1994-11-29">把字符串转为日期</a>
    <form action="user/test02" method="post">
        姓名:<input type="text" name="username"><br>
        性别:<input type="radio" name="sex" value="1"><input type="radio" name="sex" value="0">女    <br>
        年龄:<input type="text" name="age"><br>
        工资:<input type="text" name="salary"><br>
        生日:<input type="text" name="birthday"><br>
        <input type="submit" value="提交">
    </form>
</body>
</html>
public class User {
    private String username;
    private boolean sex;
    private Integer age;
    private double salary;
    private Date birthday;
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public boolean isSex() {
        return sex;
    }
    public void setSex(boolean sex) {
        this.sex = sex;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    public double getSalary() {
        return salary;
    }
    public void setSalary(double salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "User [username=" + username + ", sex=" + sex + ", age=" + age + ", salary=" + salary + ", birthday="
                + birthday + "]";
    }
}
public class DateTimeConverter implements Converter<String, Date>{
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    @Override
    public Date convert(String arg0) {
        try {
            return sdf.parse(arg0);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }
public class NumberConverter implements Converter<String, Double>{
    DecimalFormat df = new DecimalFormat("###,###.##");
    @Override
    public Double convert(String arg0) {
        try {
        Number parse = df.parse(arg0);
        return parse.doubleValue();
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
  @RequestMapping("test02")
    public String test02(User user) {
        System.out.println("全局数据转换:"+user);
        return "success";
    }

不使用注解:

 使用注解:类上加注解

 xml文件:

  输出结果:

例子2:通过a标签获取数据

@RequestMapping("test04")
    public String test04(Date birth) {
        System.out.println("全局数据类型转换"+birth);
        return "success";
    }

输出结果:

 局部类型转换器

局部类型转换器:在controller层的方法上每一次使用都需要配置一次。

@DateTimeFormat:时间类型的类型转换器,指定pattern属性值

@NumberFormat:数值类型的类型转换器

例子1:通过form表单获取数据

@DateTimeFormat注解可以放在方法参数上

也可以放在User类的属性上

 例子2:通过a标签

输出结果:

文件上传与下载

 1 文件上传

  前端页面:

      必须发送post请求

      Form表单的encytype=“multipart/form-data”

      type=file

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <form action="file/upload" method="post" enctype="multipart/form-data">
        姓名:<input type="text" name="username"><br>
        头像:<input type="file" name="file"><br>
        <input type="submit" value="提交">
    </form>
</body>
</html>

  后端要求:

      导入文件上传所需要的jar包:commons-fileupload.jar 和commons-io.jar

      springmvc.xml配置一个多媒体解析器:CommonsMultiPartResolver

      

       controller层的方法上使用MultiPartFile类型的参数接收一个文件

  @RequestMapping("/upload")
    public ModelAndView upload(MultipartFile file,HttpServletRequest request,String username) throws IOException {
        ServletContext context = request.getServletContext();
        String realPath = context.getRealPath("/upload");
        File directory = new File(realPath);
        if(!directory.exists()) {
            directory.mkdirs();
        }
        String fileName = UUID.randomUUID().toString().replaceAll("-", "")+file.getOriginalFilename();
        FileOutputStream fos = new FileOutputStream(realPath+"/"+ fileName);
        InputStream fis = file.getInputStream();
        IOUtils.copy(fis, fos);
        fis.close();
        fos.close();
        ModelAndView mv = new ModelAndView();
        mv.setViewName("success");
        mv.addObject("fileName",fileName);
        return mv;
    }

文件下载

  文件下载要求:

      返回值类型必须为ResponseEntity类型

      设置两个响应头信息

  @RequestMapping("/download")
    public ResponseEntity<byte[]> download(HttpServletRequest request) throws IOException {
        String fileName = "风吹麦浪.mp3";
        String realPath = request.getServletContext().getRealPath("/WEB-INF/"+fileName);
        FileInputStream fis = new FileInputStream(new File(realPath));
        byte[] body = new byte[fis.available()];
        fis.read(body);
    
fileName = new String(fileName.getBytes("gbk"),"iso8859-1");
     MultiValueMap<String, String> headers = new HttpHeaders();
     headers.add(
"Content-Disposition", "attachment;filename="+fileName);
     HttpStatus statusCode
= HttpStatus.OK;
     ResponseEntity
<byte[]> responseEntity = new ResponseEntity<byte[]>(body, headers, statusCode);
     return responseEntity;
   }

 拦截器[Interceptor]

 拦截器简介及实现

拦截器类似于javaweb学过的filter【过滤器】,是在请求到达目标方法之前拦截请求,然后进行过滤、权限验证。类似于现实中安检员。

具体实现:

  自定义一个类,实现HandlerInterceptor接口

public class FirstInterceptor implements HandlerInterceptor {

    /**
     * preHandle:在目标方法执行之前执行
     *     返回值:boolean类型,true表示放行该请求,false表示拦截该请求
     *     作用:日志、权限验证、获取连接
     */
    @Override
    public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
         System.out.println("FirstInterceptor preHandle");
        return true;
    }
    /**
     * postHandle:在目标handler方法执行之后,在视图渲染(render)之前【给页面填充数据】执行
     *    作用:修改域中的值,用的不多
     */
    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
            throws Exception {
        // TODO Auto-generated method stub
        System.out.println("FirstInterceptor postHandle");
    }
    /**
     * afterCompletion:在目标handler方法执行之后,在视图渲染(render)之后【给页面填充数据】执行
     *     作用:释放资源,用的不多。
     */
    @Override
    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
            throws Exception {
        System.out.println("FirstInterceptor afterCompletion");
    }
}

   在springmvc的配置文件中通过mvc:interceptors标签内部配置该拦截器对象

执行流程图:

多拦截器的执行顺序问题

问题1:拦截器的顺序实际上是由springmvc.xml文件中配置的顺序决定的。

问题2:拦截器也可以只拦截某些指定的请求。具体配置如下

问题3:拦截器中各个方法的执行顺序,是由springmvc框架源码决定的和前面学过的aop有点区别

  SpringMVC的运行流程图及源码(***)

核心架构的具体流程步骤如下:
1、  首先用户发送请求——>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;
2、  DispatcherServlet——>HandlerMapping, HandlerMapping将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象,通过这种策略模式,很容易添加新的映射策略;
3、  DispatcherServlet——>HandlerAdapter,HandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;
4、  HandlerAdapter——>处理器功能处理方法的调用,HandlerAdapter将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView对象(包含模型数据、逻辑视图名);
5、  ModelAndView的逻辑视图名——> ViewResolver, ViewResolver将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;
6、  View——>渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构,因此很容易支持其他视图技术;
7、返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。
12-14 06:54
查看更多