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"; } }
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
首先咱们看下拦截器的如何被调用的。数组
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"; } }
这个和操做系统有关系,最好加一个/, 血泪史啊