[java][Servlet]Servlet 简介-Servlet 到 Spring MVC 的简化之路-Servlet/Tomcat/ Spring 之间的关系

[java][Servlet]Servlet 简介-Servlet 到 Spring MVC 的简化之路-Servlet/Tomcat/ Spring 之间的关系

温习一下这个传统的方式,jsp+JavaBeans,这种混合模式很虐心呀,jsp在里面夹杂着,现在大家都直接搞前后端分离了。

注:Spring MVC这种方式,也早就不用了。

既然要搞一下商业软件的破解什么的,还是要温习一下古老技术,不然破解起来有点吃力。

Servlet 教程

Servlet 为创建基于 web 的应用程序提供了基于组件、独立于平台的方法,可以不受 CGI 程序的性能限制。Servlet 有权限访问所有的 Java API,包括访问企业级数据库的 JDBC API。

本教程将讲解如何使用 Java Servlet 来开发基于 web 的应用程序。

谁适合阅读本教程?

本教程是专为 Java 程序员设计的。在阅读本教程之前,需要先了解 Java Servlet 框架和它的 API。学习完本教程后,您会发现自己已经达到使用 Java Servlet 的中等水平,后续您可以自行通过更深入的学习和实践完成进阶。

阅读本教程前,您需要了解的知识:

在您开始阅读本教程之前,最好对 Java 编程语言有一个很好的理解。如果您对 web 应用程序和互联网如何工作的有基本的认识,将有助于您理解本教程。

Servlet 相关教程

  • Java 教程
  • Jsp 教程

Servlet 简介

Servlet 是什么?

Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。

使用 Servlet,您可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。

Java Servlet 通常情况下与使用 CGI(Common Gateway Interface,公共网关接口)实现的程序可以达到异曲同工的效果。但是相比于 CGI,Servlet 有以下几点优势:

  • 性能明显更好。
  • Servlet 在 Web 服务器的地址空间内执行。这样它就没有必要再创建一个单独的进程来处理每个客户端请求。
  • Servlet 是独立于平台的,因为它们是用 Java 编写的。
  • 服务器上的 Java 安全管理器执行了一系列限制,以保护服务器计算机上的资源。因此,Servlet 是可信的。
  • Java 类库的全部功能对 Servlet 来说都是可用的。它可以通过 sockets 和 RMI 机制与 applets、数据库或其他软件进行交互。

Servlet 架构

下图显示了 Servlet 在 Web 应用程序中的位置。

Servlet 架构

Servlet 任务

Servlet 执行以下主要任务:

  • 读取客户端(浏览器)发送的显式的数据。这包括网页上的 HTML 表单,或者也可以是来自 applet 或自定义的 HTTP 客户端程序的表单。
  • 读取客户端(浏览器)发送的隐式的 HTTP 请求数据。这包括 cookies、媒体类型和浏览器能理解的压缩格式等等。
  • 处理数据并生成结果。这个过程可能需要访问数据库,执行 RMI 或 CORBA 调用,调用 Web 服务,或者直接计算得出对应的响应。
  • 发送显式的数据(即文档)到客户端(浏览器)。该文档的格式可以是多种多样的,包括文本文件(HTML 或 XML)、二进制文件(GIF 图像)、Excel 等。
  • 发送隐式的 HTTP 响应到客户端(浏览器)。这包括告诉浏览器或其他客户端被返回的文档类型(例如 HTML),设置 cookies 和缓存参数,以及其他类似的任务。

Servlet 包

Java Servlet 是运行在带有支持 Java Servlet 规范的解释器的 web 服务器上的 Java 类。

Servlet 可以使用 javax.servlet 和 javax.servlet.http 包创建,它是 Java 企业版的标准组成部分,Java 企业版是支持大型开发项目的 Java 类库的扩展版本。

这些类实现 Java Servlet 和 JSP 规范。在写本教程的时候,二者相应的版本分别是 Java Servlet 2.5 和 JSP 2.1。

Java Servlet 就像任何其他的 Java 类一样已经被创建和编译。在您安装 Servlet 包并把它们添加到您的计算机上的 Classpath 类路径中之后,您就可以通过 JDK 的 Java 编译器或任何其他编译器来编译 Servlet。

下一步呢?

接下来,本教程会带你一步一步地设置您的 Servlet 环境,以便开始后续的 Servlet 使用。因此,请系紧您的安全带,随我们一起开始 Servlet 的学习之旅吧!相信您会很喜欢这个教程的。

Servlet 到 Spring MVC 的简化之路

背景

Servlet和JSP是开发Java Web应用程序的两种基本技术,Spring MVC是Spring框架中用于开发Web应用的一个模块。相信大家也和我一样,是从编写Servelt和JSP开始,然后一步步向Spring MVC靠拢。那么Spring MVC到底简化了Servlet什么地方,使Spring MVC成为Web应用开发的首选框架呢,本文将会就这个方面进行探讨。

Servlet简介

什么是Servlet

Servlet是一种基于Java语言,用于创建Web应用程序。在Servlet之前,CGI(通用网关接口)脚本语言作为服务端编程语言很受欢迎,但是这门技术有很多的缺点:

  • CGI(通用网关接口) CGI即使可以让服务器能够调用外部程序,并将HTTP请求信息传递给外部程序处理,对于每一个请求,会启动一个新的进程。

     

  • CGI技术的缺点

  1. 客户端数量增加时,响应时间更多
  2. 每一个其请求,需要启动一个新的进程,消耗大量的系统资源
  3. 使用平台依赖语言,如:C、C++、Perl
  • Servlet

     

  • Servlet的优点

  1. 更好的性能:每个请求创建的是线程,而不是进程
  2. 可移植性:使用Java跨平台语言
  3. 更强大:Servlet有JVM管理,不需要担心内存泄露、溢出等

Servlet的演化

  • Servlet的基本目录

    在tomcat/webapps目录下创建上述目录结构,所有HTML,静态文件直接保存在应用程序目录下,所有的Servlet类保存在web-inf/classe目录或子目录下,web.xml(部署描述符)文件保存在web-inf目录下。

     

  • Servlet接口 在最基本的Servlet类中,需要实现Servlet接口定义的init()、servic()、destroy()、getServletConfig()和geServletInfo()方法,其中业务逻辑在service中编写,在service方法中最常用的是通过PrintWriter对象进行内容的输出。

  • 演进1:GenericServlet抽象类 实现Servlet接口的时候必须将所有的方法实现,即使方法中没有任何代码。在GenericServlet抽象类的帮助下,只需要重写service方法即可。

  • 演进2:HttpServlet抽象类 HttpServlet覆盖了GenericServlet类,将ServletRequest和ServletResponse对象分别封装为HttpServletRequest和HttpServletResponse对象。HttpServlet同时实现了service方法,在请求进来时,Web容器首先调用HttpServlet的service方法,并根据请求的类型调用doGet或doPost方法,搜易我们只需要覆盖doGet()和goPost()方法即可。

演进3:JSP的加入

写过Servlet的朋友应该知道,Servlet的最大缺点就是在Servlet类中编写大量繁杂的HTML代码,使得Java代码与HTML代码糅杂在一起,所以JSP应运而生。
JSP本质也是Servelt,然而其不需要编译,JSP页面是一个以.jsp扩展名的文本文件。简单的JSP页面在第一次请求后被翻译为(JSP名)_jsp的servlet,翻译之后的Servelt可以看到:_jspInit(),_jspDestory(),_jspService()这样的方法其实都是和Servlet相对应的。

演进4:Spring横空出世

Spring提供了强大的控制反转(IOC)和依赖注入(DI)功能,达到项目组件的解耦。

演进5:Spring Web模块 - Spring MVC

学过Servlet的朋友应该知道,当要使用Servlet完成的复杂的功能时,需要编写多个Servlet类,并且在web.xml进行注册,这对于完成复杂的Web应用,代码编写会变得很复杂,开发成本也会很高。所以Spring提供了强大的Web开发框架Spring MVC。Spring MVC是Spring产品的一部分,享有Spring松耦合等所有优点。
Spring MVC是一个模型-视图-控制器的Web框架,建立在前端控制器servlet(DispatcherServlet),它负责发送每个请求到合适的处理程序,使用视图来返回响应结果。
Spring MVC的架构:

 

Spring web MVC框架提供了MVC(模型 - 视图 - 控制器)架构和用于开发灵活和松散耦合的Web应用程序的组件。MVC模式导致应用程序的不同方面(输入逻辑,业务逻辑和UI逻辑)分离,同时提供这些元素之间的松散耦合

  • 模型(Model):封装了应用程序的数据,通常由POJO类组成
  • 视图(View):负责渲染模型数据,一般来说它生成客户端浏览器可以解释HTML输出
  • 控制器(Controller):负责处理用户请求并构建适当的模型,并将其传递给视图进行渲染

DispatcherServlet组件类 Spring MVC框架是围绕DispatcherServlet设计的,它处理所有的请求和响应。Spring MVC DispatcherServlet的工作流程:

 

DispatcherServlet处理HTTP请求的工作流程

  1. 接受HTTP请求后,DispatcherServlet
  2. 会查询HandlerMapping以调用相应的Controller(根据请求的url)
  3. Controller接受请求并根据请求的类型Get/Post调用相应的服务方法,服务方法进行相应的业务处理,并设置模型数据,最后将视图名称返回给DispatcherServlet
  4. DispatcherServlet根据返回的视图名称从ViewResolver获取对应的视图
  5. DispatcherServlet将模型数据传递到最终的视图,并将视图返回给浏览器。

总结

至此Servlet到Spring MVC的演化之路落下帷幕,只能感慨,技术的变更和迭代速度远远超乎我们的意料,我们只有不断地学习,才能跟上时代的潮流。

Servlet/Tomcat/ Spring 之间的关系

0.基础知识

在idea中打开servlet的源码:

 

 

可以看见servlet就是一个接口;接口就是规定了一些规范,使得一些具有某些共性的类都能实现这个接口,从而都遵循某些规范。

有的人往往以为就是servlet直接处理客户端的http请求,其实并不是这样,servlet并不会去监听8080端口;直接与客户端打交道是“容器”,比如常用的tomcat。

客户端的请求直接打到tomcat,它监听端口,请求过来后,根据url等信息,确定要将请求交给哪个servlet去处理,然后调用那个servlet的service方法,service方法返回一个response对象,tomcat再把这个response返回给客户端。

 

 

1. Servlet的生命周期

 

从创建到毁灭:

 

  1. 调用 init() 方法初始化
  2. 调用 service() 方法来处理客户端的请求
  3. 调用 destroy() 方法释放资源,标记自身为可回收
  4. 被垃圾回收器回收

 

由上面可以看见,servlet的init方法和destroy方法,一般容器调用这两个方法之间的过程,就叫做servlet的生命周期。

调用的整个过程就如上图所示。

当请求来容器第一次调用某个servlet时,需要先初始化init(),

但当某个请求再次打到给servlet时,容器会起多个线程同时访问一个servlet的service()方法。

 

 

由此可以看出,多个客户访问同一service()方法,会涉及线程安全的问题。

 

如果service()方法没有访问Servlet的成员变量也没有访问全局的资源比如静态变量、文件、数据库连接等,而是只使用了当前线程自己的资源,比如非指向全局资源的临时变量、request和response对象等。该方法本身就是线程安全的,不必进行任何的同步控制。

如果service()方法访问了Servlet的成员变量,但是对该变量的操作是只读操作,该方法本身就是线程安全的,不必进行任何的同步控制。

如果service()方法访问了Servlet的成员变量,并且对该变量的操作既有读又有写,通常需要加上同步控制语句。

如果service()方法访问了全局的静态变量,如果同一时刻系统中也可能有其它线程访问该静态变量,如果既有读也有写的操作,通常需要加上同步控制语句。

如果service()方法访问了全局的资源,比如文件、数据库连接等,通常需要加上同步控制语句。

 

 

面试问题:Servlet如何同时处理多个请求访问? 

单实例多线程: 主要是请求来时,会由线程调度者从线程池李取出来一个线程,来作为响应线程。这个线程可能是已经实例化的,也可能是新创建的。


Servlet容器默认是采用单实例多线程的方式处理多个请求的: 
1.当web服务器启动的时候(或客户端发送请求到服务器时),Servlet就被加载并实例化(只存在一个Servlet实例); 
2.容器初始化化Servlet主要就是读取配置文件(例如tomcat,可以通过servlet.xml的设置线程池中线程数目,初始化线程池通过web.xml,初始化每个参数值等等。 
3.当请求到达时,Servlet容器通过调度线程(Dispatchaer Thread) 调度它管理下线程池中等待执行的线程(Worker Thread)给请求者; 
4.线程执行Servlet的service方法; 
5.请求结束,放回线程池,等待被调用; 
(注意:避免使用实例变量(成员变量),因为如果存在成员变量,可能发生多线程同时访问该资源时,都来操作它,照成数据的不一致,因此产生线程安全问题)

 

从上面可以看出: 
第一:Servlet单实例,减少了产生servlet的开销; 
第二:通过线程池来响应多个请求,提高了请求的响应时间; 
第三:Servlet容器并不关心到达的Servlet请求访问的是否是同一个Servlet还是另一个Servlet,直接分配给它一个新的线程;如果是同一个Servlet的多个请求,那么Servlet的service方法将在多线程中并发的执行; 
第四:每一个请求由ServletRequest对象来接受请求,由ServletResponse对象来响应该请求;

 

 

 

 

 2. Spring 

 

 任何Spring Web的entry point,都是servlet。

 

大名顶顶的spring框架已经风靡多时,一个事物的出现和流行都是会有原因的,那么为什么spring 框架会出现呢?原因就是为了简化java开发

spring的核心就是通过依赖注入、面向切面编程aop、和模版技术,解耦业务与系统服务,消除重复代码。借助aop,可以将遍布应用的关注点(如事物和安全)从它们的应用对象中解耦出来。

 

 

 Spring 中的Bean

 1) POJO和JavaBean的区别 : 

"Plain Ordinary Java Object",简单普通的java对象。主要用来指代那些没有遵循特定的java对象模型,约定或者框架的对象。

POJO的内在含义是指那些:
有一些private的参数作为对象的属性,然后针对每一个参数定义get和set方法访问的接口。
没有从任何类继承、也没有实现任何接口,更没有被其它框架侵入的java对象。

JavaBean 是一种JAVA语言写成的可重用组件。JavaBean符合一定规范编写的Java类,不是一种技术,而是一种规范。大家针对这种规范,总结了很多开发技巧、工具函数。符合这种规范的类,可以被其它的程序员或者框架使用。它的方法命名,构造及行为必须符合特定的约定:

  1. 所有属性为private。

  2. 这个类必须有一个公共的缺省构造函数。即是提供无参数的构造器。

  3. 这个类的属性使用getter和setter来访问,其他方法遵从标准命名规范。

  4. 这个类应是可序列化的。实现serializable接口。

因为这些要求主要是靠约定而不是靠实现接口,所以许多开发者把JavaBean看作遵从特定命名约定的POJO。

 

spring中,应用对西那个生存于spring容器中,spring 容器创建对象,装配它们,管理它们的整个生命周期。spring容器通过依赖注入,管理构成应用的组件,它会创建相互协作的组件之间的关联。

2) Bean的生命周期

 

 

 Spring MVC

 

 

 

 

 Spring MVC的运行流程:

 

 

 

 

参考:

https://www.runoob.com/servlet/servlet-intro.html

https://juejin.im/post/6844903570681135117

https://www.cnblogs.com/shawshawwan/p/9002126.html

posted @ 2020-08-04 17:18  landv  阅读(403)  评论(0编辑  收藏  举报