Java Servlet 简称servlet是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。
使用 Servlet,您可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。
1.servlet;
2.filter;
3.listener;
1.创建工程:servlet-xml
2.创建servlet:
package com.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class ServletDemo */ public class ServletDemo extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public ServletDemo() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setCharacterEncoding("GBK"); response.getWriter().write("菜鸟教程:https://www.runoob.com/servlet/servlet-intro.html"); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
3.web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:web="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <servlet> <servlet-name>ServletDemo</servlet-name> <servlet-class>com.servlet.ServletDemo</servlet-class> </servlet> <servlet-mapping> <servlet-name>ServletDemo</servlet-name> <url-pattern>/ServletDemo</url-pattern> </servlet-mapping> </web-app>
4.启动tomcat,访问 http://localhost :8080/servlet-xml/ServletDemo
不用web.xml配置,用注解也可以使用servlet,查看servlet官方文档:
大概意思是说框架提供了ServletContainerInitializer的实现,必须是绑定在META/INF/services目录下,文件为:javax.servlet.ServletContainerInitializer,文件里包含ServletContainerInitializer的实现类的目的地,类路径。
1.新建工程servlet-anno,也是 Dynamic web project。
2.新建javax.servlet.ServletContainerInitializer文件。
3.新建servlet:
package com.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class OrderServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub resp.getWriter().write("testServlet...order"); } }
4.监听器的实现:
package com.servlet; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; /** * 监听应用的启动和停止 */ public class OrderListener implements ServletContextListener { //监听ServletContext销毁 @Override public void contextDestroyed(ServletContextEvent arg0) { // TODO Auto-generated method stub System.out.println("OrderListener...contextDestroyed..."); } //监听ServletContext启动初始化 @Override public void contextInitialized(ServletContextEvent arg0) { // TODO Auto-generated method stub ServletContext servletContext = arg0.getServletContext(); System.out.println("OrderListener...contextInitialized..."); } }
5.过滤器:
package com.servlet; 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; public class OrderFilter implements Filter { @Override public void destroy() { // TODO Auto-generated method stub } @Override public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { // 过滤请求 System.out.println("UserFilter...doFilter..."); //放行 arg2.doFilter(arg0, arg1); } @Override public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub } }
6.实现ServletContainerInitializer,即servlet容器初始化,主要是做三大组件的注册。
package com.servlet; import java.util.EnumSet; import java.util.Set; import javax.servlet.DispatcherType; import javax.servlet.ServletContainerInitializer; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.annotation.HandlesTypes; import com.service.TestService; //容器启动的时候会将@HandlesTypes指定的这个类型下面的子类(实现类,子接口等)传递过来; //传入感兴趣的类型; @HandlesTypes(value={TestService.class}) public class TestServletContainerInitializer implements ServletContainerInitializer{ @Override public void onStartup(Set<Class<?>> arg0, ServletContext arg1) throws ServletException { System.out.println("感兴趣的类型:"); for (Class<?> claz : arg0) { System.out.println(claz);//当传进来后,可以根据自己需要利用反射来创建对象等操作 } //注册servlet组件 javax.servlet.ServletRegistration.Dynamic servlet = arg1.addServlet("orderServlet", new OrderServlet()); //配置servlet的映射信息(路径请求) servlet.addMapping("/orderTest"); //注册监听器Listener arg1.addListener(OrderListener.class); //注册Filter javax.servlet.FilterRegistration.Dynamic filter = arg1.addFilter("orderFilter", OrderFilter.class); //添加Filter的映射信息,可以指定专门来拦截哪个servlet filter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*"); } }
tomcat启动加载应用的时候,会运行onStartup方法;
Set<Class<?>> arg0:感兴趣的类型的所有子类型(对实现了
TestService接口相关的);
ServletContext arg1:代表当前Web应用的ServletContext;一个Web应用一个ServletContext;
1)、使用ServletContext注册Web组件(Servlet、Filter、Listener)
2)、使用编码的方式,在项目启动的时候给ServletContext里面添加组件;
启动tomcat:
如图启动的时候打印出了3个感兴趣的类即实现了TestService接口的;另外打印出了监听器的日志,即ServletContext启动创建的时候。
访问 http://localhost :8080/servlet-anno/orderTest即可进入对应的servlet:即进入了过滤器
除了在ServletContainerInitializer注册servlet还可以用注解@WebServle来加入组件:新增如下代码并重启tomcat
@WebServlet("/anno") public class TestServlet extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getWriter().write("servlet-anno....success"); } }
访问 http://localhost :8080/servlet-anno/anno也是OK的
spring-mvc整合也是基于servlet的,基于注解版的servlet。
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.0.6.RELEASE</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>3.0-alpha-1</version> <scope>provided</scope> </dependency>
①可找到javax.servlet.ServletContainerInitializer文件为:org.springframework.web.SpringServletContainerInitializer.
②即SpringServletContainerInitializer为servlet容器的初始化类,容器启动调用onStartup方法:查看代码发现主要是做了把感兴趣的类做一下判断然后调用各自的onStartup方法。
这个感兴趣的类是重点:@HandlesTypes(WebApplicationInitializer.class)
③WebApplicationInitializer在spring-web中有三个实现类:
a:AbstractContextLoaderInitializer--主要是注册监听器.
b:AbstractDispatcherServletInitializer--主要是DispatcherServlet容器初始化,如图注册servlet,filter步骤都和注解版servlet步骤类似。
c:AbstractAnnotationConfigDispatcherServletInitializer--提供了注解方式配置的dispatcherServlet初始化器,即如下2个方法:
1.getRootConfigClasses()根容器(存放service业务层,repositories数据库dao层及事务控制相关处理);
2.getServletConfigClasses() 即servlet容器(存放controller,视图解析,映射相关)。
如官网图 https://docs.spring.io/spring... :
新建一个初始化器:
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; import com.enjoy.config.TestAppConfig; import com.enjoy.config.TestRootConfig; //web容器启动的时候创建对象;调用方法来初始化容器以前前端控制器 public class TestWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { //获取根容器的配置类;(Spring的配置文件) 父容器; @Override protected Class<?>[] getRootConfigClasses() { //指定配置类(配置文件)位置 return new Class<?>[]{TestRootConfig.class} ; } //获取web容器的配置类(SpringMVC配置文件) 子容器(servlet容器); @Override protected Class<?>[] getServletConfigClasses() { return new Class<?>[]{TestAppConfig.class} ; } //获取DispatcherServlet的映射信息 // /:拦截所有请求(包括静态资源(xx.js,xx.png)),但是不包括*.jsp; // /*:拦截所有请求;连*.jsp页面都拦截;jsp页面是tomcat的jsp引擎解析的; @Override protected String[] getServletMappings() { // TODO Auto-generated method stub return new String[]{"/"}; } }
再来看看父容器TestRootConfig和servlet容器TestAppConfig配置类:
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.FilterType; import org.springframework.stereotype.Controller; //Spring的容器不扫描controller;父容器 @ComponentScan(value="com.enjoy",excludeFilters={ @Filter(type=FilterType.ANNOTATION,classes={Controller.class}) }) public class TestRootConfig { }
import java.util.List; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.FilterType; import org.springframework.format.FormatterRegistry; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.stereotype.Controller; import org.springframework.validation.MessageCodesResolver; import org.springframework.validation.Validator; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer; import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.ViewResolverRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; //SpringMVC只扫描Controller;子容器 //useDefaultFilters=false 禁用默认的过滤规则; @ComponentScan(value="com.enjoy",includeFilters={ @Filter(type=FilterType.ANNOTATION,classes={Controller.class}) },useDefaultFilters=false) public class TestAppConfig { }
启动tomcat,2个配置文件分别会扫描对应的类加载到spring的对应的根容器和servlet容器中,注解整合spring-mvc就完成啦!!!
xml配置的时候如下配置拦截器,视图解析等。
若使用配置注解定制我们的springmvc,可看官网描述,加入@EnableWebMvc,来定制配置功能。
直接在servlet容器对应的配置里面加入@EnableWebMvc并实现WebMvcConfigurer接口即可对对应需要配置的用代码做配置,或者继承WebMvcConfigurer的具体实现类。