Web框架的前生今世 从Servlet到Spring MVC到Spring boot
背景
上世纪90年代,随着Internet和浏览器的飞速发展,基于浏览器的B/S模式随之火爆发展起来。最初,用户使用浏览器向WEB服务器发送的请求都是请求静态的资源,比如html、css等。 但是可以想象:根据用户请求的不同动态的处理并返回资源是理所当然必须的要求。

servlet的定义
- Servlet is a technology which is used to create a web application. servlet是一项用来创建web application的技术。
 - Servlet is an API that provides many interfaces and classes including documentation. servlet是一个提供很多接口和类api及其相关文档。
 - Servlet is an interface that must be implemented for creating any Servlet.servlet是一个接口,创建任何servlet都要实现的接口。
 - Servlet is a class that extends the capabilities of the servers and responds to the incoming requests. It can respond to any requests. servlet是一个实现了服务器各种能力的类,对请求做出响应。它可以对任何请求做出响应。
 - Servlet is a web component that is deployed on the server to create a dynamic web page.servlet是一个web组件,部署到一个web server上(如tomcat,jetty),用来产生一个动态web页面。
 
servlet的历史

web Container
web容器也叫servlet容器,负责servlet的生命周期,映射url请求到相应的servlet。
A web container (also known as a servlet container;[1] and compare "webcontainer"[2]) is the component of a web server that interacts with Java servlets. A web container is responsible for managing the lifecycle of servlets, mapping a URL to a particular servlet and ensuring that the URL requester has the correct access-rights.A web container handles requests to servlets, JavaServer Pages (JSP) files, and other types of files that include server-side code. The Web container creates servlet instances, loads and unloads servlets, creates and manages request and response objects, and performs other servlet-management tasks.A web container implements the web component contract of the Java EE architecture. This architecture specifies a runtime environment for additional web components, including security, concurrency, lifecycle management, transaction, deployment, and other services.
常见的web容器如下:

在web容器中,web应用服务器的结构如下:

1.普通servlet实现页面访问

1.1 实例1:使用web.xml实现一个http服务
实现一个简单的servlet
- package com.howtodoinjava.servlets;
 - 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 MyFirstServlet extends HttpServlet {
 - private static final long serialVersionUID = -1915463532411657451L;
 - @Override
 - protected void doGet(HttpServletRequest request,
 - HttpServletResponse response) throws ServletException, IOException
 - {
 - response.setContentType("text/html;charset=UTF-8");
 - PrintWriter out = response.getWriter();
 - try {
 - // Write some content
 - out.println("<html>");
 - out.println("<head>");
 - out.println("<title>MyFirstServlet</title>");
 - out.println("</head>");
 - out.println("<body>");
 - out.println("<h2>Servlet MyFirstServlet at " + request.getContextPath() + "</h2>");
 - out.println("</body>");
 - out.println("</html>");
 - } finally {
 - out.close();
 - }
 - }
 - @Override
 - protected void doPost(HttpServletRequest request,
 - HttpServletResponse response) throws ServletException, IOException {
 - //Do some other work
 - }
 - @Override
 - public String getServletInfo() {
 - return "MyFirstServlet";
 - }
 - }
 
web.xml配置servlet
/MyFirstServlet MyFirstServlet com.howtodoinjava.servlets.MyFirstServlet MyFirstServlet /MyFirstServlet
1.2 编程方式实现一个http服务请求
不需要xml
- package com.journaldev.first;
 - import java.io.IOException;
 - import java.io.PrintWriter;
 - import java.util.Date;
 - import javax.servlet.ServletException;
 - import javax.servlet.annotation.WebInitParam;
 - import javax.servlet.annotation.WebServlet;
 - import javax.servlet.http.HttpServlet;
 - import javax.servlet.http.HttpServletRequest;
 - import javax.servlet.http.HttpServletResponse;
 - /**
 - * Servlet implementation class FirstServlet
 - */
 - @WebServlet(description = "My First Servlet", urlPatterns = { "/FirstServlet" , "/FirstServlet.do"}, initParams = {@WebInitParam(name="id",value="1"),@WebInitParam(name="name",value="pankaj")})
 - public class FirstServlet extends HttpServlet {
 - private static final long serialVersionUID = 1L;
 - public static final String HTML_START="<html><body>";
 - public static final String HTML_END="</body></html>";
 - /**
 - * @see HttpServlet#HttpServlet()
 - */
 - public FirstServlet() {
 - super();
 - // TODO Auto-generated constructor stub
 - }
 - /**
 - * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
 - */
 - protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 - PrintWriter out = response.getWriter();
 - Date date = new Date();
 - out.println(HTML_START + "<h2>Hi There!</h2><br/><h3>Date="+date +"</h3>"+HTML_END);
 - }
 - /**
 - * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
 - */
 - protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 - // TODO Auto-generated method stub
 - }
 - }
 
2.spring mvc实现页面访问
2.1 web.xml方式

示例:
- <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 - xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
 - http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
 - version="2.5">
 - <display-name>Gradle + Spring MVC Hello World + XML</display-name>
 - <description>Spring MVC web application</description>
 - <!-- For web context -->
 - <servlet>
 - <servlet-name>hello-dispatcher</servlet-name>
 - <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
 - <init-param>
 - <param-name>contextConfigLocation</param-name>
 - <param-value>/WEB-INF/spring-mvc-config.xml</param-value>
 - </init-param>
 - <load-on-startup>1</load-on-startup>
 - </servlet>
 - <servlet-mapping>
 - <servlet-name>hello-dispatcher</servlet-name>
 - <url-pattern>/</url-pattern>
 - </servlet-mapping>
 - <!-- For root context -->
 - <listener>
 - <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 - </listener>
 - <context-param>
 - <param-name>contextConfigLocation</param-name>
 - <param-value>/WEB-INF/spring-core-config.xml</param-value>
 - </context-param>
 - </web-app>
 
2.2 编码方式
- public class MyWebAppInitializer implements WebApplicationInitializer {
 - @Override
 - public void onStartup(ServletContext container) {
 - // Create the 'root' Spring application context
 - AnnotationConfigWebApplicationContext rootContext =
 - new AnnotationConfigWebApplicationContext();
 - rootContext.register(AppConfig.class);
 - // Manage the lifecycle of the root application context
 - container.addListener(new ContextLoaderListener(rootContext));
 - // Create the dispatcher servlet's Spring application context
 - AnnotationConfigWebApplicationContext dispatcherContext =
 - new AnnotationConfigWebApplicationContext();
 - dispatcherContext.register(DispatcherConfig.class);
 - // Register and map the dispatcher servlet
 - ServletRegistration.Dynamic dispatcher =
 - container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
 - dispatcher.setLoadOnStartup(1);
 - dispatcher.addMapping("/");
 - }
 - }
 
内部实现

3.spring boot
继承了spring mvc的框架,实现SpringBootServletInitializer
- package com.mkyong;
 - import org.springframework.boot.SpringApplication;
 - import org.springframework.boot.autoconfigure.SpringBootApplication;
 - import org.springframework.boot.builder.SpringApplicationBuilder;
 - import org.springframework.boot.web.support.SpringBootServletInitializer;
 - @SpringBootApplication
 - public class SpringBootWebApplication extends SpringBootServletInitializer {
 - @Override
 - protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
 - return application.sources(SpringBootWebApplication.class);
 - }
 - public static void main(String[] args) throws Exception {
 - SpringApplication.run(SpringBootWebApplication.class, args);
 - }
 - }
 
然后controller
- package com.mkyong;
 - import java.util.Map;
 - import org.springframework.beans.factory.annotation.Value;
 - import org.springframework.stereotype.Controller;
 - import org.springframework.web.bind.annotation.RequestMapping;
 - @Controller
 - public class WelcomeController {
 - // inject via application.properties
 - @Value("${welcome.message:test}")
 - private String message = "Hello World";
 - @RequestMapping("/")
 - public String welcome(Map<String, Object> model) {
 - model.put("message", this.message);
 - return "welcome";
 - }
 - }
 
总结:
1.servlet的本质没有变化,从web框架的发展来看,web框架只是简化了开发servlet的工作,但还是遵循servlet规范的发展而发展的。
2.servlet的历史发展,从配置方式向编程方式到自动配置方式发展
3.spring mvc框架的分组:root和child(可以有多个dispatcherservlet),多个child可以共享root,child直接不共享
参考文献:
【1】https://en.wikipedia.org/wiki/Web_container
【2】https://baike.baidu.com/item/servlet/477555?fr=aladdin
【3】https://www.javatpoint.com/servlet-tutorial
【4】https://www.journaldev.com/1854/java-web-application-tutorial-for-beginners#deployment-descriptor
【5】https://blog.csdn.net/qq_22075041/article/details/78692780