Spring MVC学习二

11.处理json和HttpMessageConverter

在开发中,我们往往需要服务器返回的数据格式是按照json格式来返回的。

  1. 处理json-@ResponseBody
package com.zzti.springmvc.json;

public class Dog {
    private String name;
    private String address;

    public Dog() {
    }

    public Dog(String name, String address) {
        this.name = name;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}
@Controller
public class JsonController {

    @RequestMapping("/getJson")
    @ResponseBody
    public Dog getJson(){
        Dog dog = new Dog("大黄狗","上海浦东");
        return dog;
    }
}

在这里插入图片描述
2. 处理json-@RequestBody
客户端发送json字符串数据,使用@RequestBody将客户端提交的json数据,封装成JavaBean对象,再把这个Javabean以json对象形式返回

@PostMapping("/save")
@ResponseBody
public User save(@RequestBody User user){
    System.out.println("user= " + user);
    return user;
}
package com.zzti.springmvc.json;

public class Dog {
    private String name;
    private String address;

    public Dog() {
    }

    public Dog(String name, String address) {
        this.name = name;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

在这里插入图片描述
注意细节:

  • 目标方法正常返回需要的数据,可以是一个对象,也可以是一个集合
  • @ResponseBody可以直接写在controller上,这样对所有方法生效

处理JSON-底层实现(HttpMessageConverter)

  1. 使用HttpMessageConverter将请求信息转化并绑定到处理方法的入参中,或将响应的结果转为对应类型的响应信息,Spring提供了两种途径
    a.使用@ResponseBody / @RequestBody对目标方法进行标注
    b.使用HttpEntity / ResponseEntity 作为目标方法的入参或返回值
  2. 当控制器处理方法使用到上述两种方法时,Spring首先根据请求头或响应头的Accept属性选择匹配的HttpMessageConverter,进而根据参数泛型或泛型类型的过滤得到匹配的HttpMessageConverter,若找不到可用的HttpMessageConverter将报错

12. 文件上传和下载

通过返回ResponseEntity的类型,可以实现文件下载的功能

 @RequestMapping("/downFile")
public ResponseEntity<byte[]> downFile(HttpSession session) throws Exception {
    //先获取到你要下载的文件
    InputStream stream = session.getServletContext().getResourceAsStream("WEB-INF/imgs/g1.png");
    byte[] bytes = new byte[stream.available()];
    stream.read(bytes);
    //构建返回的ResponseEntity<byte[]>
    HttpStatus status = HttpStatus.OK;//返回成功
    //根据http协议告诉浏览器,返回的就是一个文件,浏览器就淡出小窗口
    HttpHeaders headers = new HttpHeaders();
    /**
     * context-type 指示响应内容的格式
     * context-disposition 指示如何处理响应内容 (inline[直接在页面显示];attachment[以附件形式下载])
     */
    headers.add("Content-Disposition","attachment;filename=g1.png");
    ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers, status);
    return responseEntity;
}

在这里插入图片描述
Spring MVC中默认没有配置MultipartResolver,因此不能处理文件的上传工作,要是实现上传功能,就需要配置MultipartResolver

<!--配置springmvc文件上传解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    
</bean>
<!--使用Spring提供的过滤器,处理中文乱码-->
<filter>
  <filter-name>CharacterEncodingFilter</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>
</filter>
<filter-mapping>
  <filter-name>CharacterEncodingFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
 @RequestMapping("/fileUpload")
 public String fileUpload(@RequestParam(value = "file") MultipartFile file,
                          HttpServletRequest request) throws Exception{
     String originalFilename = file.getOriginalFilename();
     System.out.println("上传文件名= " + originalFilename);
     String filePath = request.getServletContext().getRealPath("WEV-INF/imgs/" + originalFilename);
     File saveToFile = new File(filePath);
     file.transferTo(saveToFile);
     return "success";
 }

在这里插入图片描述

13. 自定义拦截器

Spring MVC可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能,自定义的拦截器必须实现HandlerInterceptor接口。自定义拦截器有三个方法: preHandler() 在业务处理器处理请求之前被调用,在该方法中对用户请求request进行处理;postHandler() 在目标方法处理完请求后执行;afterCompletion() 在完全处理请求后被调用,可以在该方法中进行一些资源清理的操作。

执行流程:

  1. 如果preHandler(),返回false,则不再执行目标方法,可以在此指定返回页面
  2. postHandler在目标方法被执行后执行,可以在方法中访问到目标方法返回的ModelAndView对象
  3. 若preHandler返回true,则afterCompletion(),在渲染视图之后被执行
  4. 若preHandler返回false,则afterCompletion(),不会被执行
  5. 在配置拦截器时,可以指定拦截器对哪些请求生效,哪些不生效。

在applicationContext-mvc.xml文件中添加如下配置

  <!--配置自定义拦截器-->
    <mvc:interceptors>
        <!--
            第一种方式: 在interceptors配置一个引用,
            指向你需要使用的拦截器(对所有的请求都拦截)
        -->
        <ref bean="myInterceptor01"/>
        <mvc:interceptor>
            <mvc:mapping path="/hi"/>
            <ref bean="myInterceptor01"/>
        </mvc:interceptor>
    </mvc:interceptors>
package com.zzti.springmvc.interceptor;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 完成一个自定义拦截器,如何配置拦截器和拦截器的运行流程
 */
@Component
public class MyInterceptor01 implements HandlerInterceptor {
    /**
     * 1. preHandle()在目标方法执行之前被调用
     * 2. 返回false,就不会再执行目标方法,可以在此响应请求返回给页面
     * 3. 不管返回true,还是false,都会执行当前拦截器之前的拦截器的afterCompletion()
     * 不会执行当前拦截器的afterCompletion()
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("======MyInterceptor01 preHandle()===========");
        return true;
    }

    /**
     * postHandler在目标方法被执行后执行,可以在方法中访问到目标方法返回的ModelAndView对象
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("======MyInterceptor01 postHandle()===========");
    }

    /**
     * 1. 若preHandler返回true,则afterCompletion(),在渲染视图之后被执行
     * 2. 若preHandler返回false,则afterCompletion(),不会被执行
     * 3. 若当前拦截器的下一个拦截器的preHandle()返回false,则在执行下一个拦截器preHandle()后马上被执行
     * 可以访问到目标方法中出现的异常
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("======MyInterceptor01 afterCompletion()===========");
    }
}
package com.zzti.springmvc.interceptor;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/interceptor")
public class FurnController {
    @RequestMapping("/hi")
    public String hi(){
        System.out.println("FurnController hi()");
        return "success";
    }

    @RequestMapping("/hello")
    public String hello(){
        System.out.println("FurnController hello()");
        return "success";
    }
}
=============测试结果===================
======MyInterceptor01 preHandle()===========
FurnController hi()
======MyInterceptor01 postHandle()===========
======MyInterceptor01 afterCompletion()===========

注意事项与细节:
默认配置是所有的目标方法都拦截,也可以指定拦截目标方法
如下只拦截hi

<mvc:interceptor>
    <mvc:mapping path="/hi"/>
    <ref bean="myInterceptor01"/>
</mvc:interceptor>

mvc:mapping 支持通配符,同时指定不对哪些目标方法进行拦截(不拦截/hello())

<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor01"/>
</mvc:interceptor>

14. Spring MVC执行流程

在这里插入图片描述

  • 前端控制器(DispacherServlet); 是整个流程的控制中心,接收请求,响应结果,相当于转发器
  • 处理器映射器(HandlerMapping):根据URL去查找处理器 (Handler),Spring MVC提供了不同的映射器实现不同的映射方式,比如: 配置文件方式、实现接口方式、注解方式;
  • 处理器适配器(HandlerAdapter): 会把处理器包装成适配器,这样就可以支持多种类型的处理器
  • 处理器(Handler/Controller): 程序员自己处理业务逻辑的
  • 视图解析器(ViewResovler): 进行视图解析,多返回的是字符串,进行渲染处理,可以解析成对应的页面,
  • 视图(View): view是一个接口,实现类支持不同的view类型(html/jsp/freemarker…),这个也需要程序员自己开发

具体流程步骤如下:

  1. 用户发送http请求到DispacherServlet,前端控制器收到请求后不自己处理,而是委托给其他的解析器进行处理,作为转发器,进行全局的流程控制
  2. DispacherServlet会先调用HandlerMapping处理器映射器,HandlerMapping会把请求映射成HandlerExecutionChain处理器执行链对象(包含HandlerInterceptor拦截器(多个)、一个Handler对象)这样很容易添加新的映射策略
  3. DispacherServlet调用HandlerAdapter处理器适配器,HandlerAdapter将处理器包装成适配器,从而支持多种类型的处理器(适配器设计模式的应用)
  4. HandlerAdapter调用Handler处理器,处理器中进行一些业务逻辑的实现,HandlerAdapter将会根据适配的结果调用真正的处理器的功能方法,完成功能处理,并返回一个ModeAndView对象(包含模型数据、逻辑视图名)给前端控制器
  5. DispacherServlet调用ViewResovler视图解析器,ViewResovler把逻辑视图名解析为具体的View
  6. View会根据传进来的Model(是一个Map数据结构)模型数据进行渲染,支持多种视图技术
  7. 返回控制权给DispacherServlet,由DispacherServlet返回响应给用户,这样一个流程就结束。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值