一. 拦截器实现HandlerInterceptor 接⼝
SpringMVC 中的 Interceptor 拦截器也是相当重要和相当有⽤的,它的主要作⽤是拦截⽤户的请求并进⾏相应的处理。⽐如通过它来进⾏权限验证,或者是来判断⽤户是否登陆等操作。对于 SpringMVC 拦截器的定义⽅式有两种:
实现接⼝:org.springframework.web.servlet.HandlerInterceptor
继承适配器:org.springframework.web.servlet.handler.HandlerInterceptorAdapter
1.拦截器实现HandlerInterceptor 接⼝
java
/**
1.
2. 拦截器实现 HandlerInterceptor 接⼝
*/
public class MyInterceptor01 implements HandlerInterceptor {
/**
3. 在 ⽬标Handler(⽅法)执⾏前 执⾏
4. 返回 true:执⾏handler⽅法
5. 返回 false:阻⽌⽬标handler⽅法执⾏
6. @param request
7. @param response
8. @param handler
9. @return
10. @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("⽬标Handler执⾏前执⾏MyInterceptor01 --> preHandle⽅法...");
/**
11. 返回 true:执⾏handler⽅法
12. 返回 false:阻⽌⽬标handler⽅法执⾏
*/
return true;
}
/**
13. 在 ⽬标Handler(⽅法)执⾏后,视图⽣成前 执⾏
14. @param request
15. @param response
16. @param handler
17. @param modelAndView
18. @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("⽬标Handler执⾏后,视图⽣成前执⾏MyInterceptor01 -->
postHandle⽅法...");
}
/**
19. 在 ⽬标Handler(⽅法)执⾏后,视图⽣成后 执⾏
20. @param request
21. @param response
22. @param handler
23. @param ex
24. @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse
response, Object handler, Exception ex) throws Exception {
System.out.println("⽬标Handler执⾏后,视图⽣成后执⾏MyInterceptor01 -->
afterCompletion⽅法...");
}
}
2.拦截器xml配置
xml
<mvc:interceptors>
<!-
定义在 mvc:interceptor 下⾯,可以⾃定义需要拦截的请求
如果有多个拦截器满⾜拦截处理的要求,则依据配置的先后顺序来执⾏-->
<mvc:interceptor>
<!-- 通过 mvc:mapping 配置需要拦截的资源。⽀持通配符。可配置多个。 -->
<mvc:mapping path="/**"/> <!-- "/**"表示拦截所有的请求。 -->
<!-- 通过 mvc:mapping 配置不需要被拦截的资源。⽀持通配符。可配置多个。 -->
<mvc:exclude-mapping path="/url/*"/> <!-- "/url/*"表示放⾏url路径下的请求。 -->
<bean class="com.xxxx.springmvc.interceptor.MyInterceptor01"/>
</mvc:interceptor>
</mvc:interceptors>
二.继承 HandlerInterceptorAdapter
实际上最终还是 HandlerInterceptor 接⼝实现。
- ⼦类实现类
java
/**
1. 拦截器实现
2. 继承 HandlerInterceptorAdapter 适配器
*/
public class MyInterceptor02 extends HandlerInterceptorAdapter {
/**
3. 在 ⽬标Handler(⽅法)执⾏前 执⾏
4. 返回 true:执⾏handler⽅法
5. 返回 false:阻⽌⽬标handler⽅法执⾏
6. @param request
7. @param response
8. @param handler
9. @return
10. @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("⽬标Handler执⾏前执⾏MyInterceptor02 --> preHandle⽅法...");
/**
11. 返回 true:执⾏handler⽅法
12. 返回 false:阻⽌⽬标handler⽅法执⾏
*/
return true;
}
}
- 拦截器xml配置
xml
<mvc:interceptors>
<mvc:interceptor>
<!-- 拦截的资源 -->
<mvc:mapping path="/**"/>
<!-- 放⾏的资源 -->
<mvc:exclude-mapping path="/url/test01"/>
<mvc:exclude-mapping path="/url/test02"/>
<bean class="com.xxxx.springmvc.interceptor.MyInterceptor02"/>
</mvc:interceptor>
</mvc:interceptors>
- 多个拦截器实现
xml
<mvc:interceptors>
<!-
拦截器链(多个拦截器)
如果有多个拦截器满⾜拦截处理的要求,则依据配置的先后顺序来执⾏
先配置的拦截器的 preHandle ⽅法先执⾏
先配置的拦截器的 postHandle、afterCompletion ⽅法后执⾏-->
<mvc:interceptor>
<!-- 拦截所有请求 -->
<mvc:mapping path="/**" />
<bean class="com.xxxx.springmvc.interceptor.MyInterceptor01" />
</mvc:interceptor>
<mvc:interceptor>
<!-- 拦截所有请求 -->
<mvc:mapping path="/**" />
<bean class="com.xxxx.springmvc.interceptor.MyInterceptor02" />
</mvc:interceptor>
</mvc:interceptors>
三. ⽂件上传
- pom.xml⽂件修改
xml
<!-- 添加 commons-fileupload 依赖 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.2</version>
</dependency>
- servlet-context.xml修改
xml
<!-- ⽂件上传 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 允许⽂件上传的最⼤尺⼨ -->
<property name="maxUploadSize">
<value>104857600</value>
</property>
<!--
设置⽂件放⼊临时⽂件夹的最⼤⼤⼩限制。
此值是阈值,低于此值,则保存在内存中,如⾼于此值,则⽣成硬盘上的临时⽂件。-->
<property name="maxInMemorySize">
<value>4096</value>
</property>
</bean>
四.RestFul URL
Restful ⻛格的 API 是⼀种软件架构⻛格,设计⻛格⽽不是标准,只是提供了⼀组设计原则和约束条件。它主要⽤于客户端和服务器交互类的软件。基于这个⻛格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
在Restful ⻛格中,⽤户请求的 url 使⽤同⼀个 url,⽤请求⽅式:get,post,delete,put...等⽅式对请求的处理⽅法进⾏区分,这样可以在前后台分离式的开发中使得前端开发⼈员不会对请求的资源地址产⽣混淆和⼤量的检查⽅法名的麻烦,形成⼀个统⼀的接⼝。
在 Restful ⻛格中,现有规定如下:
GET(SELECT):从服务器查询,可以在服务器通过请求的参数区分查询的⽅式。
POST(CREATE):在服务器端新建⼀个资源,调⽤ insert 操作。
PUT(UPDATE):在服务器端更新资源,调⽤ update 操作。
PATCH(UPDATE):在服务器端更新资源(客户端提供改变的属性)。(⽬前 jdk7 未实现,tomcat7 不⽀持)。
DELETE(DELETE):从服务器端删除资源,调⽤ delete 语句。
- Get 请求配置
java
/**
* restful --> get 请求,执⾏查询操作
* @param id
* @return
*/
@GetMapping("account/{id}")
@ResponseBody
public Account queryAccountById(@PathVariable Integer id){
return accountService.selectById(id);
}
- Delete 请求配置
java
/* restful-->delete 请求 执⾏删除操作
* @param id
* @return
*/
@DeleteMapping("account/{id}")
@ResponseBody
public Map<String,Object> deleteAccount(@PathVariable Integer id){
int result = accountService.delAccount(id);
Map<String,Object> map=new HashMap<String,Object>();
if(result == 1 ){
map.put("msg","success");
map.put("code",200);
}
else {
map.put("msg","error");
map.put("code",500);
}
return map;
}
- Post 请求配置
java
/* restful --> post 请求,执⾏添加操作
* @return
*/
@PostMapping("account")
@ResponseBody
public Map<String,Object> saveAccount(@RequestBody Account account){
int result = accountService.saveAccount(account);
Map<String,Object> map=new HashMap<String,Object>();
if(result == 1 ){
map.put("msg","success");
map.put("code",200);
}
else {
map.put("msg","error");
map.put("code",500);
}
return map;
}
- Put 请求配置
java
/* restful-->put 请求执⾏更新操作
* @param id
* @param account
* @return
*/
@PutMapping("account")
@ResponseBody
public Map<String,Object> updateAccount(@RequestBody Account account){
int result = accountService.updateAccount(account);
Map<String,Object> map=new HashMap<String,Object>();
if(result == 1 ){
map.put("msg","success");
map.put("code",200);
}
else {
map.put("msg","error");
map.put("code",500);
}
return map;
}
五.全局异常统⼀处理
在 JavaEE 项⽬的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的、不可预知的异常需要处理。每个过程都单独处理异常,系统的代码耦合度⾼,⼯作量⼤且不好统⼀,维护的⼯作量也很⼤。
SpringMVC 对于异常处理这块提供了⽀持,通过 SpringMVC 提供的全局异常处理机制,能够将所有类型的异常处理从各处理过程解耦出来,既保证了相关处理过程的功能较单⼀,也实现了异常信息的统⼀
处理和维护。
全局异常实现⽅式 Spring MVC 处理异常有 3 种⽅式:
- 使⽤ Spring MVC 提供的简单异常处理器 SimpleMappingExceptionResolver
- 实现 Spring 的异常处理接⼝ HandlerExceptionResolver ⾃定义⾃⼰的异常处理器
- 使⽤ @ExceptionHandler 注解实现异常处理
-
全局异常处理⽅式⼀
-
配置简单异常处理器
java<!-- 配置全局异常统⼀处理的 Bean (简单异常处理器) --> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <!-- ⻚⾯在转发时出现异常,设置默认的错误⻚⾯ (error代表的是⼀个视图) --> <property name="defaultErrorView" value="error"></property> <!-- 异常发⽣时,设置异常的变量名 --> <property name="exceptionAttribute" value="ex"></property> </bean>
可以在处理异常的⻚⾯获取异常信息 使用 ${ex}
-
使⽤⾃定义异常
java/** * ⾃定义异常:参数异常 */ public class ParamsException extends RuntimeException { private Integer code = 300; private String msg = "参数异常!"; public ParamsException() { super("参数异常!"); } public ParamsException(String msg) { super(msg); this.msg = msg; } public ParamsException(Integer code) { super("参数异常!"); this.code = code; }
使⽤ SimpleMappingExceptionResolver 进⾏异常处理,具有集成简单、有良好的扩展性、对已有代码没有⼊侵性等优点,但该⽅法仅能获取到异常信息,若在出现异常时,对需要获取除异常以外的数据的
情况不适⽤。
-
-
全局异常处理⽅式⼆(推荐)
-
实现 HandlerExceptionResolver 接⼝
java/** * 全局异常统⼀处理 */ @Component public class GlobalExceptionResolver implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, Exception ex) { ModelAndView mv = new ModelAndView("error"); mv.addObject("ex","默认错误信息"); return mv; } }
-
⾃定义异常处理
java/** * 全局异常统⼀处理 */ @Component public class GlobalExceptionResolver implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, Exception ex) { ModelAndView mv = new ModelAndView("error"); mv.addObject("ex","默认错误信息"); // 判断是否是⾃定义异常 if (ex instanceof ParamsException) { mv.setViewName("params_error"); ParamsException e = (ParamsException) ex; mv.addObject("ex", e.getMsg()); } if (ex instanceof BusinessException) { mv.setViewName("business_error"); BusinessException e = (BusinessException) ex; mv.addObject("ex", e.getMsg()); } return mv; } }
使⽤实现 HandlerExceptionResolver 接⼝的异常处理器进⾏异常处理,具有集成简单、有良好的扩展性、对已有代码没有⼊侵性等优点,同时,在异常处理时能获取导致出现异常的对象,有利于提供更详细的异常处理信息。
-
-
全局异常处理⽅式三
-
⻚⾯处理器继承 BaseController
javapublic class BaseController { @ExceptionHandler public String exc(HttpServletRequest request,HttpServletResponse response,Exception ex){ request.setAttribute("ex", ex); if(ex instanceof ParamsException){ return "error_param"; } if(ex instanceof BusinessException){ return "error_business"; } return "error"; } }
使⽤ @ExceptionHandler 注解实现异常处理,具有集成简单、有扩展性好(只需要将要异常处理的 Controller 类继承于 BaseController 即可)、不需要附加Spring 配置等优点,但该⽅法对已有代码存在⼊侵性(需要修改已有代码,使相关类继承于 BaseController),在异常处理时不能获取除异常以外的数据
-
-
未捕获异常的处理
对于 Unchecked Exception ⽽⾔,由于代码不强制捕获,往往被忽略,如果运⾏期产⽣了Unchecked Exception,⽽代码中⼜没有进⾏相应的捕获和处理,则我们可能不得不⾯对尴尬的 404、 500......等服务器内部错误提示⻚⾯。此时需要⼀个全⾯⽽有效的异常处理机制。⽬前⼤多数服务器也都⽀持在 web.xml 中通过(Websphere/Weblogic)或者(Tomcat)节点配置特定异常情况的显示⻚⾯。修改 web.xml ⽂件,增加以下内容:
xml<!-- 出错⻚⾯定义 --> <error-page> <exception-type>java.lang.Throwable</exception-type> <location>/500.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/500.jsp</location> </error-page> <error-page> <error-code>404</error-code> <location>/404.jsp</location> </error-page>