在spring boot中添加自己的Servlet有两种方法,代码注册Servlet和注解自动注册(Filter和Listener也是如此)。
- 代码注册通过ServletRegistrationBean、 FilterRegistrationBean 和 ServletListenerRegistrationBean 获得控制。 也可以通过实现 ServletContextInitializer 接口直接注册。
- 在 SpringBootApplication 上使用@ServletComponentScan 注解后,Servlet、Filter、Listener 可以直接通过 @WebServlet、@WebFilter、@WebListener 注解自动注册,无需其他代码。
Servlet3.0作为J2EE 6规范一部分,并随J2EE6一起发布,WeFilter是过滤器注解,@WebServlet是Servlet注解,是Servlet3.0的新特性,不需要在web.xml进行配置,简化了配置。
一、servlet介绍
Web开发使用 Controller 基本上可以完成大部分需求,但是我们还可能会用到 Servlet、Filter、Listener、Interceptor 等等。这里重点是总结一下Servlet相关知识。在Servlet3.0之后,创建Servlet可以有以下方法:
- 我之前一直是自定义一个类继承HttpServlet,并把类路径配置到在web.xml中来实现得。
- 在servlet3.0以后,我们可以不用再web.xml里面配置servlet,只需要加上代码类上@WebServlet注解就可以修改该servlet的属性了。
二、@WebServlet的使用方法
在servlet3.0以后,我们可以不用再web.xml里面配置servlet,只需要加上@WebServlet注解就可以修改该servlet的属性了。
下面是@WebServlet的属性列表。
属性名 | 类型 | 描述 |
name | String | 指定Servlet 的 name 属性,等价于 <servlet-name>。如果没有显式指定,则该 Servlet 的取值即为类的全限定名。 |
value | String[] | 该属性等价于 urlPatterns 属性。两个属性不能同时使用。 |
urlPatterns | String[] | 指定一组 Servlet 的 URL 匹配模式。等价于<url-pattern>标签。 |
loadOnStartup | int | 指定 Servlet 的加载顺序,等价于 <load-on-startup>标签。 |
initParams | WebInitParam[] | 指定一组 Servlet 初始化参数,等价于<init-param>标签。 |
asyncSupported | boolean | 声明 Servlet 是否支持异步操作模式,等价于<async-supported> 标签。 |
description | String | 该 Servlet 的描述信息,等价于 <description>标签。 |
displayName | String | 该 Servlet 的显示名,通常配合工具使用,等价于 <display-name>标签。 |
注解Servlet这个在spring boot自动配置中正好可用。在spring boot中,嵌入式Servlet容器通过扫描注解的方式注册Servlet、Filter和Servlet规范的所有监听器(如HttpSessionListener监听器)。
Spring boot 的主 Servlet 为 DispatcherServlet,其默认的url-pattern为“/”。也许我们在应用中还需要定义更多的Servlet,该如何使用SpringBoot来完成呢?
1、通过代码注册Servlet示例代码:
package com.dxz.demo.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet extends HttpServlet {
private static final long serialVersionUID = -8685285401859800066L;
@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>MyServlet doPost()</h1>");
out.println("</body>");
out.println("</html>");
}
}
//spring boot启动类
package com.dxz.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.embedded.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import com.dxz.demo.servlet.MyServlet;
@SpringBootApplication
public class DemoApplication {
/**
* 使用代码注册Servlet(不需要@ServletComponentScan注解)
* @return
*/
@Bean
public ServletRegistrationBean servletRegistrationBean() {
return new ServletRegistrationBean(new MyServlet(), "/xs/*");// ServletName默认值为首字母小写,即myServlet
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
结果:
2、使用注解注册Servlet示例代码
package com.dxz.demo.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(name="myservlet2", //不指定name的情况下,name默认值为类全路径,即com.dxz.demo.servlet.MyServlet2
urlPatterns="/xs2/dev",
loadOnStartup=1,
description="用注解声明Servlet",
initParams={//以下都是druid数据源状态监控的参数
@WebInitParam(name="allow",value=""),// IP白名单 (没有配置或者为空,则允许所有访问)
@WebInitParam(name="deny",value=""),// IP黑名单 (存在共同时,deny优先于allow)
@WebInitParam(name="loginUsername",value="dev"),// 用户名
@WebInitParam(name="loginPassword",value="123456"),// 密码
@WebInitParam(name="resetEnable",value="false")// 禁用HTML页面上的“Reset All”功能
})
public class MyServlet2 extends HttpServlet {
private static final long serialVersionUID = -8685285401859800066L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(">>>>>>>>>>MyServlet2 doGet()<<<<<<<<<<<");
ServletConfig config= getServletConfig();
System.out.println(config.getInitParameter("loginUsername"));
System.out.println(config.getInitParameter("loginPassword"));
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(">>>>>>>>>>MyServlet2 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 doPost()</h1>");
out.println("</body>");
out.println("</html>");
}
}
package com.dxz.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.embedded.ServletRegistrationBean;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.DispatcherServlet;
import com.dxz.demo.servlet.MyServlet;
@ServletComponentScan
@SpringBootApplication
public class DemoApplication {
/**
* 修改DispatcherServlet默认配置
* @param dispatcherServlet
* @return
*/
@Bean
public ServletRegistrationBean dispatcherRegistration(DispatcherServlet dispatcherServlet) {
ServletRegistrationBean registration = new ServletRegistrationBean(dispatcherServlet);
registration.getUrlMappings().clear();
registration.addUrlMappings("*.do");
registration.addUrlMappings("*.json");
return registration;
}
/**
* 使用代码注册Servlet(不需要@ServletComponentScan注解)
* @return
*/
@Bean
public ServletRegistrationBean servletRegistrationBean() {
return new ServletRegistrationBean(new MyServlet(), "/xs/*");// ServletName默认值为首字母小写,即myServlet
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
结果:
注意:
1、Servlet类使用@WebServlet注解;
2、Spring boot的启动类需要增加@ServletComponentScan用于扫描加载Servlet类;
3、其结果是“匹配的优先级是从精确到模糊,复合条件的Servlet并不会都执行
三、修改默认DispatcherServlet的功能
既然系统DispatcherServlet 默认拦截“/”,那么我们是否能做修改呢,答案是肯定的,我们在SpringBootSampleApplication中添加代码:
package com.dxz.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.embedded.ServletRegistrationBean;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.DispatcherServlet;
import com.dxz.demo.servlet.MyServlet;
@ServletComponentScan
@SpringBootApplication
public class DemoApplication {
/**
* 修改DispatcherServlet默认配置
* @param dispatcherServlet
* @return
*/
@Bean
public ServletRegistrationBean dispatcherRegistration(DispatcherServlet dispatcherServlet) {
ServletRegistrationBean registration = new ServletRegistrationBean(dispatcherServlet);
registration.getUrlMappings().clear();
registration.addUrlMappings("*.do");
registration.addUrlMappings("*.json");
return registration;
}
/**
* 使用代码注册Servlet(不需要@ServletComponentScan注解)
* @return
*/
@Bean
public ServletRegistrationBean servletRegistrationBean() {
return new ServletRegistrationBean(new MyServlet(), "/xs/*");// ServletName默认值为首字母小写,即myServlet
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
下面的示例是修改url匹配规则。当然,这里可以对DispatcherServlet做很多修改,并非只是UrlMappings。