SpringMVC从入门到精通(二)

Spring MVC

Spring MVC数据类型转换

Spring3引入了更加通用的类型转换系统,其定义了SPI接口(Converter等)和相应的运行时执行类型转换的API(ConversionService等)。该类型转换系统是Spring通用的,其定义在org.springframework.core.convert包中,提供无状态、强类型且可以在任意类型之间转换的类型转换系统,可以用于任何需要的地方,如SpEL、数据绑定。

类型转换器有如下三种接口

(1 )、Converter:类型转换器,用于转换S类型到T类型,此接口的实现必须是线程安全的且可以被共享。

    package org.springframework.core.convert.converter;  
    public interface Converter<S, T> { //① S是源类型 T是目标类型  
        T convert(S source); //② 转换S类型的source到T目标类型的转换方法  
    }   

Converter接口实现只能转换一种类型到另一种类型,不能进行多类型转换,如将一个数组转换成集合,如(String[] ----> List<String>、String[]----->List<PhoneNumberModel>等)
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

(2 )、GenericConverter和ConditionalGenericConverter:GenericConverter接口实现能在多种类型之间进行转换,ConditionalGenericConverter是有条件的在多种类型之间进行转换。

    package org.springframework.core.convert.converter;  
    public interface GenericConverter {  
        //getConvertibleTypes:指定了可以转换的目标类型对;
        Set<ConvertiblePair> getConvertibleTypes();   
        //convert:在sourceType和targetType类型之间进行转换
        Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);  
    } 
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
package org.springframework.core.convert.converter;  
public interface ConditionalGenericConverter extends GenericConverter {  
    //matches:用于判断sourceType和targetType类型之间能否进行类型转换
    boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);  
}   


对于我们大部分用户来说一般不需要自定义GenericConverter, 如果需要可以参考内置的GenericConverter来实现类型转换。
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

(3 )、ConverterFactory:工厂模式的实现,用于选择将一种S源类型转换为R类型的子类型T的转换器的工厂接口。

    package org.springframework.core.convert.converter;  
    public interface ConverterFactory<S, R> {  
        <T extends R> Converter<S, T> getConverter(Class<T> targetType);  
    }   

    S:源类型;R目标类型的父类型;T:目标类型,且是R类型的子类型;
    getConverter:得到目标类型的对应的转换器。
    如org.springframework.core.convert.support.NumberToNumberConverterFactory用于在Number类型子类型之间进行转换,如Integer--->Double, Byte---->Integer, Float--->Double等。 

    对于我们大部分用户来说一般不需要自定义ConverterFactory,如果需要可以参考内置的ConverterFactory来实现类型转换。
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

类型转换器注册器、类型转换服务有如下两种接口

类型转换器注册器、类型转换服务:提供类型转换器注册支持,运行时类型转换API支持。

(1 )、ConverterRegistry:类型转换器注册支持,可以注册/删除相应的类型转换器

    public interface ConverterRegistry {  
        void addConverter(Converter<?, ?> converter);  
        void addConverter(Class<?> sourceType, Class<?> targetType, Converter<?, ?> converter);  
        void addConverter(GenericConverter converter);  
        void addConverterFactory(ConverterFactory<?, ?> converterFactory);  
        void removeConvertible(Class<?> sourceType, Class<?> targetType);  
    } 
    可以注册:Converter实现,GenericConverter实现,ConverterFactory实现。
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

(2 )、ConversionService:运行时类型转换服务接口,提供运行期类型转换的支持。

    package org.springframework.core.convert;  
    public interface ConversionService {  
        boolean canConvert(Class<?> sourceType, Class<?> targetType);  
        boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType);  
        <T> T convert(Object source, Class<T> targetType);  
        Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);  
    }     

 convert:将源对象转换为目标类型的目标对象。  

Spring提供了两个默认实现(其都实现了ConverterRegistry、ConversionService接口):
DefaultConversionService:默认的类型转换服务实现;
DefaultFormattingConversionService:带数据格式化支持的类型转换服务实现,一般使用该服务实现即可。
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

Spring内建的类型转换器

这里写图片描述

扫描二维码关注公众号,回复: 2806689 查看本文章

这里写图片描述

自定义类型转换

我们将页面传递的字符串转换为标准化日期格式。

1.先实现类型转换器 

public class DateConverter implements Converter<String, Date> { 
    //将传入的字符串转换为日期
    public Date convert(String source) {
        SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date date = format.parse(source);
            return date;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

}
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
2.在springmvc配置文件中注册ConversionService实现和自定义的类型转换器 

<bean  id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <!--可以自定义很多类型转换器-->
    <property name="converters">
        <list>
            <bean class="cn.cad.converter.DateConverter"></bean>
        </list>
    </property>
</bean>

FormattingConversionServiceFactoryBean:是FactoryBean实现,默认使用DefaultFormattingConversionService转换器服务实现;
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
3.通过ConfigurableWebBindingInitializer注册ConversionService 

<bean id="customBinder" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
    <property name="conversionService" ref="conversionService"/>
</bean>
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
4.注册ConfigurableWebBindingInitializer到RequestMappingHandlerAdapte 


<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <property name="webBindingInitializer" ref="customBinder"></property>
</bean> 



    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

上面的方法看起来太过繁琐,SpringMVC提供了如下更简单的配置。

<!--前面说过使用<mvc:annotation-driven>就不用再配置映射器和适配器-->
<mvc:annotation-driven conversion-service="conversionService" />

<bean  id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="converters">
        <list>
            <bean class="cn.cad.converter.DateConverter"></bean>
        </list>
    </property>
</bean>
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

如上就完成了类型转换,我们程序页面输入的日期一定要符合format的格式,才能完成转换,否则就会出异常。

Controller返回类型

ModelAndView

controller方法中定义ModelAndView对象并返回,对象中可添加model数据、指定view。  

    
    
  • 1
  • 2

void

有的时候我们并不需要返回值,例如ajax请求时。不过我们也可以在方法参数列表上添加request等来进行页面跳转等操作。 

    
    
  • 1
  • 2

String

controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。 
至于数据,我们可以通过默认的Model或者ModelMap来传递参数。
通过 return "redirect:/xxx.jso"  来重定向或者转发

    
    
  • 1
  • 2
  • 3
  • 4

SpringMVC异常处理

在SpringMVC中,系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理。springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统一异常处理。

这里写图片描述

这里有篇关于SpringMVC异常处理的文章写的很棒,我就不再重复。
http://blog.csdn.net/eson_15/article/details/51731567

SpringMVC文件上传

1.首先需要加入jar包
    
    
  • 1

这里写图片描述

2.配置上传解析器

<bean id="multipartResolver"
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 设置文件上传大小 -->
    <property name="maxUploadSize" value="5000000" />
</bean>
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
3.表单一定要设置enctype="multipart/form-data" 

然后接收文件的方法 添加一个参数 
//通过MultipartFile 接收上传的文件
public  ModelAndView updateItem(Items item,MultipartFile pictureFile) throws IllegalStateException, Exception {
        String picName = UUID.randomUUID().toString();

        // 获取文件名
        String oriName = pictureFile.getOriginalFilename();
        System.out.println(oriName);


        // 开始上传文件
        pictureFile.transferTo(new File("F:\\upload\\" + picName + extName));


        itemService.updateItemById(item);
        ModelAndView modelAndView=new ModelAndView();
        modelAndView.setViewName("forward:/itemEdit");
        return modelAndView;
    }

    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

这篇博客详细介绍了SpringMVC的上传下载。
http://blog.csdn.net/evankaka/article/details/45826697/

SpringMVC拦截器

Spring Web MVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。

拦截器接口

package org.springframework.web.servlet;  
public interface HandlerInterceptor {  
    boolean preHandle(  
            HttpServletRequest request, HttpServletResponse response,   
            Object handler)   
            throws Exception;  

    void postHandle(  
            HttpServletRequest request, HttpServletResponse response,   
            Object handler, ModelAndView modelAndView)   
            throws Exception;  

    void afterCompletion(  
            HttpServletRequest request, HttpServletResponse response,   
            Object handler, Exception ex)  
            throws Exception;  
}  
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
preHandle:处理器前执行的方法,实现处理器的预处理(如登录检查),第三个参数为响应的处理器(如我们上一章的Controller实现);
     返回值:true表示继续流程(如调用下一个拦截器或处理器);
           false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应; 

postHandle:处理器后回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。 

afterCompletion:整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中preHandle返回true的拦截器的afterCompletion。 

    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

有时候我们可能只需要实现三个回调方法中的某一个,如果实现HandlerInterceptor接口的话,三个方法必须实现,不管你需不需要,此时spring提供了一个HandlerInterceptorAdapter适配器,允许我们只实现需要的回调方法。

public abstract class HandlerInterceptorAdapter implements HandlerInterceptor {  
     //省略代码 此处所以三个回调方法都是空实现,preHandle返回true。  
}  
    
    
  • 1
  • 2
  • 3

案例

1.编写拦截器
public class HandlerInterceptor1 extends HandlerInterceptorAdapter {//此处一般继承HandlerInterceptorAdapter适配器即可  
    @Override  
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  
        System.out.println("===========拦截器 preHandle");  
        return true;  
    }  
    @Override  
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {  
        System.out.println("===========拦截器 postHandle");  
    }  
    @Override  
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {  
        System.out.println("===========拦截器 afterCompletion");  
    }
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
2.编写处理器
@Controller
public class TestController {  

    @RequestMapping("/test")
    public ModelAndView test() {  
        System.out.println("===========TestController");  
        return new ModelAndView("test");  
    }  
}  
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
3.配置拦截器
<mvc:interceptors>
    <!--可以配置很多拦截器-->
    <mvc:interceptor>
        <!-- 所有的请求都进入拦截器 -->
        <mvc:mapping path="/**" />
        <!-- 配置具体的拦截器 -->
        <bean class="cn.cad.HandlerInterceptor1" />
    </mvc:interceptor>
</mvc:interceptors>

    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

然后进行检测即可。可以用来做登录检测、性能检测等。

Spring MVC

Spring MVC数据类型转换

Spring3引入了更加通用的类型转换系统,其定义了SPI接口(Converter等)和相应的运行时执行类型转换的API(ConversionService等)。该类型转换系统是Spring通用的,其定义在org.springframework.core.convert包中,提供无状态、强类型且可以在任意类型之间转换的类型转换系统,可以用于任何需要的地方,如SpEL、数据绑定。

类型转换器有如下三种接口

(1 )、Converter:类型转换器,用于转换S类型到T类型,此接口的实现必须是线程安全的且可以被共享。

    package org.springframework.core.convert.converter;  
    public interface Converter<S, T> { //① S是源类型 T是目标类型  
        T convert(S source); //② 转换S类型的source到T目标类型的转换方法  
    }   

Converter接口实现只能转换一种类型到另一种类型,不能进行多类型转换,如将一个数组转换成集合,如(String[] ----> List<String>、String[]----->List<PhoneNumberModel>等)
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

(2 )、GenericConverter和ConditionalGenericConverter:GenericConverter接口实现能在多种类型之间进行转换,ConditionalGenericConverter是有条件的在多种类型之间进行转换。

    package org.springframework.core.convert.converter;  
    public interface GenericConverter {  
        //getConvertibleTypes:指定了可以转换的目标类型对;
        Set<ConvertiblePair> getConvertibleTypes();   
        //convert:在sourceType和targetType类型之间进行转换
        Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);  
    } 
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
package org.springframework.core.convert.converter;  
public interface ConditionalGenericConverter extends GenericConverter {  
    //matches:用于判断sourceType和targetType类型之间能否进行类型转换
    boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);  
}   


对于我们大部分用户来说一般不需要自定义GenericConverter, 如果需要可以参考内置的GenericConverter来实现类型转换。
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

(3 )、ConverterFactory:工厂模式的实现,用于选择将一种S源类型转换为R类型的子类型T的转换器的工厂接口。

    package org.springframework.core.convert.converter;  
    public interface ConverterFactory<S, R> {  
        <T extends R> Converter<S, T> getConverter(Class<T> targetType);  
    }   

    S:源类型;R目标类型的父类型;T:目标类型,且是R类型的子类型;
    getConverter:得到目标类型的对应的转换器。
    如org.springframework.core.convert.support.NumberToNumberConverterFactory用于在Number类型子类型之间进行转换,如Integer--->Double, Byte---->Integer, Float--->Double等。 

    对于我们大部分用户来说一般不需要自定义ConverterFactory,如果需要可以参考内置的ConverterFactory来实现类型转换。
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

类型转换器注册器、类型转换服务有如下两种接口

类型转换器注册器、类型转换服务:提供类型转换器注册支持,运行时类型转换API支持。

(1 )、ConverterRegistry:类型转换器注册支持,可以注册/删除相应的类型转换器

    public interface ConverterRegistry {  
        void addConverter(Converter<?, ?> converter);  
        void addConverter(Class<?> sourceType, Class<?> targetType, Converter<?, ?> converter);  
        void addConverter(GenericConverter converter);  
        void addConverterFactory(ConverterFactory<?, ?> converterFactory);  
        void removeConvertible(Class<?> sourceType, Class<?> targetType);  
    } 
    可以注册:Converter实现,GenericConverter实现,ConverterFactory实现。
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

(2 )、ConversionService:运行时类型转换服务接口,提供运行期类型转换的支持。

    package org.springframework.core.convert;  
    public interface ConversionService {  
        boolean canConvert(Class<?> sourceType, Class<?> targetType);  
        boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType);  
        <T> T convert(Object source, Class<T> targetType);  
        Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);  
    }     

 convert:将源对象转换为目标类型的目标对象。  

Spring提供了两个默认实现(其都实现了ConverterRegistry、ConversionService接口):
DefaultConversionService:默认的类型转换服务实现;
DefaultFormattingConversionService:带数据格式化支持的类型转换服务实现,一般使用该服务实现即可。
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

Spring内建的类型转换器

这里写图片描述

这里写图片描述

自定义类型转换

我们将页面传递的字符串转换为标准化日期格式。

1.先实现类型转换器 

public class DateConverter implements Converter<String, Date> { 
    //将传入的字符串转换为日期
    public Date convert(String source) {
        SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date date = format.parse(source);
            return date;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
2.在springmvc配置文件中注册ConversionService实现和自定义的类型转换器 

<bean  id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <!--可以自定义很多类型转换器-->
    <property name="converters">
        <list>
            <bean class="cn.cad.converter.DateConverter"></bean>
        </list>
    </property>
</bean>

FormattingConversionServiceFactoryBean:是FactoryBean实现,默认使用DefaultFormattingConversionService转换器服务实现;
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
3.通过ConfigurableWebBindingInitializer注册ConversionService 

<bean id="customBinder" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
    <property name="conversionService" ref="conversionService"/>
</bean>
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
4.注册ConfigurableWebBindingInitializer到RequestMappingHandlerAdapte 


<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <property name="webBindingInitializer" ref="customBinder"></property>
</bean> 



  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

上面的方法看起来太过繁琐,SpringMVC提供了如下更简单的配置。

<!--前面说过使用<mvc:annotation-driven>就不用再配置映射器和适配器-->
<mvc:annotation-driven conversion-service="conversionService" />

<bean  id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="converters">
        <list>
            <bean class="cn.cad.converter.DateConverter"></bean>
        </list>
    </property>
</bean>
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

如上就完成了类型转换,我们程序页面输入的日期一定要符合format的格式,才能完成转换,否则就会出异常。

Controller返回类型

ModelAndView

controller方法中定义ModelAndView对象并返回,对象中可添加model数据、指定view。  

  
  
  • 1
  • 2

void

有的时候我们并不需要返回值,例如ajax请求时。不过我们也可以在方法参数列表上添加request等来进行页面跳转等操作。 

  
  
  • 1
  • 2

String

controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。 
至于数据,我们可以通过默认的Model或者ModelMap来传递参数。
通过 return "redirect:/xxx.jso"  来重定向或者转发

  
  
  • 1
  • 2
  • 3
  • 4

SpringMVC异常处理

在SpringMVC中,系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理。springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统一异常处理。

这里写图片描述

这里有篇关于SpringMVC异常处理的文章写的很棒,我就不再重复。
http://blog.csdn.net/eson_15/article/details/51731567

SpringMVC文件上传

1.首先需要加入jar包
  
  
  • 1

这里写图片描述

2.配置上传解析器

<bean id="multipartResolver"
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 设置文件上传大小 -->
    <property name="maxUploadSize" value="5000000" />
</bean>
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
3.表单一定要设置enctype="multipart/form-data" 

然后接收文件的方法 添加一个参数 
//通过MultipartFile 接收上传的文件
public  ModelAndView updateItem(Items item,MultipartFile pictureFile) throws IllegalStateException, Exception {
        String picName = UUID.randomUUID().toString();

        // 获取文件名
        String oriName = pictureFile.getOriginalFilename();
        System.out.println(oriName);


        // 开始上传文件
        pictureFile.transferTo(new File("F:\\upload\\" + picName + extName));


        itemService.updateItemById(item);
        ModelAndView modelAndView=new ModelAndView();
        modelAndView.setViewName("forward:/itemEdit");
        return modelAndView;
    }

  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

这篇博客详细介绍了SpringMVC的上传下载。
http://blog.csdn.net/evankaka/article/details/45826697/

SpringMVC拦截器

Spring Web MVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。

拦截器接口

package org.springframework.web.servlet;  
public interface HandlerInterceptor {  
    boolean preHandle(  
            HttpServletRequest request, HttpServletResponse response,   
            Object handler)   
            throws Exception;  

    void postHandle(  
            HttpServletRequest request, HttpServletResponse response,   
            Object handler, ModelAndView modelAndView)   
            throws Exception;  

    void afterCompletion(  
            HttpServletRequest request, HttpServletResponse response,   
            Object handler, Exception ex)  
            throws Exception;  
}  
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
preHandle:处理器前执行的方法,实现处理器的预处理(如登录检查),第三个参数为响应的处理器(如我们上一章的Controller实现);
     返回值:true表示继续流程(如调用下一个拦截器或处理器);
           false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应; 

postHandle:处理器后回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。 

afterCompletion:整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中preHandle返回true的拦截器的afterCompletion。 

  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

有时候我们可能只需要实现三个回调方法中的某一个,如果实现HandlerInterceptor接口的话,三个方法必须实现,不管你需不需要,此时spring提供了一个HandlerInterceptorAdapter适配器,允许我们只实现需要的回调方法。

public abstract class HandlerInterceptorAdapter implements HandlerInterceptor {  
     //省略代码 此处所以三个回调方法都是空实现,preHandle返回true。  
}  
  
  
  • 1
  • 2
  • 3

案例

1.编写拦截器
public class HandlerInterceptor1 extends HandlerInterceptorAdapter {//此处一般继承HandlerInterceptorAdapter适配器即可  
    @Override  
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  
        System.out.println("===========拦截器 preHandle");  
        return true;  
    }  
    @Override  
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {  
        System.out.println("===========拦截器 postHandle");  
    }  
    @Override  
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {  
        System.out.println("===========拦截器 afterCompletion");  
    }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
2.编写处理器
@Controller
public class TestController {  

    @RequestMapping("/test")
    public ModelAndView test() {  
        System.out.println("===========TestController");  
        return new ModelAndView("test");  
    }  
}  
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
3.配置拦截器
<mvc:interceptors>
    <!--可以配置很多拦截器-->
    <mvc:interceptor>
        <!-- 所有的请求都进入拦截器 -->
        <mvc:mapping path="/**" />
        <!-- 配置具体的拦截器 -->
        <bean class="cn.cad.HandlerInterceptor1" />
    </mvc:interceptor>
</mvc:interceptors>

  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

然后进行检测即可。可以用来做登录检测、性能检测等。

猜你喜欢

转载自blog.csdn.net/tao5375/article/details/81744725