SpringMVC03

类型转换器

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

 String---->int/float/double

 String------>boolean类型

全局类型转换器

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

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

2.Mvc:annotation-driven标签配置一个converservice-service属性
SpringMVC03_第1张图片

 


 3.自定义一个类实现converter接口

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

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>



"UTF-8">
Insert title here


    "user/test03?birth=1994-11-29">把字符串转为日期
    
"user/test02" method="post"> 姓名:"text" name="username">
性别:"radio" name="sex" value="1">"radio" name="sex" value="0">女
年龄:"text" name="age">
工资:"text" name="salary">
生日:"text" name="birthday">
"submit" value="提交">
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{
    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{
    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";
    }

SpringMVC03_第2张图片

不使用注解:

SpringMVC03_第3张图片

 使用注解:类上加注解

 

 xml文件:

SpringMVC03_第4张图片

  输出结果:

例子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"%>



"UTF-8">
Insert title here


    
"file/upload" method="post" enctype="multipart/form-data"> 姓名:"text" name="username">
头像:"file" name="file">
"submit" value="提交">

  后端要求:

      导入文件上传所需要的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;
    }

 

 SpringMVC03_第5张图片

文件下载

  文件下载要求:

      返回值类型必须为ResponseEntity类型

      设置两个响应头信息

SpringMVC03_第6张图片

  @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 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【过滤器】,是在请求到达目标方法之前拦截请求,然后进行过滤、权限验证。类似于现实中安检员。

SpringMVC03_第7张图片

 

具体实现:

  自定义一个类,实现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标签内部配置该拦截器对象

执行流程图:

 SpringMVC03_第8张图片

多拦截器的执行顺序问题

SpringMVC03_第9张图片

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

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

 SpringMVC03_第10张图片

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

SpringMVC03_第11张图片

 

 

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

SpringMVC03_第12张图片

 

 

SpringMVC03_第13张图片

 解析1:

1用户发送请求给前端控制器(Dispatcherservlet),前端控制器接收到请求后委托给其他的解析器进行处理,进行全局的流程控制
2.需要根据请求url查找处理器,于是前端控制器找到处理器映射器(HandlerMapper),HandlerMapper会把请求映射为HandlerExecutionChain对象HandlerExecutionChain(包含一个handler对象,多个HanndlerInterceptor对象拦截器)返回给前端控制器
3前端控制器拿到handler之后,找到处理器适配器HandlerAdapter,适配器能支持多种类型的处理器,适配器会根据适配的结果找到真正的处理器完成功能处理。处理器会返回ModelAndView对象给HandlerAdapter(包括模型数据和逻辑视图名),通过HandlerAdapter返回ModelAndView对象给前端控制器
4前端控制器请求视图解析器ViewResolver来解析成具体的视图,解析器生成视图对象返回给前端控制器
5.前端控制器把返回的视图对象传给View,View通过传进来的Model模型数据进行渲染
6.返回控制权给前端控制器,前端控制器返回响应给用户,结束

 解析2:

用户发起请求到前端控制器(DispatcherServlet),该控制器会过滤出哪些请求可以访问Servlet、哪些不能访问。就是url-pattern的作用,并且会加载springmvc.xml配置文件。
前端控制器会找到处理器映射器(HandlerMapping),通过HandlerMapping完成url到controller映射的组件,简单来说,就是将在springmvc.xml中配置的或者注解的url与对应的处理类找到并进行存储,用map这样的方式来存储。
HandlerMapping有了映射关系,并且找到url对应的处理器,HandlerMapping就会将其处理器(Handler)返回,在返回前,会加上很多拦截器。
DispatcherServlet拿到Handler后,找到HandlerAdapter(处理器适配器),通过它来访问处理器,并执行处理器。
执行处理器
处理器会返回一个ModelAndView对象给HandlerAdapter
通过HandlerAdapter将ModelAndView对象返回给前端控制器(DispatcherServlet)
前端控制器请求视图解析器(ViewResolver)去进行视图解析,根据逻辑视图名解析成真正的视图(jsp),其实就是将ModelAndView对象中存放视图的名称进行查找,找到对应的页面形成视图对象
返回视图对象到前端控制器。
视图渲染,就是将ModelAndView对象中的数据放到request域中,用来让页面加载数据的。
通过第8步,通过名称找到了对应的页面,通过第10步,request域中有了所需要的数据,那么就能够进行视图渲染了。最后将其返回即可。

解析3:

核心架构的具体流程步骤如下:
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返回响应给用户,到此一个流程结束。

你可能感兴趣的:(SpringMVC03)