欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SpringMVC是如何逐步简化Servlet的编程的

程序员文章站 2022-04-03 23:42:53
Spring MVC是如何逐步简化Servlet的编程的 Servlet和JSP是开发java Web应用程序的两种基本技术,Spring MVC是Spring框架中用于Web应用程序开发的一个模块,能够清晰的了解到从Servlet到Spring MVC开发技术之间逐步简化的过程对于深刻理解Spri ......

Spring MVC是如何逐步简化Servlet的编程的

Servlet和JSP是开发java Web应用程序的两种基本技术,Spring MVC是Spring框架中用于Web应用程序开发的一个模块,能够清晰的了解到从Servlet到Spring MVC开发技术之间逐步简化的过程对于深刻理解Spring MVC在Web应用程序开发中的作用具有很大的帮助。我们会从项目的目录结构来介绍这个简化的过程:

一、    在Servlet中

 SpringMVC是如何逐步简化Servlet的编程的

在应用程序目录下是WEB-INF目录,它包含classes子目录,Servlet类以及其他的Java类必须放在这个下面,在最基本的Servlet类中,需要实现Servlet接口定义的init(),service(),destroy(),getServletConfig()和getServletInfo()方法,其中最基本的逻辑放在service()方法中进行编写,在servic()方法中最常用的是会通过PrintWriter进行内容的输出。

演进1:实现Servlet接口的时候必须将所有的方法进行实现,即便有些根本没有包含任何代码。但是GenericServlet抽象类实现了Servlet和ServletConfig接口简化了任务。

因此在GenericServlet抽象类的帮助下,我们只需要重写service方法中实现我们的任务就可以了。

演进2:然而GenericServlet并不常用,因为HttpServlet才是主角,并且不需要覆盖service()方法而是doGet(),doPost()来编写逻辑。

HttpServlet覆盖了GenericServlet类,它将ServletRequest和ServletRespond对象分别转换成了HttpServletRequest和HttpServletRespond对象,并调用最常用的doGet()(从服务器端向客户端呈现),doPost()(从客户端获得到服务器端处理)等七种方法而不需要重写service方法。

 SpringMVC是如何逐步简化Servlet的编程的

利用部署描述符是一种配置Servlet应用程序的方法,部署描述符命名为web.xml并放在WEB-INF目录下。 

Servlet还提供了四种状态保持技术:URL重写,隐藏域,cookies和HTTPSession。其中HTTPSession是最常用的。

 

二、JSP的加入

演进3:Servlet有两个缺点:1)写在Servlet中的所有HTML标签必须包含java字符串似的处理HTTP响应报文工作复杂;2)所有的文本都是硬编码,即是出现了一点点的变化也需要重现编译。JSP解决了上述的问题并与Servlet同时使用。

JSP本质上是一个Servlet,然而其不需要编译,JSP页面是一个以.jsp扩展名的文本文件。简单的JSP页面在第一次请求后被翻译为(JSP名)_jsp的Servlet,翻译之后的Servelt可以看到:_jspInit(),_jspDestory(),_jspService()这样的方法其实都是和Servlet相对应的。

 SpringMVC是如何逐步简化Servlet的编程的

放在WEB-INF文件夹下的内容是无法直接通过浏览器输入地址访问的,而WEB-INF文件夹外的则是可以的,并且添加了新的JSP页面后无需重启JSP/Servlet容器(如tomcat)。 

解耦1:使用标准JSP访问,操作JavaBean,是实现展现(HTML)与业务实现(Java 代码)分离的第一步。

JSP中的注释(<%-- 内容 -- %>),指令(<%@ 指令名 %>),脚本(<% 脚本 %>),表达式(<%= 赋值结果 %>),声明(<%! 声明 %>),动作(<jsp:useBean />)。

演进4:JSP中的EL可以轻松访问应用程序数据,使得JSP页面不需要任何的声明,表达式和脚本。

EL表达式${expression}以及取值[]和.运算符。

演进5:JSP标准标签库(JSTL)在EL的基础上进一步解决了遍历Map,集合,条件测试,XML处理,数据库操作访问等操作的问题。

 使用JSTL需要taglib指令:

<%@ taglib uri=“uri” prefix=“prefix” %>

JSTL标签类型:声明赋值,条件判断,循环遍历,格式化,函数(主要是字符串函数)

演进6:JSP标准标签库(JSTL)提供了一些标签能解决常用的问题,但是对于一些非常见恶问题,需要扩展javax.servlet.jsp.tagetx包中的成员实现自定义标签。

 自定义标签的实现,叫作标签处理器,而简单标签处理器是指继承SimpleTag实现的经典自定义标签。经典标签处理器需要实现Tag,IterationTag及BodyTag接口或者扩展TagSupport,BodyTagSupport两个类;简单标签处理器需要实现

 SpringMVC是如何逐步简化Servlet的编程的

在构建标签处理器是,需要在构建目录中有Servlet API及JSP API(servlet-api.jar和jsp-api.jar)这两个文件。自定义标签由组件处理器(WEB-INF/classes)及标签描述器(WEB-INF中的.tld)文件组成。同样也需要taglib指令使用自定义标签。

可以把自定义的标签处理器以及标签描述器打包到jar包中,并指定绝对的URI,这样就可以把它像JSTL一样发布出来。

 SpringMVC是如何逐步简化Servlet的编程的

演进7:编写自定义标签是一件冗长琐碎的事,需要编写并变异一个标签处理类还要在标签库中进行描述。通过tag file的方式,无须辨析标签处理类和标签库描述文件也能够自定义标签。tag file使用前不需要编译,也不需要描述文件。

tag file无需提前编译且只需要JSP语法就可以。一个tag file拥有指令,脚本,EL,动作元素以及自定义标签,一个tag file以tag和tagx为后缀,它们可以包含其他资源,一个被其他文件包含的tag file应该以tagf为后缀。

 SpringMVC是如何逐步简化Servlet的编程的

tag文件必须放在路径的WEB-INF/tags目录下才能生效,和标签处理器一样,tag文件也可以打包成jar文件。

解耦2:Servlet提供了一系列的事件和事件监听借口,上层的servlet/JSP应用能够通过调用这些API进行事件驱动开发。

 监听器都继承自java.util.Event对象,监听器接口可以分为ServletContext,HttpSession和ServletRequest。监听器即一组动作的接口。编写一个监听器,只需要写一个java类来实现对应的监听器接口就可以了,然后通过@WebListener注解或者部署描述文档中增加listener元素进行注册。

演进8:使用Filter来拦截Request的请求,在用户的请求访问资源前处理ServletRequest以及ServletResponse可以实现日志记录,加解密,session检查和图像文件保护。

 Filter实现需要实现javax.servlet.Filter接口,需要实现init(),doFilter(),destroy()方法。Filter的配置可以通过@WebFilter或部署描述中的filter元素进行配置。Filter的使用需要考虑到Filter Chain的实现顺序和规则,在部署描述符中,先配置的先执行。

 SpringMVC是如何逐步简化Servlet的编程的

演进9: 修饰Request和Response实现Decorator模式

 

演进10: Servlet或者Filter占用请求处理县城,如果任务需要很长时间才能完成,当用户的并发请求超过县城树,容器会没有可用的线程。Servlet使用超时时间处理异步请求,释放正在等待完成的线程。

 

演进11: 尽管可以通过注解进行配置,但是在需要更加精细配置的情况下,部署描述符依然是需要的。部署描述符必须被命名为web.xml并且位于WEB-INF目录下,Java类必须放在WEB-INF/classes目录下,而Java的类库必须位于WEB-INF/lib目录下。所有的应用资源必须打包成.war为后缀的JAR文件。

 

演进12: web fragment可以实现在已有的web应用中部署插件和框架。

 SpringMVC是如何逐步简化Servlet的编程的

 

三、    Spring MVC的实现

演进13: Servlet的动态加载可以实现在不重启web应用的前提下,添加新的web对象,Servlet容器加载器可以以插件形式发布应用而不需要修改部署描述,对框架的使用特别有用。

ServletContext接口中提供的(创建,注册,使用)(Filter,Listener,Servlet)的方法。

 SpringMVC是如何逐步简化Servlet的编程的

initializer库是一个插件化的框架,有两个资源MyServletContainerInitializer类以及javax.servlet.ServletContainerInitializer的元文件,这个元文件必须放在WEB-INF/services目录下,这个元文件只有一行:initializer.MyServletContainerInitializer的实现类名。 

演进13: Spring作为开源的轻量级企业级应用开发框架,提供了依赖注入方法的实现。依赖注入是一种代码可测试性的解决方案。

简单来说,有两个组件A和B,A依赖于B,假定A是一个类且又一个方法使用到了B,那么A必须先获得组件B的实例引用。Spring的依赖注入会先创建B的实例,再创建A的实例,然后把B注入到A的实例中。

 SpringMVC是如何逐步简化Servlet的编程的

Spring XML的配置写在spring-config.xml文件中,配置文件可以是一份,也可以分解为多份以支持模块化的配置,既可以通过主配置文件读取多份配置文件,也可以在其他配置文件中读取主配置文件。

Spring创建控制反转容器可以通过构造器的方式,也可以是setter方法。

解耦3:Spring MVC模式实现了Web应用开发的模型2方式

 一个MVC模式的应用包含模型,视图和控制器三个部分。视图负责应用的展示。模型封装了应用的数据和业务逻辑,控制器负责接收用户输入,改变模型以及调整视图的显示。

SpringMVC是如何逐步简化Servlet的编程的 

 

Spring MVC使用Servlet充当控制器,Structs2使用Filter充当控制器。大部分都采用JSP页面作为视图。模型采用POJO(Plain Old Java Object),在实践中会采用一个JavaBean来持有模型的状态,并将业务逻辑放到一个Action类中,一个JavaBean必须拥有一个无参的构造器,通过getter/setter访问参数,同时支持持久化。

 

基本的Spring MVC项目结构包含:

1)       一个Product类,作为product的领域对象,Product类需要实现java.io.Serializable接口,因为需要保存在HttpSession中。

2)       一个ProductForm类,封装了HTML表单的输入项,ProductForm类鱼Product类相似,可以起到不将ServletRequest这个Servlet层的对象暴露给其它层的目的,同时也可以在数据校验失败时,表单对象将用于保存和展示用户在原始表单上的输入。

3)       一个ControolerServlet类作为控制器。

4)       两个JSP页面作为view。

 

 SpringMVC是如何逐步简化Servlet的编程的

解耦4:解耦控制器代码,如果将业务逻辑代码都写在Servlet控制器中是哪个,这个Servlet类将随着应用复杂度的增加而不断膨胀,应当将业务逻辑代码提取到独立的controller类中。

InputProductController类和SaveProductController类都实现了Controller接口,这使得Controller Servlet变得更加专注,就像一个Dispatcher,而非一个controller,即DispatcherServlet用来进行controller的分派。

 SpringMVC是如何逐步简化Servlet的编程的

演进14: 在Web应用执行action时,需要进行输入的校验,编程式的校验通过编码进行用户输入校验,声明式提供包含教研规则的XML文档或者属性文件。

 

演进15:在应用MVC时,可以在Controller类中调用后端业务逻辑。通常后段封装了复杂的逻辑service类,在service类中,可以实例化一个DAO类来访问数据库。在Spring环境中,Service对象可以自动被注入到Controller实例中,而DAO对象可以自动被注入到Service对象中。

 

四、    Spring MVC的优势

采用Spring MVC的优势:

1)       不需要编写DispatcherServlet;

2)       基于XML的文件配置不需要重新编译;

3)       可以实例化控制器,并根据用户的输入来构造bean;

4)       可以自动绑定用户输入,并正确进行数据类型的转换;

5)       可以进行用户输入的校验,可以重定向回输入表单,支持编程式校验和声明式校验;

6)       作为Spring框架的一部分,可以实现其他Spring提供的功能;

7)       支持国际化和本地化;

8)       支持多视图技术(JSP,FreeMarker,Velocity)。

演进16:Spring MVC自带一个开箱即用的Dispatcher Servlet。并提供了Controller接口并公开了handleRequest方法。

 要使用这个Servlet,需要在部署描述符中进行配置,并且会寻找一个应用程序的WEB-INF目录下的配置文件servletName-servlet.xml。controller需要实现org.springframework.web.servlet.mvc.Controller,Controller接口的实现类职能处理一个单一动作。

同时也需要添加Spring MVC所需要的JAR文件。

SpringMVC是如何逐步简化Servlet的编程的 

演进17:Spring MVC使用视图解析器负责解析视图,可以通过在配置文件中定义一个ViewResolver来配置试图解析器。

 springmvc-config.xml实现了Dispatcher Servlet和ViewResolver的配置。同时也需要在部署描述符中进行配置。

 SpringMVC是如何逐步简化Servlet的编程的

演进18:使用基于注解的控制器配置方法可以使得一个控制器类处理多个Action。

 @Controller注解类型用于指示Spring类的实例是一个控制器;

@RequestMapping注解可以为控制器内部的每一个动作开发相应的处理方法;

@Autowired和@Service注解可以将依赖注入到控制器内;

@ModelAttribute注解可以实现使用Spring MVC每次调用请求处理方法产生的Model类型实例。

演进19:数据绑定是将用户的输入绑定到领域模型的一种特性,也不再需要form bean这样的表单bean。表单的标签库会辅助这样的工作。

 使用表单标签库需要声明taglib指令。

演进20:由于Spring自身的数据绑定是杂乱无章的,需要通过Converter和Formatter来完成数据的绑定。

 Converter是通用元件,可以在应用程序的任意层中使用,而Formatter则是专门为Web层设计的。

需要实现的Converter接口和Formatter接口。同时也需要在springmvc-config.xml中进行注册。

演进21:Converter和Formatter只是作用于field级,Validator可以作用于object级。在调用Controller期间,将会有一个或者多个Formatter视图进行field值的变换,一旦格式化成功,Validator将会介入。

 SpringMVC是如何逐步简化Servlet的编程的

Spring MVC中有两种用户输入验证方式:Spring自带的验证框架和JSR 303的实现。前者需要实现Validator接口,并且需要调用reject方法来添加错误;后者则是通过注解给对象属性添加约束。这样的验证器不需要显式注册,但如果想要从某个属性文件中获取错误信息可以在springmvc-config.xml中进行添加。

演进22:Spring MVC提供了国际化和本地方的支持,需要讲文本元文件隔离成属性文件。

 SpringMVC是如何逐步简化Servlet的编程的

将每一个语言区域的文本元素都单独保存在一个独立的属性文件中,每个文件都包含key/value对,并且每个key都卫衣表示一个特定语言区域对象。并在springmvc-config.xml中进行配置。