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";
	}
	
}

這個和操做系統有關係,最好加一個/, 血淚史啊

相關文章
相關標籤/搜索