一、SpringMVC实现文件上传
1、原理分析
<form action="/user/fileupload1" method="post" enctype="multipart/form-data"> 选择文件:<input type="file" name="upload" /><br/> <input type="submit" value="上传" /> </form>
|
在jsp页面使用form表单进行文件的上传,使用 文件选择域< input type=”file” name=“upload”/>
2、上传的必要前提
1 form表单的enctype取值必须是:multipart/form-data (默认值是:application/x-www-form-urlencoded) enctype:是表单请求正文的类型
2 method属性取值必须是Post
3 提供一个文件选择域< input type=”file” />
3、传统的文件上传
传统方式的文件上传,指的是我们上传的文件和访问的应用存在于同一台服务器上。 并且上传完成之后,浏览器可能跳转。
(1)前端文件上传页面
<form action="/user/fileupload2" method="post" enctype="multipart/form-data"> 选择文件:<input type="file" name="upload" /><br/> <input type="submit" value="上传" /> </form>
|
(2)写后端的控制器Controller
@RequestMapping("/fileupload2") public String fileuoload2(HttpServletRequest request, MultipartFile upload) throws Exception { System.out.println("springmvc文件上传...");
String path = request.getSession().getServletContext().getRealPath("/uploads/"); File file = new File(path); if(!file.exists()){ file.mkdirs(); }
String filename = upload.getOriginalFilename(); String uuid = UUID.randomUUID().toString().replace("-", ""); filename = uuid+"_"+filename; upload.transferTo(new File(path,filename));
return "success"; }
|
(3)配置文件上传解析器
id的值multipartResolver是固定的,文件上传的解析器id是固定的,不能起别的名称,否则无法实现请求参数的绑定。 <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="10485760" /> </bean>
|
4、跨服务器方式的文件上传
在实际开发中,我们会有很多处理不同功能的服务器。
例如:
应用服务器:负责部署我们的应用
数据库服务器:运行我们的数据库
缓存和消息服务器:负责处理大并发访问的缓存和消息
文件服务器:负责存储用户上传文件的服务器。
编写前端上传的jsp页面
<h3>跨服务器文件上传</h3>
<form action="/user/fileupload3" method="post" enctype="multipart/form-data"> 选择文件:<input type="file" name="upload" /><br/> <input type="submit" value="上传" /> </form>
|
@RequestMapping("/fileupload3") public String fileuoload3(MultipartFile upload) throws Exception { System.out.println("跨服务器文件上传...");
String path = "http://localhost:9090/fileuploadserver/uploads/";
String filename = upload.getOriginalFilename(); String uuid = UUID.randomUUID().toString().replace("-", ""); filename = uuid+"_"+filename;
Client client = Client.create();
WebResource webResource = client.resource(path + filename);
webResource.put(upload.getBytes());
return "success"; }
|
二、SpringMVC中的异常处理
系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器HandlerExceptionResolver进行异常处理,如下图:
(1)先写一个异常类(对象)以及 自定义异常处理器
public class SysException extends Exception {
private String message;
@Override public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
public SysException(String message) { this.message = message; } }
|
public class SysExceptionResolver implements HandlerExceptionResolver {
@Override public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
SysException sysException = null; if(e instanceof SysException) { sysException = (SysException) e; }else { sysException = new SysException("系统正在维护..."); }
ModelAndView mv = new ModelAndView(); mv.addObject("errorMsg",sysException.getMessage()); mv.setViewName("error"); return mv; } }
|
(2)错误页面和 在springmvc的配置文件中配置异常处理器
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <html> <head> <title>Title</title> </head> <body>
<h3>执行错误</h3> ${errorMsg}
</body> </html>
|
<bean id="sysExceptionResolver" class="com.itheima.exception.SysExceptionResolver"></bean>
|
当用户访问到/testException此路径时,就会抛出异常错误对象给异常处理器,异常处理器再跳转到错误页面。
@Controller @RequestMapping("/user") public class UserController {
@RequestMapping("/testException") public String testException() throws SysException { System.out.println("方法执行");
try { int i = 10/0; } catch (Exception e) { e.printStackTrace(); throw new SysException("查询用户出现了错误..."); }
return "success"; } }
|
三、SpringMVC中的拦截器
Spring MVC 的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。
用户可以自己定义一些拦截器来实现特定的功能。拦截器链(多个拦截器)就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
过滤器与拦截器他们的区别:
(1)过滤器是servlet规范中的一部分,任何java web工程都可以使用。
拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能用。
(2)过滤器在url-pattern中配置了/之后,可以对所有要访问的资源拦截。
*拦截器它是只会拦截访问的控制器方法**,如果访问的是jsp,html,css,image或者js是不会进行拦截的。 它也是AOP思想的具体应用。
我们要想自定义拦截器, 要求必须实现:HandlerInterceptor接口。
(1)新建拦截器
public class MyInterceptor1 implements HandlerInterceptor {
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor1执行了...前111"); return true; }
@Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("MyInterceptor1执行了...后111"); }
@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("MyInterceptor1执行了...最后111"); } }
|
(2)配置拦截器
<mvc:interceptors> <mvc:interceptor>
<mvc:mapping path="/user/*"/>
<bean class="com.itheima.interceptor.MyInterceptor1"></bean> </mvc:interceptor> </mvc:interceptors>
|
1、拦截器的放行
放行的含义是指,如果有下一个拦截器就执行下一个,如果该拦截器处于拦截器链的最后一个,则执行控制器中的方法。
2、拦截器方法的说明
* default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return true; }
|
3、多个拦截器的执行顺序
多个拦截器是按照配置的顺序决定的。
流程测试:编写两个拦截器1和2
public class MyInterceptor1 implements HandlerInterceptor {
public class MyInterceptor2 implements HandlerInterceptor {
|
配置好拦截器
<mvc:interceptors> <mvc:interceptor>
<mvc:mapping path="/user/*"/>
<bean class="com.itheima.interceptor.MyInterceptor1"></bean> </mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**/"/>
<bean class="com.itheima.interceptor.MyInterceptor2"></bean> </mvc:interceptor>
</mvc:interceptors>
|