如题。本篇,我们介绍写springboot (web工程)中mvc拦截器使用以及web servlet、filter、listener的使用。
spring mvc拦截器,能够拦截对指定路径的controller的访问 ,但不会拦截对servlet的访问,因为本质上讲springMVC(前端控制器)也是个servlet,试问servlet又怎么能够拦截对servlet的访问呢?
package com.tingcream.springWeb.spring.mvc;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
/**
* mvc 拦截器 ,记录请求者ip和请求路径
* @author jelly
*
*/
@Component
public class MyMvcInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
String clientIP= request.getRemoteAddr();
String contextPath=request.getContextPath();
String uri=request.getRequestURI();
String requestPage=uri.replaceFirst(contextPath, "").replaceAll("/+", "/");
System.out.println("请求者IP:"+clientIP+",请求页面:"+requestPage);
return true;
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2, ModelAndView arg3) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest arg0,
HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
}
}
package com.tingcream.springWeb.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import com.tingcream.springWeb.spring.mvc.MyMvcInterceptor;
/**
* mvc interceptor 配置bean
*
* @author jelly
*
*/
@Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
@Autowired
private MyMvcInterceptor myMvcInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myMvcInterceptor).addPathPatterns("/**");
}
}
servlet 、filter、listener 三者都是servlet web容器中的东西,它们跟web容器产生之间关联,而跟spring其实没有直接的联系。
其实spring不一定要非得运行在web环境中,只不过因为我们大多数人都是用spring开发web程序,所以会很自然地把web容器和spring容器相混淆。而在web环境中,spring容器是web容器所创建的一个环境,实际上web中的spring只不过是web容器的一个监听器(servlet listener)
咳咳,我们现在回到正题。
springboot web项目中由于没有了web.xml,传统的在web.xml中配置servlet、filter、listener的方式显然是行不通的了,那么怎么办呢?
其实在servlet3.0规范中,已经不建议开发者在web.xml中配置servlet、filter、listener了,而是采用@WebServlet、@WebFilter、@WebListener注解方式进行标记。采用注解的方式能够有效避免web.xml配置文件的过于膨胀,并且注解方式使用起来更简洁,方便,对开发人员更友好。
MyServlet.java
package com.tingcream.springWeb.web.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* servlet
*
* @author jelly
*
*/
@WebServlet("/myServlet")
public class MyServlet extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("/myServlet 访问成功!!");
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().write("/myServlet 访问成功!! ");
}
}
MyFilter.java
package com.tingcream.springWeb.web.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
/**
* servlet 过滤器
* @author jelly
*
*/
@WebFilter(filterName="myFilter",urlPatterns="/*")
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("myFilter==========init");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("myFilter==========doFilter");
chain.doFilter(request,response);
}
@Override
public void destroy() {
System.out.println("myFilter==========destroy");
}
}
MyListener.java
package com.tingcream.springWeb.web.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
/**
* servet 监听器
* @author jelly
*
*/
@WebListener
public class MyListener implements ServletContextListener {
/**
* servlet 容器初始化
*/
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("MyListener-----servlet容器初始化 ");
}
/**
* servlet 容器销毁
*/
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("MyListener-----servlet容器销毁 ");
}
}
package com.tingcream.springWeb;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.aop.AopAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ImportResource;
/**
* spring-boot 入口程序
*
* @author jelly
*
*/
//@SpringBootApplication
@SpringBootConfiguration
@EnableAutoConfiguration(exclude={
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
JdbcTemplateAutoConfiguration.class,
AopAutoConfiguration.class})
@ComponentScan
@ImportResource({"classpath:/spring.xml"})
@ServletComponentScan
public class SpringBootApp extends SpringBootServletInitializer{
//实现SpringBootServletInitializer接口 ,需实现此方法。 可以war包形式 发布到tomcat中
@Override
protected SpringApplicationBuilder configure(
SpringApplicationBuilder builder) {
return builder.sources(SpringBootApp.class);
}
public static void main(String[] args) {
SpringApplication.run(SpringBootApp.class, args);
}
}
ok !!!
最后,笔者想简单介绍下关于spring web中的controller、servlet(jsp)、filter、listener的初始化、执行、销毁顺序 。
(启动容器时)
Listener初始化
Filter初始化
servlet初始化(第一次请求时)
controller初始化
Filter过滤器可以对servlet和controller进行过滤,而mvc拦截器只能对controller进行过滤。
如果浏览器请求了一个controller路径,则执行顺序如下:
Filter过滤器
mvc拦截器
controller
......
如果浏览器请求了一个servlet、jsp路径,则执行顺序如下:
Filter过滤器
servlet、jsp
.....
(最后停止容器时)
controller销毁
servlet、jsp销毁
filter销毁
Listener销毁