Servlet简介Servlet是Sun公司提出的一套规范,规范了Java如何开发动态网站。它提供了对服务器端Java开发的支持,也是JavaWeb技术的基础。

一个Servlet就是一个Java类,但它不是一个Applet(Java应用程序),因为Servlet没有main方法,他不能独立执行,必须要由Servlet容器去调用、管理,控制Servlet的创建、执行、销毁等生命周期阶段。

Servlet的工作方式:服务端启动,客户端发出请求,通过计算机网络将请求发送给服务端,服务端创建Servlet,并根据客户端请求调用相应方法(doPost、doGet……)处理请求后返回响应(response对象)给客户端。
        
Web容器:也叫作Web服务器,Tomcat就是Web容器,我们刚刚提到的Servlet容器是Web容器的一部分。客户端发出的HTTP请求会首先经过Web容器,Web容器会将HTTP请求解析成一个request对象交给服务端Servlet,服务端处理请求后返回的response对象也需要被Web容器解析成HTTP报文才能返回给客户端。浏览器解析HTTP报文,并将响应结果展示给用户。

这里提到了浏览器:现在主流的网络程序开发架构已经由C/S转向B/S,其中B就是指Brower浏览器。浏览器是Html、CSS、JavaScript等负责页面显示的脚本语言的解释器;它支持url并可以通过url发出HTTP请求、解析HTTP请求;浏览器还支持各种图片、视频、音频的显示;现在的浏览器还支持更多的功能,如Cookie、缓存、多种网络协议……总之,浏览器是当今web应用开发中绝对不可或缺的一部分。

JSP:JSP的出现是为解决动态响应视图问题,如CGI程序,当需要动态的返回响应页面时,只能通过response.getWriter().write()方法一行一行的输出HTML脚本返回给客户端,十分繁琐,而且Servlet作为控制层与视图层耦合,不符合MVC架构思想;而有了JSP,我们可以直接响应一个.jsp视图或映射到一个.jsp视图的逻辑视图(Struts2中会用到),在JSP中可以写Html、CSS、JS代码,可以嵌入Java代码、JSP支持的JSTL标签,Struts2等框架支持的OGNL标签等,以实现根据响应数据动态显示视图的功能,十分方便,而且Servlet只负责业务逻辑的控制,JSP负责视图层工作(与用户交互,向服务器发出请求,接收服务器响应,由响应数据不同动态显示视图),若再使用JavaBean的封装数据模型就实现了一个简单的MVC架构。

JavaBean:如果我们为了使用服务端的响应数据而在JSP中嵌入了大量的Java代码,我们的代码看起来会非常混乱难以维护。我们期望实现页面静态化(只包含静态内容,如Html,CSS,JS等),所以我们将为完成某一业务逻辑所需要的参数封装成JavaBean,在JSP中使用JavaBean组件标签替换Java代码,以保证页面的静态组成。JavaBean其实就是一个Java类,具有私有属性,一般包括有参和无参的构造方法与各属性的get、set方法。

我刚刚一直说的MVC架构:是一种Web开发模式,将Web应用分为三层
M——Model模型层,一般是指我们开发中的数据库表与entity(pojo)、dao、persistence包下的内容,主要负责数据模型的封装与数据库的相关操作;
V——View视图层,一般是指页面如JSP、Html等,主要负责与用户交互,向服务器发出请求、接收响应,由响应数据不同动态显示视图。
C——Controller控制层,一般是指项目中servlet、action、controller包下的内容,主要负责接收客户端请求,调用模型层相关方法处理请求,然后返回响应给客户端。

Service\ServiceImpl——这里需要说明的是,在实际开发中,控制层一般不会直接调用模型层方法进行数据操作,往往通过调用业务层Service,在ServiceImpl中调用模型层方法实现业务。因为一个功能可能是由多个基本的数据库操作加上一些特殊的逻辑判断才能完成的,所以通过Service\ServiceImpl这样的面向接口设计,来进一步使控制层与模型层解耦,使程序结果更清晰,更易维护与扩展。

MVC的优势在于分层使程序清晰,使各层开发人员可以专注于自己的模块,易于开发;程序解耦使程序更易维护与拓展;视图层的独立使多个业务可共用一个视图做为响应,增强了代码的可重用性。常见的MVC框架有Struts2,SpringMVC等(更确切的说这些框架只是负责MVC中的一部分,Struts2与SpringMVC的作用更多体现在控制层,而Hibernate与Mybatis等持久层框架就是用来处理模型层数据库操作的)。

学习Javaweb逃不开三个技术:过滤器、拦截器、监听器
过滤器:先于Servlet与JSP执行,也就是依赖于Web容器实现。当客户端发出一个请求时(无论是请求Action还是资源的直接定位),都可以被过滤器过滤到。我们使用过滤器大多是进行一些通用的处理,比如非法url的过滤、字符编码的设置或用户权限的确定Struts2的核心类就是一个名叫StrutsPrepareAndExcuteFilter的过滤器。

拦截器:与过滤器功能类似,但不依赖于Web容器实现。拦截器是Struts2的核心功能,是一种AOP的概念。拦截器同样可以拦截请求进行预处理,但它只能拦截Action而不能拦截资源的直接定位,这个范围差别是我们选择使用过滤器与拦截器的一个重要考量因素。拦截器的功能较过滤器更为强大,他可以访问到Action上下文ActionContex以获取request、response、session等内容。

拦截器与过滤器的区别还体现在设计思想上:过滤器重在过滤,得到合格的请求或响应;拦截器重在拦截,拦截不合理的请求或响应。

监听器:并不常用,可以监听session、Servlet上下文,往往用于一些特定的功能比如一些初始化配置工作,如在Servlet启动时配置数据库连接与连接池。

刚刚说拦截器是一种AOP的概念,那AOP是什么呢?如下这段话是我看过得最易懂的一段AOP的解释。
     面向切面编程(AOP是Aspect Oriented Program的首字母缩写),我们知道,面向对象的特点是继承、多态和封装。而封装就要求将功能分散到不同的对象中去,这在软件设计中往往称为职责分配。实际上也就是说,让不同的类设计不同的方法。这样代码就分散到一个个的类中去了。这样做的好处是降低了代码的复杂程度,使类可重用。
      但是人们也发现,在分散代码的同时,也增加了代码的重复性。什么意思呢?比如说,我们在两个类中,可能都需要在每个方法中做日志。按面向对象的设计方法, 我们就必须在两个类的方法中都加入日志的内容。也许他们是完全相同的,但就是因为面向对象的设计让类与类之间无法联系,而不能将这些重复的代码统一起来。

      也许有人会说,那好办啊,我们可以将这段代码写在一个独立的类独立的方法里,然后再在这两个类中调用。但是,这样一来,这两个类跟我们上面提到的独立的类 就有耦合了,它的改变会影响这两个类。那么,有没有什么办法,能让我们在需要的时候,随意地加入代码呢?这种在运行时,动态地将代码切入到类的指定方法、 指定位置上的编程思想就是面向切面的编程。 
      一般而言,我们管切入到指定类指定方法的代码片段称为切面,而切入到哪些类、哪些方法则叫切入点。有了AOP,我们就可以把几个类共有的代码,抽取到一个切片中,等到需要时再切入对象中去,从而改变其原有的行为。
这样看来,AOP其实只是OOP的补充而已。OOP从横向上区分出一个个的类来,而AOP则 从纵向上向对象中加入特定的代码。有了AOP,OOP变得立体了。如果加上时间维度,AOP使OOP由原来的二维变为三维了,由平面变成立体了。从技术上 来说,AOP基本上是通过代理机制实现的。 
     AOP在编程历史上可以说是里程碑式的,对OOP编程是一种十分有益的补充。


Spring的AOP是做的最成功的,但现阶段可能我们使用更多的是Spring的其他特性,控制反转(IOC)与依赖注入(DI):

IOC是一种叫做“控制反转”的设计思想。

较浅的层次——从名字上解析 
“控制”就是指对 对象的创建、维护、销毁等生命周期的控制,这个过程一般是由我们的程序去主动控制的,如使用new关键字去创建一个对象(创建),在使用过程中保持引用(维护),在失去全部引用后由GC去回收对象(销毁)。 
“反转”就是指对 对象的创建、维护、销毁等生命周期的控制由程序控制改为由IOC容器控制,需要某个对象时就直接通过名字去IOC容器中获取。

更深的层次——提到DI,依赖注入,是IOC的一种重要实现 
一个对象的创建往往会涉及到其他对象的创建,比如一个对象A的成员变量持有着另一个对象B的引用,这就是依赖,A依赖于B。IOC机制既然负责了对象的创建,那么这个依赖关系也就必须由IOC容器负责起来。负责的方式就是DI——依赖注入,通过将依赖关系写入配置文件,然后在创建有依赖关系的对象时,由IOC容器注入依赖的对象,如在创建A时,检查到有依赖关系,IOC容器就把A依赖的对象B创建后注入到A中(组装,通过反射机制实现),然后把A返回给对象请求者,完成工作。

IOC的意义何在? 
IOC并没有实现更多的功能,但它的存在使我们不需要很多代码、不需要考虑对象间复杂的耦合关系就能从IOC容器中获取合适的对象,而且提供了对 对象的可靠的管理,极大地降低了开发的复杂性。






本文转载:CSDN博客