博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
javaweb实训第六天上午——JSON&SpringMVC进阶
阅读量:2069 次
发布时间:2019-04-29

本文共 10074 字,大约阅读时间需要 33 分钟。

JSON&SpringMVC进阶

1.课程介绍

  1. JSON; (了解)
  2. SpringMVC返回JSON; (掌握)
  3. SpringMVC文件上传、下载; (掌握)
  4. SpringMVC拦截器; (掌握)
  5. SpringMVC执行流程; (掌握)

2.JSON

2.1.JSON概述

  1. 在实际开发中,通常需要和别的系统交换数据,数据交换的格式通常有XML和JSON等;
  2. JSON(JavaScript Object Notation:JavaScript对象表示法)是一种基于JavaScript 语法开放的轻量级数据交换格式,使用js语法来描述数据对象;
  3. JSON作为一个轻量级的数据格式,相对于XML,文档更小,结构清晰简洁,读写效率更高,XML需要很多的标签,在数据传输的时候无疑会消耗更多网络资源和流量:
    (1)用XML表示一个对象:
tom
20
5000.0

(2)用JSON表示一个对象:{“id”:1,“name”:“tom”,“salary”:5000.0}

2.2.JSON语法

2.2.1.如何用JSON表示一个对象

简单对象:

var obj={“name”:“tom”,“age”:34}; alert(obj.name); //tom

复杂对象:

var obj={“name”:“vikey”,“address”:{“city”:“成都”,“street”:“九眼桥”,“room”:“215”}}; alert(obj.address.street); //九眼桥

2.2.2.如何用JSON表示一个数组

语法:

var obj = [value,value,value]value可以是ob

ject、数组、简单数据类型(string、number、boolean等)、json对象

例子:

var obj = [{
”id”:1,”name”:”tom1”,”salary”:5000.0},{
”id”:2,”name”:”tom2”,”salary”:6000.0},{
”id”:3,”name”:”tom3”,”salary”:7000.0}]alert(obj.length);alert(obj[1].name);

遍历:

注意:json中数据的属性名必须用双引号或单引号引起来(双引号是标准格式,单引号是非标准格式),属性值如果是字符型必须用引号引起来;

2.2.3.JSON字符串和JSON对象

JSON字符串:var obj = ‘{
“id”:1,”name”:”tom”,”salary”:5000.0}’;alert(obj.id); XJson对象:var obj = {
“id”:1,”name”:”tom”,”salary”:5000.0};alert(obj.id); //1alert(obj.name); //tom

3.SpringMVC返回JSON

1.有时候后台需要向前台传递JSON格式的数据,那么这个时候要把Java对象转换为JSON,就需要第三方的支持:

  (1)Jackson:http://jackson.codehaus.org/
  (2)JSON-lib:http://json-lib.sourceforge.net/
  (3)Gson:http://code.google.com/p/google-gson/
  (4)FastJson阿里开源

3.1.Java对象转成JSON格式的数据

1.加入jackson工具包:

在这里插入图片描述

2.后台编程(使用@ResponseBody注解):

在这里插入图片描述

3.2.Json中对日期格式的特殊处理

从后台向前台:

(1)默认返回的日期格式为时间戳,而在前台我们希望显示出指定规则的日期字符串:
  默认:{“name”:“小明哥”,“birthdate”:121223223}
  期望: {“name”:“小明哥”,“birthdate”:“2025-12-12 14:12:12”}
(2)在日期get属性,字段上,添加一个格式化注解
  import com.fasterxml.jackson.annotation.JsonFormat;
  @JsonFormat(pattern=“yyyy-MM-dd HH:mm:ss”,timezone=“GMT+8”)
从前台向后台:
(1)在后台模型的setter方法上,添加注解:
  @DateTimeFormat(pattern=“yyyy-MM-dd HH:mm:ss”)
(2)访问地址:localhost:8080/jsonV587?birthDay=2017-06-13 16:50:53
(3)后台接收:

@RequestMapping("/getJson")@ResponseBody//将返回的数据自动转换成json格式的数据,而且是用了@ResponseBody,不会经过视图解析器public Date getJson(User user){
//接收的用对象接收,直接用Date类型的参数会报400(请求无效) System.out.println(user.getBirthday()); return user.getBirthday();}

3.3.注意事项

  1. 出现406状态异常:缺少jar包,加入jackson的jar包即可;
  2. 使用@ResponseBody注解之后,不会经过视图解析器;
  3. 如果在ie中测试,会弹出下载文件的窗口,可以在spring-mvc.xml的
中加入以下配置解决:
text/html;charset=UTF-8

4.文件上传与下载

4.1.文件上传

  1. 文件上传:指的是将本地的文件复制到服务器上;
  2. SpringMvc中的文件上传是对原生文件上传的封装,目的是,较少代码量,提高开发效率;
  3. 文件上传三要素:
      (1)表单的提交的方式必须是POST请求(get请求对提交的数据)
      (2)表单中必须有一个文件上传项:,文件上传项必须有name属性和值;
      (3)表单的enctype属性的值必须是multipart/form-data

4.1.1.添加jar文件

  1. 由于SpringMVC自己没有实现文件上传,它使用的是apache.commons.fileupload
      com.springsource.org.apache.commons.fileupload-1.2.0.jar
      com.springsource.org.apache.commons.io-1.4.0.jar

4.1.2.jsp页面

在这里插入图片描述

4.1.3.配置上传解析器

SpringMVC使用MultipartFile来进行文件上传,所以我们首先要配置MultipartResolver,用于处理表单中的file,如果没有配置就会报如下错误:提示告诉开发者你没有配置文件上传解析器:

配置MultipartResolver:注意id="multipartResolver"的id值不能乱写

#{1024*1024}

4.1.4.后台处理

@Controllerpublic class UploadController {
@RequestMapping(value="/upload",method=RequestMethod.POST) public String uploadFile(MultipartFile fileUpload,String name,HttpServletRequest req) throws FileNotFoundException, IOException {
System.out.println("普通表单获取方式:" + name); //上传表单信息:注意MultipartFile对象的名称必须与上传表单项的name属性值一致 System.out.println("上传文件是否为空:" + fileUpload.isEmpty()); System.out.println("上传文件的大小(字节):" + fileUpload.getSize()); System.out.println("上传文件的类型:" + fileUpload.getContentType()); System.out.println("上传表单name属性值:" + fileUpload.getName()); System.out.println("上传文件名:" + fileUpload.getOriginalFilename()); // 获取upload真实路径:一大巨坑(uploadFile千万不要和请求upload一样的名字,否则第二次上传出现405) String realPath = req.getServletContext().getRealPath("/uploadFile"); File file = new File(realPath); if (!file.exists()) {
// 如果upload文件夹不存在,就创建 file.mkdirs(); } String prefix = UUID.randomUUID().toString().replaceAll("-", "");//使用UUID加前缀命名文件,防止名字重复被覆盖 String fileName = prefix+"_"+fileUpload.getOriginalFilename(); InputStream in= fileUpload.getInputStream();;//声明输入输出流 OutputStream out=new FileOutputStream(new File(realPath+"\\"+fileName));//指定输出流的位置; //使用IOUtils.copy实现文件复制 IOUtils.copy(in, out); System.out.println("上传成功"); in.close(); out.close(); return "redirect:/upload.jsp"; }}

4.2.文件下载

文件下载:就是将服务器(表现在浏览器中)中的资源下载(复制)到本地磁盘;

4.2.1.前台代码

  1. 前台使用超链接,超链接转到后台控制器,在控制器通过流的方式进行操作;
    在这里插入图片描述

4.2.2.后台代码

@Controllerpublic class DownloadController {
@RequestMapping("/download") public void download(String filename,HttpServletRequest req,HttpServletResponse resp) throws Exception{
//1.获取输入流 //1.1.获取文件在服务器的绝对路径 String parentPath = req.getServletContext().getRealPath("/download"); File file = new File(parentPath, filename); if(file.exists()){
FileInputStream in = new FileInputStream(file); //2.获取输出流 //2.1.设置文件下载的名字 -- 附件表示做下载或上传操作,浏览器就不会将文件的内容直接显示出来了 resp.setHeader("Content-Disposition", "attachment; filename=" + filename); //2.2.获取输出流 ServletOutputStream out = resp.getOutputStream(); //3.实现下载 IOUtils.copy(in, out); //关流,释放资源 out.close(); in.close(); } }}

4.2.3.解决中文问题

问题描述:当下载 “美女.rar”,问题就出现了?

在这里插入图片描述

解决方法:兼容IE、edge和其他浏览器

分析: 如果是IE或edge就用URLEncoder,如果是其他浏览器就要用以下方式解决:

new String(name.getBytes("UTF-8"),"ISO-8859-1")user–agent:这个请求头是指用户代理的意思,告诉服务器使什么浏览器;@Controllerpublic class DownloadController {
@RequestMapping("/download") public void download(String filename,HttpServletRequest req,HttpServletResponse resp) throws Exception{
//1.获取输入流 //1.1.获取文件在服务器的绝对路径 String parentPath = req.getServletContext().getRealPath("/download"); File file = new File(parentPath, filename); if(file.exists()){
FileInputStream in = new FileInputStream(file); //2.获取输出流 //2.1.中文文件名称处理(ie和edge都是微软的浏览器 -- 处理方式一样)//区分浏览器,User-Agent中有浏览器的信息,trident是ie引擎名称,具体://mozilla/5.0 (windows nt 6.2; win64; x64; trident/7.0; rv:11.0) like gecko【eclipse自带ie浏览器】//Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) //Chrome/64.0.3282.140 Safari/537.36 Edge/18.17763【电脑安装的edge浏览器】//mozilla/5.0 (windows nt 10.0; win64; x64; rv:68.0) gecko/20100101 firefox/68.0【火狐】//mozilla/5.0 (windows nt 10.0; win64; x64) applewebkit/537.36 (khtml, like gecko) chrome/73.0.3683.86 safari/537.36【谷歌】 //ie浏览器 if(req.getHeader("User-Agent").toUpperCase().indexOf("TRIDENT")!=-1){
filename = URLEncoder.encode(filename, "utf-8"); //电脑自带edge【edʒ】浏览器 }else if(req.getHeader("User-Agent").toUpperCase().indexOf("EDGE")!=-1){
filename = URLEncoder.encode(filename, "utf-8"); }else{
//其他浏览器 filename = new String(filename.getBytes("UTF-8"),"ISO-8859-1");//转码的方式 }; //2.2.设置文件下载的名字 -- 附件表示做下载或上传操作,浏览器就不会将文件的内容直接显示出来了 resp.setHeader("Content-Disposition", "attachment; filename=" + filename); //2.3.获取输出流 ServletOutputStream out = resp.getOutputStream(); //3.实现下载 IOUtils.copy(in, out); //关流,释放资源 out.close(); in.close(); } }}

页面:

美女.jpg

注:Microsoft Edge和IE的最大区别就是Edge 是windows 10 之后有微软推出的浏览器,而在windows 10 之前微软系统自家浏览器都是IE;

5.SpringMVC拦截器

5.1.创建拦截器

public class MyInterceptor implements HandlerInterceptor {
//preHandle()方法在业务处理器处理请求之前被调用 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("进入拦截器了...."); //这里可以判断用户是否登录 //没有登录可以使用 request/response跳转回登录页面 //注:如果不继续执行返回false,否则返回true return false; } // postHandle()方法在业务处理器处理请求之后被调用 @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
} // afterCompletion()方法在DispatcherServlet完全处理完请求后被调用 @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}}

5.2.配置拦截器

6.SpringMVC执行流程

6.1.流程图

在这里插入图片描述

6.2.流程描述

注:控制器即处理器(Handler)

  1. 用户向服务器发送请求,请求会统一交给SpringMVC前端控制DispatcherServlet处理;
  2. DispatcherServlet通过请求HandlerMapping(处理器映射管理对象)找到该请求对应的Handler对象(包括控制器以及Handler对象对应的拦截器) 和HandlerExecutionChain对象(包含:控制器+2个拦截器);
  3. DispatcherServlet请求HandlerAdapter,选择一个合适的HandlerAdapter去处理Handler。(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(…)方法);
  4. 提取request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
      HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
      数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
      数据格式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
      数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
  5. Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;
  6. 根据返回的ModelAndView,选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet;
  7. ViewResolver 结合Model和View,来渲染视图(Model+View合成)
  8. 将渲染结果返回给客户端;

6.3.SpringMVC工作流程描述(简易版本:面试)

  1. 客户端将请求统一提交到DispatcherServlet;
  2. DispatcherServlet会将请求交给HandlerMapping进行请求映射,匹配该请求的Handler;
  3. DispatcherServlet再请求HandlerAdapter调用相应的Handler处理请求,并向前端控制器返回一个ModelAndView对象;
  4. DispatcherServlet将ModelAndView对象交给ViewResoler视图解析器处理,返回指定的视图View;
  5. DispatcherServlet 对 View 进行渲染(即将模型数据填充至视图中);
  6. DispatcherServlet 将页面响应给用户;

7.课程总结

7.1.重点

  1. SpringMvc返回Json数据;
  2. SprignMvc文件上传;
  3. SpringMvc执行流程;

7.2.难点

  1. SprignMvc文件上传;
  2. SpringMvc执行流程;

7.3.如何掌握

  1. 课上认真听课;
  2. 完成课后练习;
  3. 抓住课程重点;

7.4.排错技巧

  1. 通过异常和错误找出问题,分析问题,解决问题;
  2. 还原代码;
  3. 代码最小化;
  4. 断点;

8.常见问题

  1. 状态异常:如果出现406状态异常,jackson的jar文件没有导入
  2. HTTP Status 500 - Request processing failed; nested exception is java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured?
    分析:缺少配置

9.课后练习

  1. 课堂代码1-2遍;

10.面试题

  1. SpringMVC执行流程?

11.扩展知识或课外阅读推荐(可选)

11.1.扩展知识

拦截器(interceptor)与过滤器(filter)的区别?

  1. 拦截器与过滤器有很多相似之处,都可以拦截请求,也可以放行;
  2. 拦截器是SpringMVC中的组件,需要在Spring的配置文件中配置。而过滤器是JavaEE中的组件,在web.xml中配置。Filter的执行顺序在Interceptor之前;
  3. 拦截器(Interceptor)是基于Java的反射机制,而过滤器(Filter)是基于函数回调。从灵活性上说拦截器功能更强大些,Filter能做的事情,都能做,而且可以在请求前,请求后执行,比较灵活。Filter主要是针对URL地址做一个编码的事情、过滤掉没用的参数、安全校验(比较泛的,比如登录不登录之类),太细的话,还是建议用interceptor;
    在这里插入图片描述

11.2.课外阅读

转载地址:http://srcmf.baihongyu.com/

你可能感兴趣的文章