springmvc java对象转json,上传下载,拦截器Interceptor以及源码解析

 

package com.atguigu.my.controller;

import java.util.Collection;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.atguigu.my.bean.Employee;
import com.atguigu.my.dao.EmployeeDao;

@Controller
public class JsonController {
	@Autowired
	private EmployeeDao employeeDao;
	@RequestMapping(value = "/testJson")
	@ResponseBody
	public Collection<Employee> getAll() {
		Collection<Employee> emps = employeeDao.getAll();
;		return emps;
	}
}

只是写一个<a href = "testJson">测试json</a>java

而后再springmvc.xml中开启注解驱动<mvc:annotation-driven/>web

而后须要印如jackson的三个jar包,jackson是阿里巴巴产品,可以自动将java对象转为json对象spring

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

	<context:component-scan base-package="com.atguigu"></context:component-scan>
	
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/view/"></property>
		<property name="suffix" value=".jsp"></property>
	</bean>
	
	<mvc:default-servlet-handler/>
	
	<mvc:annotation-driven />
	
	<!-- 
		处理文件,将客户端上传的File文件,处理为MultipartFile
		注意:文件解析器的bean中id必须设置为multipartResolver
	 -->
	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<!-- 设置文件解析的编码,注意:必定要和页面的pageEncoding保持一致 -->
		<property name="defaultEncoding" value="UTF-8"></property>
		<!-- 设置最大上传文件大小 -->
		<property name="maxUploadSize" value="88888888"></property>
	</bean>

	<mvc:interceptors>
		<!-- 默认拦截全部请求 -->
		<bean class="com.atguigu.interceptor.FirstInterceptor"></bean>
		<bean class="com.atguigu.interceptor.SecondInterceptor"></bean>
		<!-- 此方式要求拦截器类上必须加注解@Component -->
		<!-- <ref bean="firstInterceptor"/> -->
		
		<!-- 设置自定义拦截方式 -->
		<!-- <mvc:interceptor>
			<bean></bean>
			<mvc:mapping path=""/>
			<mvc:exclude-mapping path=""/>
		</mvc:interceptor> -->
	</mvc:interceptors>

</beans>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>SpringMVC04</display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
  <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>
  
  <!-- The front controller of this Spring Web application, responsible for handling all application requests -->
	<servlet>
		<servlet-name>springDispatcherServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:springMVC.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<!-- Map all requests to the DispatcherServlet for handling -->
	<servlet-mapping>
		<servlet-name>springDispatcherServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
</web-app>
package com.atguigu.interceptor;

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

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

@Component
public class FirstInterceptor implements HandlerInterceptor {

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("First:preHandle");
		return true;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("First:postHandle");
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("First:afterCompletion");
	}

}
package com.atguigu.interceptor;

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

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

@Component
public class SecondInterceptor implements HandlerInterceptor {

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("Second:preHandle");
       //统计请求耗时
        long startTime = System.currentTimeMillis();
        request.setAttribute("startTime", startTime);
		return true;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		 System.out.println("Second:postHandle");
         long startTime = (Long)request.getAttribute("startTime");
        long endTime = System.currentTimeMillis();
        long executeTime = endTime - startTime;
        //modified the exisitng modelAndView
        modelAndView.addObject("executeTime",executeTime);
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("Second:afterCompletion");
	}

}
package com.atguigu.test;

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

@Controller
public class TestInterceptorController {

	
	/**
	 * 当有多个拦截器时,
	 * preHandle:按照拦截器数组的正向顺序执行
	 * postHandle:按照拦截器数组的反向顺序执行
	 * afterCompletion:按照拦截器数组的反向顺序执行
	 * 
	 * 当多个拦截器的preHandle有不一样的值时
	 * 第一个返回false,第二个返回false:只有第一个preHandle会执行
	 * 第一个返回true,第二个返回false:两个(所有)拦截器的preHandle都会执行
	 * 可是(所有)postHandle都不会执行,而afterCompletion只有第一个(返回false的拦截器以前的全部afterCompletion)会执行
	 * 第一个返回false,第二个返回true:只有第一个的preHandle会执行
	 */
	@RequestMapping("/testInterceptor")
	public String testInterceptor() {
		return "success";
	}
	
}

拦截器(Interceptor)和过滤器(Filter)的区别

Spring的Interceptor(拦截器)与Servlet的Filter有类似之处,好比两者都是AOP编程思想的体现,都能实现权限检查、日志记录等。不一样的是:编程

Filter Interceptor Summary
Filter 接口定义在 javax.servlet 包中 接口 HandlerInterceptor 定义在org.springframework.web.servlet 包中  
Filter 定义在 web.xml 中    
Filter在只在 Servlet 先后起做用。Filters 一般将 请求和响应(request/response) 当作黑盒子,Filter 一般不考虑servlet 的实现。 拦截器可以深刻到方法先后、异常抛出先后等,所以拦截器的使用具备更大的弹性。容许用户介入(hook into)请求的生命周期,在请求过程当中获取信息,Interceptor 一般和请求更加耦合。 在Spring构架的程序中,要优先使用拦截器。几乎全部 Filter 可以作的事情, interceptor 都可以轻松的实现
Filter 是 Servlet 规范规定的。 而拦截器既能够用于Web程序,也能够用于Application、Swing程序中。 使用范围不一样
Filter 是在 Servlet 规范中定义的,是 Servlet 容器支持的。 而拦截器是在 Spring容器内的,是Spring框架支持的。 规范不一样
Filter 不可以使用 Spring 容器资源 拦截器是一个Spring的组件,归Spring管理,配置在Spring文件中,所以能使用Spring里的任何资源、对象,例如 Service对象、数据源、事务管理等,经过IoC注入到拦截器便可 Spring 中使用 interceptor 更容易
Filter 是被 Server(like Tomcat) 调用 Interceptor 是被 Spring 调用 所以 Filter 老是优先于 Interceptor 执行

 

interceptor 的执行顺序大体为:json

  1. 请求到达 DispatcherServlet
  2. DispatcherServlet 发送至 Interceptor ,执行 preHandle
  3. 请求达到 Controller
  4. 请求结束后,postHandle 执行

首先咱们看下拦截器的如何被调用的。数组

Web请求被DispatcherServlet截获后,会调用DispatcherServlet的doDispatcher方法。spring-mvc

很明显地看到,在HandlerAdapter处理以后,以及处理完成以后会调用HandlerExecutionChain的方法。session

HandlerExecutionChain的applyPreHandle、applyPostHandle、triggerAfterCompletion方法以下:mvc

很明显,就是调用内部实现HandlerInterceptor该接口集合的各个对应方法。app

 

下面咱们看下HandlerExecutionChain的构造过程。

 HandlerExecutionChain是从HandlerMapping接口的getHandler方法获取的。

 HandlerMapping的基础抽象类AbstractHandlerMapping中:

咱们看到,HandlerExecutionChain的拦截器是从AbstractHandlerMapping中的adaptedInterceptors和mappedInterceptors属性中获取的。

package com.atguigu.test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;

import javax.servlet.http.HttpSession;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;

@Controller
public class TestUploadAndDownController {

	@RequestMapping("/down")
	public ResponseEntity<byte[]> down(HttpSession session) throws IOException{
		
		//获取下载文件的路径
		String realPath = session.getServletContext().getRealPath("img");
		String finalPath = realPath + File.separator + "2.jpg";
		InputStream is = new FileInputStream(finalPath);
		//available():获取输入流所读取的文件的最大字节数
		byte[] b = new byte[is.available()];
		is.read(b);
		//设置请求头
		HttpHeaders headers = new  HttpHeaders();
		headers.add("Content-Disposition", "attachment;filename=zzz.jpg");
		//设置响应状态
		HttpStatus statusCode = HttpStatus.OK;
		ResponseEntity<byte[]> entity = new ResponseEntity<byte[]>(b, headers, statusCode);
		return entity;
	}
	
	@RequestMapping(value="/up", method=RequestMethod.POST)
	public String up(String desc, MultipartFile uploadFile, HttpSession session) throws IOException {
		//获取上传文件的名称
		String fileName = uploadFile.getOriginalFilename();
		String finalFileName = UUID.randomUUID() + fileName.substring(fileName.lastIndexOf("."));
		String path = session.getServletContext().getRealPath("photo") + File.separator + finalFileName;
		File file = new File(path);
		uploadFile.transferTo(file);
		return "success";
	}
	
	@RequestMapping(value="/up_old", method=RequestMethod.POST)
	public String up_old(String desc, MultipartFile uploadFile, HttpSession session) throws IOException {
		//获取上传文件的名称
		String fileName = uploadFile.getOriginalFilename();
		String path = session.getServletContext().getRealPath("photo") + File.separator + fileName;
		//获取输入流
		InputStream is = uploadFile.getInputStream();
		//获取输出流
		File file = new File(path);
		OutputStream os = new FileOutputStream(file);
		/*int i = 0;
		while((i = is.read()) != -1) {
			os.write(i);
		}*/
		
		/*int i = 0;
		byte[] b = new byte[1024];
		while((i = is.read(b)) != -1) {
			os.write(b, 0, i);
		}*/
		
		os.close();
		is.close();
		return "success";
	}
	
}

这个和操做系统有关系,最好加一个/, 血泪史啊

相关文章
相关标签/搜索