前言
spring boot使用servlet方式跟原生servlet 存在区别,其内部做一一些校验,使用方式更为严谨。spring boot中的HttpRequster一些request.getReader操作后拿不到的requestBody(请求体),但是在单独的servlet工程可以拿到。
比如使用
wget --post-data ‘{“name”: 123}’ “url?id=123&name=abc”
这样请求再servlet中解析为x-form请求contentType 但依然能拿到post-data 中的内容。而spring boot中则 x-form请求头的内容会被拦截,通过reader.readline则拿不到content。
这时候则如果用linxu用curl请求则需要使用更为严谨专门发http请求的curl命令:
curl -H “ContentType: application/json” -X POST -X GET -d ‘{“name”: 123}’ “url?id=123&name=abc”
spring boot 中的Web开发使用 Controller 基本上可以完成大部分需求,但是我们还可能会用到Servlet、Filter、Listener、Interceptor 等等。
当使用Spring-Boot时,嵌入式Servlet容器通过扫描注解的方式注册Servlet、Filter和Servlet规范的所有监听器(如HttpSessionListener监听器)。
Spring boot 的主 Servlet 为 DispatcherServlet,其默认的url-pattern为“/”。也许我们在应用中还需要定义更多的Servlet。
使用注意
但在spring boot中使用的servlet 地址不会出现在其配置RequestMappings的url中,则会发生不能对这些请求进行监听,比如请求量查看,请求方法的消费和spring cloud断路器运用。
在spring boot中添加自己的Servlet有两种方法,代码注册Servlet和注解自动注册(Filter和Listener也是如此)。
使用方法
ServletRegistrationBean代码注册
通过ServletRegistrationBean、 FilterRegistrationBean 和 ServletListenerRegistrationBean 获得控制。
也可以通过实现 ServletContextInitializer 接口直接注册。
Servlet注解实现
在 SpringBootApplication 上使用@ServletComponentScan注解后,Servlet、Filter、Listener 可以直接通过 @WebServlet、@WebFilter、@WebListener 注解自动注册,无需其他代码。
1、注解实现注册servlet
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(urlPatterns="/myServlet2/*", description="Servlet的说明")
public class MyServlet2 extends HttpServlet{
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(">>>>>>>>>>doGet()<<<<<<<<<<<");
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(">>>>>>>>>>doPost()<<<<<<<<<<<");
resp.setContentType("text/html");
PrintWriter out = resp.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Hello World</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>这是:myServlet2</h1>");
out.println("</body>");
out.println("</html>");
}
}
2、注解实现过滤器Filter
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;
/**
*
* 使用注解标注过滤器
* @WebFilter将一个实现了javax.servlet.Filter接口的类定义为过滤器
* 属性filterName声明过滤器的名称,可选
* 属性urlPatterns指定要过滤的URL模式,也可使用属性value来声明.(指定要过滤的URL模式是必选属性)
*/
@WebFilter(filterName="myFilter",urlPatterns="/*")
publicclass MyFilter implements Filter{
@Override
publicvoid init(FilterConfig config) throws ServletException {
System.out.println("过滤器初始化");
}
@Override
publicvoid doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("执行过滤操作");
chain.doFilter(request, response);
}
@Override
publicvoid destroy() {
System.out.println("过滤器销毁");
}
}
3 、注解拦截器ServletContextListener
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
/**
* 使用@WebListener注解,实现ServletContextListener接口
*
* @author Angel(QQ:412887952)
* @version v.0.1
*/
@WebListener
public class MyServletContextListener implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("ServletContex销毁");
}
@Override
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("ServletContex初始化");
}
}
4、监听Session的创建与销毁
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
* 监听Session的创建与销毁
*
*/
@WebListener
public class MyHttpSessionListener implements HttpSessionListener {
@Override
publicvoid sessionCreated(HttpSessionEvent se) {
System.out.println("Session 被创建");
}
@Override
publicvoid sessionDestroyed(HttpSessionEvent se) {
System.out.println("ServletContex初始化");
}
}
上述功能生效需要
- 然后程序入口加上扫描servlet注解,注解有参数,可以指定扫描某个包注解,支持XXX.*等包解析
@SpringBootApplication
@ServletComponentScan
public class AppApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(AppApplication.class, args);
}
}
- 方案二是采用自己SpringBoot 配置bean的方式进行配置的,SpringBoot提供了三种BeanFilterRegistrationBean、ServletRegistrationBean、ServletListenerRegistrationBean
分别对应配置原生的Filter、Servlet、Listener,下面提供的三个配置和方案一采用的方式能够达到统一的效果
@Bean
public ServletRegistrationBean indexServletRegistration() {
ServletRegistrationBean registration = new ServletRegistrationBean(new IndexServlet());
registration.addUrlMappings("/hello");
return registration;
}
@Bean
public FilterRegistrationBean indexFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean(new IndexFilter());
registration.addUrlPatterns("/");
return registration;
}
@Bean
public ServletListenerRegistrationBean servletListenerRegistrationBean(){
ServletListenerRegistrationBean servletListenerRegistrationBean = new ServletListenerRegistrationBean();
servletListenerRegistrationBean.setListener(new IndexListener());
return servletListenerRegistrationBean;
}
扩展
大家在使用的时候有没有发觉,其实SpringBoot在使用SpringMvc的时候不需要配置DispatcherServlet的,因为已经自动配置了,
但是如果想要加一些初始配置参数如何解决,方案如下:
@Bean
public ServletRegistrationBean dispatcherRegistration(DispatcherServlet dispatcherServlet) {
ServletRegistrationBean registration = new ServletRegistrationBean(dispatcherServlet);
registration.addUrlMappings("*.do");
registration.addUrlMappings("*.json");
return registration;
}
可以通过注入DispatcherServlet 然后用ServletRegistrationBean包裹一层 动态的加上一些初始参数
当然也可以再controller注解的方法中使用httpRequest 和httpReposne也能达到servlet差不多效果。
使用方法如下:
/**
* controller中使用httpRequest
* @Description
* @param request
* @param response
* @param session
* @param out
* @throws IOException
*/
@RequestMapping("/testServletAPI")
public void testServletAPI(HttpServletRequest request,
HttpServletResponse response,HttpSession session,
Writer out) throws IOException{
System.out.println(request);
System.out.println(response);
System.out.println(session);
out.write("hello");
}
}