拦截器属于AOP的一种实现,在现在的开发之中如果不是提供拦截器,那么基本上这个框架的设计就属于失败的设计,而在SpringMVC里面也自然提供有拦截器的操作.
在Spring里面提供有一个专门的拦截器实现接口:org.springframework.web.servlet.HandlerInterceptor.在这个接口里面一共定义有三个方法:
操作执行前拦截:
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, java.lang.Object handler) throws java.lang.Exception
执行时拦截
default void postHandle(HttpServletRequest request, HttpServletResponse response, java.lang.Object handler, @Nullable ModelAndView modelAndView) throws java.lang.Exception
操作执行完拦截
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, java.lang.Object handler, @Nullable java.lang.Exception ex) throws java.lang.Exception
大部分情况下都会在preHandle里面进行处理,因为拦截器主要处理的就是拦截前的操作,
范例:定义一个拦截器
package cn.zwb.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class MyHandler implements HandlerInterceptor{
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse response, Object obj, Exception ex)
throws Exception {
System.out.println("##############33执行处理完毕");
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
// TODO Auto-generated method stub
System.out.println("##########执行中拦截");
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) throws Exception {
System.out.println("#############3执行前拦截");
return true;
}
}
随后在applicationContext.xml文件里面去定义拦截器的使用
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/pages/**/*.action"/>
<bean class="cn.zwb.interceptor.MyHandler"></bean>
</mvc:interceptor>
</mvc:interceptors>
在整个SpringMVC里面采用了同样结构的资源定位符号,此处表示在pages目录下的所有的*.action都进行拦截
在整个的拦截器的处理过程之中,将处理的步骤拆分的非常细,但是拦截器最为重要的做法是进行输入数据的拦截操作,可是这个操作要如何进行呢?要想进行输入数据的拦截,那么重点就要放在perHandler()方法上,
如果说这个方法返回true表示正常向下执行,而返回false表示不执行后续的操作.
要想进行数据验证拦截操作.那么关键的部分就在于preHandle()方法里面的Object参数.
org.springframework.web.method.HandlerMethod
在这个类里面定义有如下的一堆操作方法:
触发此拦截器的程序类(Action):public Object getBean();
取得处理的方法:public Method get,ethod();
取得Bean的类型:public Class<?> getBeanType();
取得方法的参数数据:
public MethodParameter[] getMethodParameters()
取得方法:
public java.lang.reflect.Method getMethod()取得参数名称:
public java.lang.String getParameterName()
取得参数类型:
public java.lang.Class<?> getParameterType()
范例:取得要操作的Action数据:
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) throws Exception {
HandlerMethod hanm=(HandlerMethod)obj;
System.out.println("#############3执行前拦截");
System.out.println("操作的Action对象"+hanm.getBean()+",类型:"+hanm.getBeanType()+",方法名称:"+hanm.getMethod());
MethodParameter[] methodParameters = hanm.getMethodParameters();
for (MethodParameter methodParameter : methodParameters) {
System.out.println("方法:"+methodParameter.getMethod()+",参数名称"+methodParameter.getParameterName());
}
return true;
}
此时只要是用户执行的操作,现在都可以利用拦截器取得.
既然可以取得了基础内容,那么下面就可以实现信息的验证功能.
范例:实现拦截处理
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) throws Exception {
HandlerMethod hanm=(HandlerMethod)obj;
System.out.println("#############3执行前拦截");
System.out.println("操作的Action对象"+hanm.getBean()+",类型:"+hanm.getBeanType()+",方法名称:"+hanm.getMethod());
MethodParameter[] methodParameters = hanm.getMethodParameters();
for (MethodParameter methodParameter : methodParameters) {
System.out.println("方法:"+methodParameter.getMethod()+",参数名称"+methodParameter.getParameterName());
}
try{
String fieldName=hanm.getMethod().getName()+"Rule";
Field field=hanm.getBean().getClass().getDeclaredField(fieldName);
field.setAccessible(true);
String rules=(String) field.get(hanm.getBean());//取得规则信息
System.out.println("**********取得规则信息**********"+rules);
String result[]=rules.split("\\|"); //拆分验证规则
for (String string : result) {
String temp[]=string.split(":");
String paramValue=request.getParameter(temp[0]);
System.out.println("参数名称:"+temp[0]+",参数内容:"+paramValue+",验证规则:"+temp[1]);
}
}catch(Exception e){
}
return true;
}
但是对于拦截器的操作还需要考虑一种情况,那么就是表单的文件上传问题.对于上传文件一般都会要求有限制,例如,本次的上传操作只能够是图片,那么就需要在拦截器里面继续进行拦截的配置.
范例:定义表单
<body>
<form action="pages/hello/insert.action" method="post" enctype="multipart/form-data">
新闻编号:<input type="text" id="nid" name="nid" value="999"><br>
消息名称:<input type="text" id="title" name="title" value="啦啦啦"><br>
上传文件:<input type="file" id="pic" name="pic" ><br>
<input type="submit" value="提交">
<input type="reset" value="重置">
</form>
</body>
现在发现对于上传的文件并没有设置相应的验证规则,所以现在进一步完善拦截器
范例:拦截非法图片信息
package package cn.zwb.interceptor;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.core.MethodParameter;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartRequest;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class MyHandler implements HandlerInterceptor{
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse response, Object obj, Exception ex)
throws Exception {
System.out.println("##############33执行处理完毕");
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
// TODO Auto-generated method stub
System.out.println("##########执行中拦截");
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) throws Exception {
HandlerMethod hanm=(HandlerMethod)obj;
System.out.println("#############3执行前拦截");
System.out.println("操作的Action对象"+hanm.getBean()+",类型:"+hanm.getBeanType()+",方法名称:"+hanm.getMethod());
MethodParameter[] methodParameters = hanm.getMethodParameters();
for (MethodParameter methodParameter : methodParameters) {
System.out.println("方法:"+methodParameter.getMethod()+",参数名称"+methodParameter.getParameterName());
}
//定义一个专门用于保存错误信息的map集合
Map<String, String> errors=new HashMap<String, String>();
try{
String fieldName=hanm.getMethod().getName()+"Rule";
Field field=hanm.getBean().getClass().getDeclaredField(fieldName);
field.setAccessible(true);
String rules=(String) field.get(hanm.getBean());//取得规则信息
System.out.println("**********取得规则信息**********"+rules);
String result[]=rules.split("\\|"); //拆分验证规则
for (String string : result) {
String temp[]=string.split(":");
String paramValue=request.getParameter(temp[0]);
System.out.println("参数名称:"+temp[0]+",参数内容:"+paramValue+",验证规则:"+temp[1]);
if(paramValue==null){
errors.put(temp[0], "数据内容不允许为空");
return false;
}else{
if("int".equalsIgnoreCase(temp[1])){
if(!paramValue.matches("\\d+")){
errors.put(temp[0], "数据类型必须是整数!!");
return false;
}
}
}
}
}catch(Exception e){}
boolean flag=true;
if(errors.size()>0){ //有错误信息再进行跳转
flag=false;
}else{ //表示现在的基础信息验证完成.下面需要判断是否有上传文件
MultipartResolver mr=new CommonsMultipartResolver();
if(mr.isMultipart(request)){ //如果有文件上传
MultipartRequest mreq=(MultipartRequest)request;//取得上传文件的内容
Map<String,MultipartFile > map= mreq.getFileMap(); //取得所有的上传文件
if(map.size()>0){
Field field=hanm.getBean().getClass().getDeclaredField("mimeRule");
field.setAccessible(true);
String mime=(String)field.get(hanm.getBean());
System.out.println(mime);
String resultMime[]=mime.split(",");
Iterator<Map.Entry<String,MultipartFile>> it=map.entrySet().iterator();
while(it.hasNext()){
Map.Entry<String,MultipartFile> me=it.next();
String fileName=me.getKey();
MultipartFile file=me.getValue(); //取得文件内容
System.out.println("文件名称:"+fileName+",文件内容:"+file+",\n"+file.getContentType());
if(!this.isExists(resultMime, file.getContentType())){
errors.put(fileName, "上传了非法文件");
flag=false;
break;
}
}
}
}
}
if(!flag){
System.out.println(errors);
request.getRequestDispatcher("/errors.jap").forward(request, response);
return false;
}
return true;
}
public boolean isExists(String data[],String str){
for (String string : data) {
if(str.equals(string)){
return true;
}
}
return false;
}
}
}