springMVC学习笔记——加载静态资源、Json、文件上传与下载、拦截器

加载静态资源

  • 配置Tomcat的默认servlet,即DefaultServlet(注意:该注解要配合开启MVC驱动注解使用才有效)。

  • DefaultServlet的请求路径与DispatcherServlet的请求路径相同,都为 /,

  • 处理请求时,开发人员编写的Servlet优先级高于DefaultServlet,因此,当收到客户端传来的请求时,DispatcherServlet先去搜索项目中有无能够处理该请求的方法,若有,则处理请求,若没有,则该请求交给DefaultServlet处理。

  • 对于静态资源而言,DispatcherServlet不能处理,需要使用DefaultServlet处理,所以要配置Tomcat的DefaultServlet。

<!-- 配置Tomcat默认Servlet -->
<mvc:default-servlet-handler/>
	
<!-- 开启MVC驱动 -->
<mvc:annotation-driven/>

Json

小知识

json 有两种格式:
(1)json 对象:{key:value, key:value, ...}
(2)json 数组:[value1, value2, ...]

json 对象的解析方式:对象.key
json 数组的解析方式:for 循环遍历

java 对象转换为 json:
(1)Bean、Map => json 对象
(2)List => json 数组

jackson

当服务器需要向客户端返回 json 格式的数据时,springMVC 默认使用 jackson 将数据转换为 json 格式,再发送给客户端。

springMVC 处理 json 数据的步骤:

  1. 导入 jackson 的相关 jar 包。
    在这里插入图片描述
  2. 在 springMVC 配置文件中开启 MVC 注解驱动。<mvc:annotation-driven/>
  3. 在处理 json 数据的方法上(常为处理 ajax 请求)使用@ResponseBody注解。
  4. 在方法内,将要以 json 格式发送到客户端的数据以返回值的形式返回。

@ResponseBody:当方法上添加该注解之后,方法的返回值不再表示视图名称,而是表示要发送给客户端的数据。

代码

在这里插入图片描述
在这里插入图片描述
springMVC配置文件

<mvc:default-servlet-handler/>
	
<!-- 开启MVC驱动 -->
<mvc:annotation-driven/>

Student.java

private String stuName;
private Integer gender;
private Integer age;
private School school;

School.java

private String grade;
private String stuClass;

TestJson.java

@Controller
public class TestJson {

	@RequestMapping(value="/stuInfo",method=RequestMethod.GET)	
	@ResponseBody
	public List<Student> getStuInfo() {
		Student stu1 = new Student("MCC1", 1, 20, new School("p1", "jlu1"));
		Student stu2 = new Student("MCC2", 0, 21, new School("p2", "jlu2"));
		Student stu3 = new Student("MCC3", 1, 22, new School("p3", "jlu3"));
		ArrayList<Student> stuList = new ArrayList<Student>();
		stuList.add(stu1);
		stuList.add(stu2);
		stuList.add(stu3);
		return stuList;
	}
}

json.jsp

  • 实现1:遍历输出返回的 json 数组(因为服务器返回的是 List 集合,因此被转换为 json 数组)。
  • 实现2:不刷新页面,将数据以列表形式显示。
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>json</title>
	<script type="text/javascript" src="${ pageContext.request.contextPath }/static/jquery-1.7.2.js"></script>
	<script type="text/javascript">
		$(function(){
			$("#ajax1").click(function(){
				$.ajax({
					url:"http://localhost:8080/RESTful_CRUD/stuInfo",
					type:"Get",
					success:function(msg){
						//实现1:遍历输出返回的json数组(因为服务器返回的是List集合,因此被转换为json数组)
						/*
						for(var i=0;i<msg.length;i++){
							alert("stuName:"+msg[i].stuName+", school:"+msg[i].school.grade);
						}
						*/
						//实现2:不刷新页面,将数据以列表形式显示
						var stuTable = 
							"<table>"+
								"<tr>"+
									"<th>姓名</th>"+
									"<th>性别</th>"+
									"<th>年龄</th>"+
									"<th>年级</th>"+
									"<th>班级</th>"+
								"</tr>";
						for(var i=0; i<msg.length; i++){
							stuTable += 
								"<tr>"+
									"<td>"+msg[i].stuName+"</td>"+
									"<td>"+msg[i].gender+"</td>"+
									"<td>"+msg[i].age+"</td>"+
									"<td>"+msg[i].school.grade+"</td>"+
									"<td>"+msg[i].school.stuClass+"</td>"+
								"</tr>";
						}
						stuTable += "</table>";
						$("body").append(stuTable);
					},
					dataType:"json"
				});	
			});
			//测试使用$.getJSON()
			$("#ajax2").click(function(){
				$.getJSON("http://localhost:8080/RESTful_CRUD/stuInfo",function(msg){
					for(var i=0;i<msg.length;i++){
						alert("stuName:"+msg[i].stuName+", school:"+msg[i].school.grade);
					}
				});
			});
		});
	</script>
</head>
<body>
	<button id="ajax1">ajax1</button>
	<button id="ajax2">ajax2</button>
</body>
</html>

文件上传与下载

文件上传

springMVC 将上传的文件转换为 MultipartFile 类型,该类型需要在 springMVC 配置文件中进行配置才能使用。
注意:
(1)bean 标签的 id 值为固定值id="multipartResolver",不能修改。
(2)可以通过 property 标签设置上传对象的属性,如默认编码格式defaultEncoding、最大上传文件大小maxUploadSize等。

<!-- 处理文件,将上传的File文件转换为MultipartFile -->
<!-- 注意:id为固定名称,不能修改 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
	<!-- 设置上传文件的编码格式,一定要和jsp页面的pageEncoding值保持一致 -->
	<property name="defaultEncoding" value="UTF-8"></property>
	<!-- 设置最大上传文件大小,大小要写具体的数字,不能写表达式 -->
	<property name="maxUploadSize" value="10240000"></property>
</bean>
方法作用
getName()获取表单 type=“file” 输入框的 name 属性值
getOriginalFilename()获取上传文件的文件名
getInputStream()获取上传文件的输入流
transferTo()读取文件输入流,写入到磁盘输出流
  1. 上传单个文件

    实现方式:在方法的参数位置传入 MultipartFile 对象。
    注意:对象名要与表单的 name 属性值相同。

    <form action="http://localhost:8080/RESTful_CRUD/upload" method="post" enctype="multipart/form-data">
    	文件:<input type="file" name="file"/><br/>
    	描述:<input type="text" name="description"/><br/>
    	<input type="submit" value="上传"/>
    </form>
    

    方法1:使用 getInputStream()(麻烦)

    /**
    * 单文件上传
     * @param file
     * @param decription
     * @return
     * @throws IOException 
     */
    @RequestMapping(value="/upload",method=RequestMethod.POST)
    public String fileUpload_old(MultipartFile file, String decription, HttpSession session) throws IOException {
    	//获取type="file"输入框的name属性值
    	//String name = file.getName();
    	//System.out.println(name);//file
    	//获取上传文件的文件名
    	String filename = file.getOriginalFilename();
    	//System.out.println(filename);//1577368025905.jpg
    	//获取上传文件的输入流
    	InputStream inputStream = file.getInputStream();
    	//将上传的文件保存到upload文件夹下
    	//获取upload文件夹的磁盘路径
    	String path = session.getServletContext().getRealPath("upload");
    	String finalPath = path + File.separator + filename;
    	OutputStream outputStream = new FileOutputStream(new File(finalPath));
    	//读取文件,并写入到输出流
    	byte[] b = new byte[1024];
    	int i = 0;
    	while((i=inputStream.read(b))!=-1) {
    		outputStream.write(b, 0, i);
    	}
    	inputStream.close();
    	outputStream.close();
    	return "success";
    }
    

    方法2:使用 transferTo()(常用)

    /**
    * 单文件上传
     * @param file
     * @param decription
     * @return
     * @throws IOException 
     */
    @RequestMapping(value="/upload",method=RequestMethod.POST)
    public String fileUpload(MultipartFile file, String decription, HttpSession session) throws IOException {
    	//获取文件名
    	String filename = file.getOriginalFilename();
    	//将文件保存到upload文件夹下,获取文件夹路径
    	String path = session.getServletContext().getRealPath("upload");
    	//通过UUID设置文件名,避免文件重名
    	//格式为:upload/filenameUUID.xxx`在这里插入代码片`
    	//以filename的最后一个.为分隔符,将文件名分割,再与UUID拼接
    	String prefix = filename.substring(0, filename.lastIndexOf("."));
    	String suffix = filename.substring(filename.lastIndexOf("."));
    	//与UUID拼接
    	String finalPath = path + File.separator + prefix + UUID.randomUUID() + suffix;
    	//读取文件输入流,写入到磁盘输出流
    	file.transferTo(new File(finalPath));
    	return "success";
    }
    
  2. 上传多个文件

    实现方式:在方法的参数位置传入 MultipartFile[ ] 对象
    注意:对象名要与表单的 name 属性值相同。

    <!-- 上传多个文件 -->
    <form action="http://localhost:8080/RESTful_CRUD/uploadMore" method="post" enctype="multipart/form-data">
    	文件:<input type="file" name="files"/><br/>
    	文件:<input type="file" name="files"/><br/>
    	描述:<input type="text" name="description"/><br/>
    	<input type="submit" value="上传"/>
    </form>
    
    /**
    * 多文件上传
     * @param file
     * @param decription
     * @return
     * @throws IOException 
     */
    @RequestMapping(value="/uploadMore",method=RequestMethod.POST)
    public String fileUploadMore(MultipartFile[] files, String decription, HttpSession session) throws IOException {
    	for(int i=0; i<files.length; i++) {
    		MultipartFile file = files[i];
    		//获取文件名
    		String filename = file.getOriginalFilename();
    		//将文件保存到upload文件夹下,获取文件夹路径
    		String path = session.getServletContext().getRealPath("upload");
    		//通过UUID设置文件名,避免文件重名
    		//格式为:upload/filenameUUID.xxx
    		//以filename的最后一个.为分隔符,将文件名分割,再与UUID拼接
    		String prefix = filename.substring(0, filename.lastIndexOf("."));
    		String suffix = filename.substring(filename.lastIndexOf("."));
    		//与UUID拼接
    		String finalPath = path + File.separator + prefix + UUID.randomUUID() + suffix;
    		//读取文件输入流,写入到磁盘输出流
    		file.transferTo(new File(finalPath));
    	}
    	return "success";
    }
    

文件下载

  • ResponseEntity<T>:响应实体类,springMVC 通过返回该类对象,实现下载功能。
  • new ResponseEntity<T>(byte[] body,MultiValueMap<String, String> headers,HttpStatus status):构造方法内需要传入三个参数。
  • getRealPath():参数为空字符串时,返回项目在磁盘上的绝对路径;参数为文件名时,返回文件在磁盘上的绝对路径。
<a href="http://localhost:8080/RESTful_CRUD/download/1577368025905.jpg">下载1577368025905.jpg</a>
/**
 * 文件下载
 * @param fileName
 * @param session
 * @return 下载实体 ResponseEntity<byte[]>
 * @throws IOException
 */
@RequestMapping("/download/{fileName}")
public ResponseEntity<byte[]> fileDownload(@PathVariable("fileName")String fileName, HttpSession session) throws IOException{
	//获取文件路径
	//getRealPath():参数为空字符串时,返回项目在磁盘上的绝对路径;参数为文件名时,返回文件在磁盘上的绝对路径
	String path = session.getServletContext().getRealPath("imgs");
	String realPath = path + File.separator + fileName + ".jpg";
	//读取文件
	FileInputStream inputStream = new FileInputStream(new File(realPath));
	BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
	byte[] b = new byte[bufferedInputStream.available()];
	//设置响应头
	HttpHeaders headers = new HttpHeaders();
	headers.add("Content-Disposition", "attachment;filename="+fileName);
	//设置响应状态码
	HttpStatus httpStatus = HttpStatus.OK;
	ResponseEntity<byte[]> entity = new ResponseEntity<byte[]>(b, headers, httpStatus);
	return entity;
}

拦截器

概念

在这里插入图片描述

拦截器的作用位置:拦截器作用在 springMVC 核心控制器将请求分发到对应的 Servlet 程序之间的位置。

自定义拦截器

  1. springMVC 提供了一个默认拦截器,程序员可以通过如下两种方式实现自定义拦截器:
    (1)实现HandlerInterceptor接口
    (2)继承HandlerInterceptorAdapter适配器类
  2. HandlerInterceptor 接口内有三个方法:
    (1)preHandle():在 Servlet 程序执行之前执行。若返回 true,则继续执行 Servlet 程序,若返回 false,则结束 Servlet 程序。
    (2)postHandle:在 Servlet 程序处理完请求之后,但 DispatcherServlet 向客户端返回响应数据之前执行。
    (3)afterCompletion():在 Servlet 程序执行完毕后执行。若 preHandle() 返回 true,且该拦截器前没有返回 false 的拦截器,则该方法一定会执行,若 preHandle 返回 false,则该方法一定不会执行。即:返回 false 的拦截器之前的所有返回 true 的拦截器的 afterCompletion() 方法都会执行。
  3. 在springMVC 的配置文件中,使用标签<mvc:interceptors></mvc:interceptors>配置拦截器类。配置方法:
    (1)通过 bean 标签的 class 属性,设置某个类为拦截器类。
    (2)在拦截器类上使用注解 @Component 创建对象,在 ref 标签内通过 bean 属性指定该类为拦截器类。
<mvc:interceptors>
	<!-- 将MyInterceptor类设置为拦截器类 -->
	<bean class="com.mcc.springMVC.interceptor.MyInterceptor"></bean>
	<!-- <ref bean="myInterceptor"/> -->
</mvc:interceptors>
package com.mcc.springMVC.interceptor;

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

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

@Component
public class MyInterceptor extends HandlerInterceptorAdapter{

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		// TODO Auto-generated method stub
		return super.preHandle(request, response, handler);
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		// TODO Auto-generated method stub
		super.postHandle(request, response, handler, modelAndView);
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		// TODO Auto-generated method stub
		super.afterCompletion(request, response, handler, ex);
	}
}

设置拦截路径

不设置拦截路径时,拦截器默认拦截全部请求,拦截路径以/开始。

方法:使用<mvc:interceptor></mvc:interceptor>标签实现。
在该标签内,有属性:
(1)<mvc:mapping path=""/>:拦截路径,如:拦截所有请求路径为 .html 的请求<mvc:mapping path="/*.html"/>
(2)<bean></bean>:为哪个拦截器设置拦截路径
(3)<mvc:exclude-mapping path=""/>:不需要拦截的路径

多个拦截器的执行顺序

当有多个拦截器时,有以下几种情况:(以下假设除 springMVC 默认拦截器外,还有两个自定义拦截器)

拦截器preHandle() 的返回值执行顺序
1,21:true,2:true1:preHandle() => 2:preHandle() => 2:postHandle() => 1:postHandle() => 2:afterCompletion() => 1:afterCompletion()
1,21:true,2:false1:preHandle() => 2:preHandle() => 1:afterCompletion(),返回 false 的拦截器之前的所有返回 true 的拦截器的 afterCompletion() 方法都会执行。
1,21:false,2:true1:preHandle()
1,21:false,2:false1:preHandle()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值