需要在 webapp/static/img 下 放一张叫 1.png的图片
@RequestMapping("/testDown")
public ResponseEntity test(HttpSession session) throws Exception {
//获取ServletContext对象
ServletContext servletContext = session.getServletContext();
//获取服务器中的文件的真实路径
String realPath = servletContext.getRealPath("/static/img/1.png");
//创建输入流
InputStream is = new FileInputStream(realPath);
//创建字节数组
byte[] bytes = new byte[is.available()];
//将流读取到字节数组中
is.read(bytes);
//创建HttpHeaders对象 设置响应头信息
MultiValueMap headers = new HttpHeaders();
//设置要下载方式及下载文件的名字
headers.add("content-Disposition","attachment;filename=1.png");
//设置响应状态码
HttpStatus code = HttpStatus.OK;
//创建ResponseEntity对象
ResponseEntity entity = new ResponseEntity<>(bytes,headers,code);
//关闭输入流
is.close();
return entity;
}
文件上传要求form的请求方式必须为 post,并且添加属性enctype="multipart/form-data"
springmvc中将上传的文件封装到MultipartFile对象中,通过此对象可以获取文件相关信息
上传步骤:
添加依赖
commons-fileupload commons-fileupload 1.3.3 在springmvc配置文件中 添加配置
编写html
编写controller
@RequestMapping("/testUp") public String testUp(MultipartFile photo,HttpSession session) throws IOException { String fileName = photo.getOriginalFilename();//上传文件名 //获取ServletContext对象 ServletContext servletContext = session.getServletContext(); //获取服务器中的文件的真实路径 String realPath = servletContext.getRealPath("photo"); System.out.println(realPath); File file = new File(realPath); //判断路径是否存在 if(!file.exists()){ file.mkdir(); } String finalPath = realPath+File.separator+fileName; photo.transferTo(new File(finalPath)); return "success"; }
上面的代码可以实现上传,但是 会存在一个问题, 当文件名重复时 就会出现覆盖问题, 如何解决????
一般就是换个名字,
@RequestMapping("/testUp") public String testUp(MultipartFile photo,HttpSession session) throws IOException { //获取上传文件名 String fileName = photo.getOriginalFilename(); //获取上传文件的后缀名 String suffix = fileName.substring(fileName.lastIndexOf(".")); //将UUID作为文件名 String uuid = UUID.randomUUID().toString().replaceAll("-","");//可以替换也可以不替换,不替换就有- //将uuid与后缀拼接后 作为 文件名 fileName = uuid+suffix; //获取ServletContext对象 ServletContext servletContext = session.getServletContext(); //获取服务器中photo的真实路径 String realPath = servletContext.getRealPath("photo"); System.out.println(realPath); File file = new File(realPath); //判断路径是否存在 if(!file.exists()){ file.mkdir(); } String finalPath = realPath+File.separator+fileName; photo.transferTo(new File(finalPath)); return "success"; }
1、过滤器是基于函数回调,拦截器是基于java的反射机制的。
2、过滤器是servlet规范规定的,只能用于web程序中,而拦截器是在spring容器中,它不依赖servlet容器。
3、过滤器可以拦截几乎所有的请求(包含对静态资源的请求),而拦截器只拦截action请求(不拦截静态资源请求)。
4、滤器不能访问action上下文、值栈里的对象,拦截器可以访问action上下文、值栈里的对象。
5、在action的生命周期中,过滤器只能在容器初始化时被调用一次,拦截器可以多次被调用,而。
6、拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。
7、拦截器是被包裹在过滤器之中。
过滤器、拦截器、aop 顺序
拦截顺序:filter—>Interceptor—->@Aspect -->Interceptor)
过滤器: 依赖于servlet容器。在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数据,比如:在过滤器中修改字符编码;在过滤器中修改HttpServletRequest的一些参数,包括:过滤低俗文字、危险字符等。
拦截器: 依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用。由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理。
执行顺序 :
SpringMVC的机制是由同一个Servlet来分发请求给不同的Controller,其实这一步是在Servlet的service()方法中执行的。所以过滤器、拦截器、service()方法,dispatc()方法的执行顺序应该是这样的
springmvc中的拦截器用于拦截 控制器方法的执行
springmvc中的拦截器需要实现HandlerInterceptor
springmvc的拦截器必须在springmvc的配置文件中进行配置:
//自定义拦截器
public class FirstInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("FirstInterceptor preHandle ");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("FirstInterceptor postHandle ");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("FirstInterceptor afterCompletion ");
}
}
或者
@Component
public class FirstInterceptor implements HandlerInterceptor {}
注意要添加 包的扫描到 拦截器所在的包
或者
springmvc中的拦截器有三个抽象方法:
preHandle( ):该方法在控制器的处理请求方法前执行,其返回值表示是否中断后续操作,返回 true 表示继续向下执行 即调用控制器方法,返回 false 表示中断后续操作 即不调用控制器方法。
postHandle( ):该方法在控制器的处理请求方法调用之后、解析视图之前执行postHandle,可以通过此方法对请求域中的模型和视图做进一步的修改。
afterCompletion( ):该方法在控制器的处理请求方法执行完成后执行,即视图渲染结束后执行afterCompletion,可以通过此方法实现一些资源清理、记录日志信息等工作。
1.若每个拦截器的preHandle()都返回true
此时多个拦截器的执行顺序和拦截器在springmvc的配置文件的配置顺序有关:
preHandle()会按照配置的顺序执行,而postHandle() 和 afterComplation()会按照配置的反序执行
@Component
public class SecondInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("SecondInterceptor preHandle ");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("SecondInterceptor postHandle ");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("SecondInterceptor afterCompletion ");
}
}
@Component
public class FirstInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("FirstInterceptor preHandle ");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("FirstInterceptor postHandle ");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("FirstInterceptor afterCompletion ");
}
}
打开页面: 控制台输出
FirstInterceptor preHandle --配置顺序 SecondInterceptor preHandle SecondInterceptor postHandle -反序 FirstInterceptor postHandle SecondInterceptor afterCompletion -反序 FirstInterceptor afterCompletion
2.若 某个拦截器的preHandle()返回了false
preHandle()返回false和它之前的拦截器的preHandle()都会执行,postHandle() 都不执行,返回false的拦截器之前的拦截器的 afterComplation()会执行
@Component
public class SecondInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("SecondInterceptor preHandle ");
return false; //改为 false
}
}
控制台输出
FirstInterceptor preHandle SecondInterceptor preHandle FirstInterceptor afterCompletion