Spring MVC是如何逐步简化Servlet的编程的java
Servlet和JSP是开发java Web应用程序的两种基本技术,Spring MVC是Spring框架中用于Web应用程序开发的一个模块,可以清晰的了解到从Servlet到Spring MVC开发技术之间逐步简化的过程对于深入理解Spring MVC在Web应用程序开发中的做用具备很大的帮助。咱们会从项目的目录结构来介绍这个简化的过程:web
1、 在Servlet中spring
在应用程序目录下是WEB-INF目录,它包含classes子目录,Servlet类以及其余的Java类必须放在这个下面,在最基本的Servlet类中,须要实现Servlet接口定义的init(),service(),destroy(),getServletConfig()和getServletInfo()方法,其中最基本的逻辑放在service()方法中进行编写,在servic()方法中最经常使用的是会经过PrintWriter进行内容的输出。数据库
演进1:实现Servlet接口的时候必须将全部的方法进行实现,即使有些根本没有包含任何代码。可是GenericServlet抽象类实现了Servlet和ServletConfig接口简化了任务。express |
所以在GenericServlet抽象类的帮助下,咱们只须要重写service方法中实现咱们的任务就能够了。编程
演进2:然而GenericServlet并不经常使用,由于HttpServlet才是主角,而且不须要覆盖service()方法而是doGet(),doPost()来编写逻辑。后端 |
HttpServlet覆盖了GenericServlet类,它将ServletRequest和ServletRespond对象分别转换成了HttpServletRequest和HttpServletRespond对象,并调用最经常使用的doGet()(从服务器端向客户端呈现),doPost()(从客户端得到到服务器端处理)等七种方法而不须要重写service方法。api
利用部署描述符是一种配置Servlet应用程序的方法,部署描述符命名为web.xml并放在WEB-INF目录下。 浏览器
Servlet还提供了四种状态保持技术:URL重写,隐藏域,cookies和HTTPSession。其中HTTPSession是最经常使用的。tomcat
2、JSP的加入
演进3:Servlet有两个缺点:1)写在Servlet中的全部HTML标签必须包含java字符串似的处理HTTP响应报文工做复杂;2)全部的文本都是硬编码,便是出现了一点点的变化也须要重现编译。JSP解决了上述的问题并与Servlet同时使用。 |
JSP本质上是一个Servlet,然而其不须要编译,JSP页面是一个以.jsp扩展名的文本文件。简单的JSP页面在第一次请求后被翻译为(JSP名)_jsp的Servlet,翻译以后的Servelt能够看到:_jspInit(),_jspDestory(),_jspService()这样的方法其实都是和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两个类;简单标签处理器须要实现
在构建标签处理器是,须要在构建目录中有Servlet API及JSP API(servlet-api.jar和jsp-api.jar)这两个文件。自定义标签由组件处理器(WEB-INF/classes)及标签描述器(WEB-INF中的.tld)文件组成。一样也须要taglib指令使用自定义标签。
能够把自定义的标签处理器以及标签描述器打包到jar包中,并指定绝对的URI,这样就能够把它像JSTL同样发布出来。
演进7:编写自定义标签是一件冗长琐碎的事,须要编写并变异一个标签处理类还要在标签库中进行描述。经过tag file的方式,无须辨析标签处理类和标签库描述文件也可以自定义标签。tag file使用前不须要编译,也不须要描述文件。 |
tag file无需提早编译且只须要JSP语法就能够。一个tag file拥有指令,脚本,EL,动做元素以及自定义标签,一个tag file以tag和tagx为后缀,它们能够包含其余资源,一个被其余文件包含的tag file应该以tagf为后缀。
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的实现顺序和规则,在部署描述符中,先配置的先执行。
演进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应用中部署插件和框架。 |
3、 Spring MVC的实现
演进13: Servlet的动态加载能够实如今不重启web应用的前提下,添加新的web对象,Servlet容器加载器能够以插件形式发布应用而不须要修改部署描述,对框架的使用特别有用。 |
ServletContext接口中提供的(建立,注册,使用)(Filter,Listener,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的实例中。
Spring XML的配置写在spring-config.xml文件中,配置文件能够是一份,也能够分解为多份以支持模块化的配置,既能够经过主配置文件读取多份配置文件,也能够在其余配置文件中读取主配置文件。
Spring建立控制反转容器能够经过构造器的方式,也能够是setter方法。
解耦3:Spring MVC模式实现了Web应用开发的模型2方式 |
一个MVC模式的应用包含模型,视图和控制器三个部分。视图负责应用的展现。模型封装了应用的数据和业务逻辑,控制器负责接收用户输入,改变模型以及调整视图的显示。
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。
解耦4:解耦控制器代码,若是将业务逻辑代码都写在Servlet控制器中是哪一个,这个Servlet类将随着应用复杂度的增长而不断膨胀,应当将业务逻辑代码提取到独立的controller类中。 |
InputProductController类和SaveProductController类都实现了Controller接口,这使得Controller Servlet变得更加专一,就像一个Dispatcher,而非一个controller,即DispatcherServlet用来进行controller的分派。
演进14: 在Web应用执行action时,须要进行输入的校验,编程式的校验经过编码进行用户输入校验,声明式提供包含教研规则的XML文档或者属性文件。 |
演进15:在应用MVC时,能够在Controller类中调用后端业务逻辑。一般后段封装了复杂的逻辑service类,在service类中,能够实例化一个DAO类来访问数据库。在Spring环境中,Service对象能够自动被注入到Controller实例中,而DAO对象能够自动被注入到Service对象中。 |
4、 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文件。
演进17:Spring MVC使用视图解析器负责解析视图,能够经过在配置文件中定义一个ViewResolver来配置试图解析器。 |
springmvc-config.xml实现了Dispatcher Servlet和ViewResolver的配置。同时也须要在部署描述符中进行配置。
演进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将会介入。 |
Spring MVC中有两种用户输入验证方式:Spring自带的验证框架和JSR 303的实现。前者须要实现Validator接口,而且须要调用reject方法来添加错误;后者则是经过注解给对象属性添加约束。这样的验证器不须要显式注册,但若是想要从某个属性文件中获取错误信息能够在springmvc-config.xml中进行添加。
演进22:Spring MVC提供了国际化和本地方的支持,须要讲文本元文件隔离成属性文件。 |
将每个语言区域的文本元素都单独保存在一个独立的属性文件中,每一个文件都包含key/value对,而且每一个key都卫衣表示一个特定语言区域对象。并在springmvc-config.xml中进行配置。