上篇分享我们已经有了一个最基础具有登陆验证功能 的SpringBoot web项目,本篇对照之前SpringMVC 的xml配置,阐述SpringBoot 中的filter 和 interceptor。
一、web.xml中的filter 和 SpringBoot filter 比较。
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在SpringBoot 中我们定义一个filter:
package cn.pw.pf.web.filter;
import org.springframework.core.annotation.Order;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* 自定义Filter
* Login Filter
* @Description:
* @Author:libin
* @Date: Created in 16:40 2017/11/13
*/
@WebFilter(filterName = "myFilter",urlPatterns = "/*")
@Order(1)
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("filter======> 我是过滤器!");
chain.doFilter(request,response);
}
@Override
public void destroy() {
}
}
@WebFilter 是自定义Filter的关键注解,属性filterName 相当于web.xml中的 <filter-name>
;属性urlPatterns 相当于web.xml中的<url-pattern>
。
@Order(1)在定义多个Filter时,用于决定执行顺序的,数字越小,越先执行。
说明:本篇以web.xml的CharacterEncodingFilter为例,但在SpringBoot中CharacterEncodingFilter有更简单的配置,在application.xml中做如下配置便可 :
spring:
http:
encoding:
charset: UTF-8
enabled: true
force: true
言归正传,我们启动项目测试一下过滤器是否 生效:
在浏览器分别打开 http://localhost:8680/hello 和 http://localhost:8680/login ,观察控制台输出,如果不出意外,控制台连续输出了 “filter======> 我是过滤器!”,看来我们的过滤器生效了,我们还可以将urlPatterns 设置 为 /hello ,这样只有访问 http://localhost:8680/hello 时,控制台才会输出 “filter======> 我是过滤器!”。
二、spring-mvc.xml中的 interceptor 和SpringBoot interceptor 比较
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/static/**" />
<bean class="cn.pw.pf.web.filter.MyInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
上面的配置不用解释,先在filter包下编写一个MyInterceptor类。
package cn.pw.pf.web.filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 自定义拦截器
* @Description:
* @Author:libin
* @Date: Created in 17:46 2017/11/13
*/
@Component
public class MyInterceptor implements HandlerInterceptor {
Logger logger = LoggerFactory.getLogger(MyInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
logger.info("执行preHandle==============》");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
logger.info("执行postHandle==============》");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
logger.info("执行afterCompletion==============》");
}
}
下面我们看在SpringBoot中如何让自定义的拦截器MyInterceptor 生效
package cn.pw.pf.web.filter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 配置自定义拦截器
* @Description:
* @Author:libin
* @Date: Created in 17:41 2017/11/13
*/
@Configuration
public class MyWebConfig extends WebMvcConfigurerAdapter{
@Autowired
private MyInterceptor myInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor).addPathPatterns("/*").excludePathPatterns("/hello/**");
super.addInterceptors(registry);
}
}
阅读上面的代码,我们不难发现,主要在重写WebMvcConfigurerAdapter的addInterceptors方法上,addPathPatterns添加了要拦截的路径,excludePathPatterns添加了排除的路径。
我们重启项目,测试一下,访问 http://localhost:8680/login ,也可以在login界面点击登录。
测试结果,我们分析任何一次访问都经过了filter和interceptor。
filter======> 我是过滤器!
cn.pw.pf.web.filter.MyInterceptor : 执行preHandle==============》
cn.pw.pf.web.filter.MyInterceptor : 执行postHandle==============》
cn.pw.pf.web.filter.MyInterceptor : 执行afterCompletion==============》
我们再访问排除的URL是否生效,打开 http://localhost:8680/hello ,页面上显示出了内容,控制台只是输出了
filter======> 我是过滤器!
我们排除掉的”/hello/**”,拦截器不再拦截它,测试顺利通过!
有同学就问了,你为什么不按spring-mvc.xml中一样 ,排除 static 资源。原因很简单,SpringBoot默认不拦截所有的静态资源,如果不信,可以 直接访问 http://localhost:8680/css/common.css 试试。
说明:SpringBoot把类路径下的/static,/public,/resources和META-INF/resources文件下的静态文件映射为了 “/”,可以直接访问,我们也可以根据下面的方法自定义静态文件的存放位置。
三、自定义静态文件存放 位置,只需在MyWebConfig 中,重写addResourceHandlers方法。
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/img/**").addResourceLocations("classpath:/img/");
super.addResourceHandlers(registry);
}
这样,我们就定义了一个和static平级的文件夹img用来存放图片,随便丢一张 图片no.jpg进去,然后带上路径访问:
http://localhost:8680/img/no.jpg
OK,今天的分享就到此结束了,SpringBoot的基础使用就分享这么多,很简单。
到今天互联网迸发的时代,微服务已是大势所趋,只有在 SpringCloud 微服务架构下,使用SpringBoot才是开发人员值得研究的方向。如果有人想深入了解SpringBoot ,我推荐《java EE 开发的颠覆者 Spring Boot 实战》这本书。但是,初学的读者一定要注意,这本书是在SpringBoot 1.3版本的基础上讲解的,想实践书中的例子,一定要用对版本,要不会很苦恼。
后面的分享,我将开启新的篇章,结合SpringCloud 、Eureka、等,逐步由简入深,来完成一个基于微服务框架的简单demo,帮助初学者快速上手。