1.课程介绍
- JSON; (了解)
- SpringMVC返回JSON; (掌握)
- SpringMVC文件上传、下载; (掌握)
- SpringMVC拦截器; (掌握)
- SpringMVC执行流程; (掌握)
2.JSON
2.1.JSON概述
在实际开发中,通常需要和别的系统交换数据,数据交换的格式通常有XML和JSON等;
JSON(JavaScript Object Notation:JavaScript对象表示法)是一种基于JavaScript 语法开放的轻量级数据交换格式,使用js语法来描述数据对象;
JSON作为一个轻量级的数据格式,相对于XML,文档更小,结构清晰简洁,读写效率更高,XML需要很多的标签,在数据传输的时候无疑会消耗更多网络资源和流量:
(1)用XML表示一个对象:
<person id="1"> <name>tom</name> <age>20</age> <salary>5000.0</salary> </person>
(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); X Json对象: var obj = {“id”:1,”name”:”tom”,”salary”:5000.0}; alert(obj.id); //1 alert(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.注意事项
- 出现406状态异常:缺少jar包,加入jackson的jar包即可;
- 使用@ResponseBody注解之后,不会经过视图解析器;
- 如果在ie中测试,会弹出下载文件的窗口,可以在spring-mvc.xml的
<mvc:annotation-driven>中加入以下配置解决: <!-- 开启spring对MVC的支持 --> <mvc:annotation-driven> <!-- 避免在IE浏览器中返回JSON时出现下载文件的情况 --> <mvc:message-converters> <bean id="mappingJackson2HttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8</value> </list> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>
4.文件上传与下载
4.1.文件上传
文件上传:指的是将本地的文件复制到服务器上;
SpringMvc中的文件上传是对原生文件上传的封装,目的是,较少代码量,提高开发效率;
文件上传三要素:
(1)表单的提交的方式必须是POST请求(get请求对提交的数据)
(2)表单中必须有一个文件上传项:,文件上传项必须有name属性和值;
(3)表单的enctype属性的值必须是multipart/form-data
4.1.1.添加jar文件
由于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值不能乱写
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 设置上传文件的最大尺寸为1MB --> <property name="maxUploadSize"> <!-- spring el写法:1MB --> <value>#{1024*1024}</value> </property> <!-- 效果同上 --> <property name="maxUploadSize" value="1048576" /> </bean>
4.1.4.后台处理
@Controller public 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.前台代码
- 前台使用超链接,超链接转到后台控制器,在控制器通过流的方式进行操作;
4.2.2.后台代码
@Controller public 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:这个请求头是指用户代理的意思,告诉服务器使什么浏览器; @Controller public 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(); } } }
页面:
<a href='/download?fileName=<%=URLEncoder.encode("美女.jpg", "utf-8") %>'>美女.jpg</a>
注:Microsoft Edge和IE的最大区别就是Edge 是windows 10 之后有微软推出的浏览器,而在windows 10 之前微软系统自家浏览器都是IE;
javaweb实训第六天上午——JSON&SpringMVC进阶(2)https://developer.aliyun.com/article/1415131?spm=a2c6h.13148508.setting.32.6e1a4f0eQzpjQW