一、servlet,servlet容器
Servlet 是一种基于 Java 技术的 Web 组件,用于生成动态内容,由容器管理。类似于其他 Java 技术组件,Servlet 是平台无关的 Java 类组成,并且由 Java Web 服务器加载执行。在以前的servlet规范中,必须放在相应的目录中才可以执行,比如web-inf,而SpringBoot就非常简单,不需要复杂的步骤。
Servlet容器,有时也称为Servlet引擎,作为Web服务器或应用服务器的一部分,通过请求和响应对话,提供Web客户端与Servlet交互的能力。容器管理Servlet实例以及他们的生命周期。
Servlet3.0以后,也就是tomcat8.0以后采用注解驱动。用注解或API的方式代替了XML,不需要XML就可以启动容器了。也就是说用jar包的方式就可以启动,不 需要用war包去启动了。SpringBoot用了嵌入式引擎,嵌入式引擎必须由嵌入式容器启动,tomcat之所以能做到嵌入式容器,是因为servlet做了改革。SpringBoot除了自动装配以外,还有一个最大的亮点是异步IO,异步上下文。Servlet3.1和websocket有紧密的关联。
二、servlet组件
1997年六月,Servlet 1.0 版本发行,当时还不属于J2EE规范,最新版本 Servlet 4.0 处于研发状态。下面说的都是servlet3.1规范,支持Tomcat8。Servlet 3.0 前时代,几乎都是注解驱动或API编程的方式。Annotation用于申明,真正的注册在于调用它 的API,通过API的方式动态的进行注册,之前只能通过XML配置,比较固态化。
常见服务组件
javax.servlet.Servlet
public interface Servlet {
void init(ServletConfig var1) throws ServletException;
ServletConfig getServletConfig();
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
String getServletInfo();
void destroy();
}
javax.servlet.Filter(since Servlet 2.3)
Filter是在servlet之前执行的。
public interface Filter {
void init(FilterConfig var1) throws ServletException;
void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
void destroy();
}
上下文组件
javax.servlet.ServletContext
一个servlet容器是允许多个应用上下文的,SpringBoot里面至少有一个,实际上可以有两个应用上下文,一个是服务端,一个是管理端,一个应用上下文就是一个应用,一个Web容器里面可以支持多个应用的部署。
javax.servlet.http.HttpSession,
HTTPSession可以通过cookie或url重写的方式进行Session的跟踪,用于用户和服务端的识别,http是无状态的协议,session可以用来管理用户和服务端的会话。
javax.servlet.http.HttpServletRequest,请求上下文
javax.servlet.http.HttpServletResponse
javax.servlet.http.Cookie(客户端),存储信息量比session小
Cookie用于跟踪用户的会话,服务端发送一个cookie,相对于session来说,生命周期比较短,保存的信息有限,每个浏览器保存的大小和信息量不一样的。
配置
javax.servlet.ServletConfig
javax.servlet.FilterConfig(since Servlet 2.3 )
输入输出
javax.servlet.ServletInputStream
javax.servlet.ServletOutputStream
对于应用程序而言,servlet是web服务器的一部分,而web服务器是基于socket的,所以servlet和web服务器是类似的,也是二进制的输入输出,编码问题要考虑到是字符流,不是字节流。
异常
javax.servlet.ServletException
Servlet异常有两种,servletException,IOException.
事件(since Servlet 2.3 )
生命周期类型
javax.servlet.ServletContextEvent
javax.servlet.http.HttpSessionEvent
java.servlet.ServletRequestEvent
在servlet里面,所有的事件类都会实现EventListener这个接口,这个接口只是一个标记性接口,在java.util包里面,里面是空的,没有任何方法。
属性上下文类型
javax.servlet.ServletContextAttributeEvent
javax.servlet.http.HttpSessionBindingEvent
javax.servlet.ServletRequestAttributeEvent
监听器(since Servlet 2.3)
生命周期类型
javax.servlet.ServletContextListener
javax.servlet.http.HttpSessionListener
javax.servlet.http.HttpSessionActivationListener
javax.servlet.ServletRequestListener
属性上下文类型
javax.servlet.ServletContextAttributeListener
javax.servlet.http.HttpSessionAttributeListener
javax.servlet.http.HttpSessionBindingListener
javax.servlet.ServletRequestAttributeListener
组件申明注解
@javax.servlet.annotation.WebServlet
@javax.servlet.annotation.WebFilter
@javax.servlet.annotation.WebListener
@javax.servlet.annotation.ServletSecurity,不用太关心,实际中会用很多其他的方式来代替他,其他的方式会比servlet更灵活一些。
@javax.servlet.annotation.HttpMethodConstraint
@javax.servlet.annotation.HttpConstraint
SpringBoot是通过main方法来启动的,有个annotation web的applicationContext来进行初始化的,以前是有个启动类,这个类会创建新的上下文,springMVC 的启动是通过dispatcherServlet来构建的,而SpringBoot是把dispatcherServlet作为一个组件(@bean)来初始化了,就不会出现脱钩的情况。
假如代码是在第三方包里的,实现servlet时,它是2.4版本的,无法用注解(3.0)实现,就要用 new ServletRegistrationBean().addURLMappings(“/aaa/aaa”)这种方式来实现。
配置申明
@javax.servlet.annotation.WebInitParam
上下文,servlet 3.1另外一个最大的亮点就是异步上下文
javax.servlet.AsyncContext
事件
javax.servlet.AsyncEvent
监听器
javax.servlet.AsyncListener
Servlet 组件注册
javax.servlet.ServletContext#addServlet()
javax.servlet.ServletRegistration
Filter 组件注册
javax.servlet.ServletContext#addFilter()
javax.servlet.FilterRegistration
监听器注册
javax.servlet.ServletContext#addListener()
javax.servlet.AsyncListener
自动装配
初始器
javax.servlet.ServletContainerInitializer
类型过滤
@javax.servlet.annotation.HandlesTypes
Servlet 生命周期
初始化
当容器启动或者第一次执行时,Servlet#init(ServletConfig)方法被执行,初始化当前Servlet 。
处理请求
当HTTP 请求到达容器时,Servlet#service(ServletRequest,ServletResponse) 方法被执行,来处理请求。
销毁
当容器关闭时,容器将会调用Servlet#destroy 方法被执行,销毁当前Servlet。
Filter 生命周期
初始化
当容器启动时,Filter#init(FilterConfig)方法被执行,初始化当前Filter。
处理请求
当HTTP 请求到达容器时,Filter#doFilter(ServletRequest,ServletResponse,FilterChain) 方法被执行,来拦截请求,在Servlet#service(ServletRequest,ServletResponse) 方法调用前执行。
销毁
当容器关闭时,容器将会调用Filter#destroy 方法被执行,销毁当前Filter。
Servlet在SpringBoot中的使用
Servlet 组件扫描
注解方式注册
Servlet,Filter,监听器
Spring Boot API方式注册:1.实现一个接口;2.打上一个标记@。。。。
@org.springframework.boot.web.servlet.ServletComponentScan,指定包路径扫描
String[] value() default {}
String[] basePackages() default {}
指定类扫描
Class<?>[] basePackageClasses() default {}
Servlet 组件
扩展 javax.servlet.Servlet
javax.servlet.http.HttpServlet
org.springframework.web.servlet.FrameworkServlet
标记 @javax.servlet.annotation.WebServlet
Filter 组件
实现 javax.servlet.Filter
org.springframework.web.filter.OncePerRequestFilter
标记 @javax.servlet.annotation.WebFilter
监听器组件
实现Listener接口
javax.servlet.ServletContextListener
javax.servlet.http.HttpSessionListener
javax.servlet.http.HttpSessionActivationListener
javax.servlet.ServletRequestListener
javax.servlet.ServletContextAttributeListener
javax.servlet.http.HttpSessionAttributeListener
javax.servlet.http.HttpSessionBindingListener
javax.servlet.ServletRequestAttributeListener
标记 @javax.servlet.annotation.WebListener
前面的都是依赖于servlet组件,现在才是依赖于springboot自己的组件
Servlet 组件
扩展 javax.servlet.Servlet
javax.servlet.http.HttpServlet
org.springframework.web.servlet.FrameworkServlet
组装 Servlet
Spring Boot 1.4.0 开始支持
org.springframework.boot.web.servlet.ServletRegistrationBean
Spring Boot 1.4.0 之前
org.springframework.boot.context.embedded.ServletRegistrationBean
暴露 Spring Bean
@Bean
Filter 组件
实现 javax.servlet.Filter
org.springframework.web.filter.OncePerRequestFilter
组装 Filter
Spring Boot 1.4.0 开始
org.springframework.boot.web.servlet.FilterRegistrationBean
Spring Boot 1.4.0 之前
org.springframework.boot.context.embedded.FilterRegistrationBean
暴露 Spring Bean
@Bean
监听器组件
实现 Listener
组装 Listener
Spring Boot 1.4.0 开始
org.springframework.boot.web.servlet.ServletListenerRegistrationBean
Spring Boot 1.4.0 之前
org.springframework.boot.context.embedded.ServletListenerRegistrationBean
激活
激活 传统Servlet Web部署
Spring Boot 1.4.0 开始
org.springframework.boot.web.support.SpringBootServletInitializer
组装 org.springframework.boot.builder.SpringApplicationBuilder
配置JSP视图
org.springframework.boot.autoconfigure.web.WebMvcProperties
spring.mvc.view.prefix
spring.mvc.view.suffix
Tomcat 8 性能比6,7都要高一点,所以嵌入式容器性能要稍微高一点,SpringBoot性能大概比spring高1.1倍左右(阿里做压测时的结论)
从SpringBoot1.4开始就没有log4j1了,就只有log4j2,logback了,不建议升级到1.5版本,可以升级到2.0版本。
SpringMVC的上下文是通过dispatcherServlet去构建的,SpringBoot是把dispatcherServlet作为一个组件进行初始化了,打上了@Bean的标记。
前后端分离项目,如果页面变化比较少,用模板引擎会更好。
写代码的时候注意对重载方法的思考,增加灵活性,减少代码的漏洞。
默认的SpringBoot对JSP是不支持的,必须激活传统的Web Servlet部署。因为unertow这种非servlet容器是不支持jsp的,所以jsp在SpringBoot上是受限制的,SpringBoot更希望你用相应的模板引擎,而不是jsp。
Web-inf目录在java里面是读不到的。
War包是maven的标准方式。
SpringBoot版本 Spring版本
1.5 4.3
SpringBoot 1.3-1.5坑很多,建议直接升级到2.0,。1.5版本很多东西删掉了,1.4开始就没有log4j-1了,只有log4j-2,logback了。VelocityEngineFactory这个接口在Spring中已经被移除了,Boot 1.5也被移除了。不建议升级到1.5版本。
一般做微服务的时候,依赖和jar包就不能太多,Boot是用自动装配的方式做的,需要关注的东西较多,维护起来的话比以前更麻烦,必须要搜好多的代码,要对spring有很多了解,对底层的原理,机制要很熟悉,大项目的组件没必要用Boot。
前后端分离,做的比较纯的就不需要模板引擎了,只需要json,xml就可以了,用ajax请求。模板引擎的好处是,如果用json或js这种方式的话,数据更新必然会很小,如果数据更新很多,就会在不同的地方增加很多代码,可读性差,不好维护,有个模板直接引入就会方便很多。看页面交互的情况。