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 getAll() {
Collection emps = employeeDao.getAll();
;return emps;
}
}
只是写一个测试json
然后再springmvc.xml中开启注解驱动
然后需要印如jackson的三个jar包,jackson是阿里巴巴产品,能够自动将java对象转为json对象
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">
SpringMVC04
index.jsp
CharacterEncodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
CharacterEncodingFilter
/*
springDispatcherServlet
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:springMVC.xml
1
springDispatcherServlet
/
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 的执行顺序大致为:
请求到达 DispatcherServlet
DispatcherServlet 发送至 Interceptor ,执行 preHandle
请求达到 Controller
请求结束后,postHandle 执行
首先我们看下拦截器的如何被调用的。
Web请求被DispatcherServlet截获后,会调用DispatcherServlet的doDispatcher方法。
很明显地看到,在HandlerAdapter处理之后,以及处理完成之后会调用HandlerExecutionChain的方法。
HandlerExecutionChain的applyPreHandle、applyPostHandle、triggerAfterCompletion方法如下:
很明显,就是调用内部实现HandlerInterceptor该接口集合的各个对应方法。
下面我们看下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 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 entity = new ResponseEntity(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";
}
}
这个和操作系统有关系,最好加一个/, 血泪史啊