很多应用程序的问题在于处理业务数据和显示业务数据的视图的对象之间存在紧密耦合。通常,更新业务对象的命令都是从视图本身发起的,使视图对任何业务对象更改都有高度敏感性。而且,当多个视图依赖同一个业务对象是没有灵活性的。
Spring Web Mvc是一种基于Java的实现了Web Mvc设计模式的请求驱动类型的轻量级web框架,即使使用了MVC架构模式的思想,将web层进行指责解耦,基于请求驱动指的是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring Web Mvc也是我们日常web开发的。
一、SpringMvc简介
在早期的Javaweb开发中,统一把显示层、控制层、数据层的操作全部交给JSP或者JavaBean来进行处理,称作为Model1:
这样开发web应用的话会出现几个弊端,
- Jsp和JavaBean之间严重耦合,Java代码和HTML代码耦合在了一起
- 对于开发者的要求大大增加,需要前后端一起掌握
- 前端和后端相互依赖,前端需要等待后端完成,后端也需要等待前端完成,才能进行测试的过程
- 代码难以复用
所以出现了servlet+jsp+JavaBean这种模式,这就是早期的MVC模式model2:
首先用户的请求会到达servlet,然后根据请求调用响应的JavaBean,并把所有显示的结果交给JSP去完成,这样的模式就称作为MVC模式化
- M代表模型,模型就是数据,就是dao,bean
- V代表视图,视图就是网页,用来展示模型中的数据
- C代表控制器,控制器就是把不同的数据展示在不同的页面上,servlet就是这个角色
为了解决一些问题,数据库事务问题和NoSql,传统的模型层被拆分为业务层和数据访问层。在service下可以通过spring的声明式事务操作数据访问层。在业务层上允许可以直接访问NoSql,这样就能满足Nosqsl,它可以大大的提高互联网的性能。
架构的特点为:结构松散,几乎可以在Spring Mvc中使用各类视图;松耦合,各个模块分离;与spring无缝集成。
二、SpringMvc使用
使用idea创建一个springMvc架构项目,idea会自动下载一些所需的jar包,并且创建好结构,结构图如下图所示
修改web.xml配置文件,拦截所有的请求,并交由Spring Mvc的后台控制器来处理,
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
修改spring Mvc的映射配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="simpleUrlHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <!-- /hello 路径的请求交给 id 为 helloController 的控制器处理--> <prop key="/hello">helloController</prop> </props> </property> </bean> <bean id="helloController" class="controller.HelloController"></bean> </beans>
编写HelloController类,获取请求后操作index.jsp页面
public class HelloController implements Controller { @Override public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception { ModelAndView mav = new ModelAndView("index.jsp"); mav.addObject("message", "Hello Spring MVC"); return mav; } }
编写好index,jsp和配置Tomcat及相关环境启动即可
根据Spring Mvc请求
当用户在页面中点击连接或者提交表单的时候,请求就开始工作了,从离开浏览器开始到获取响应返回,它会经历很多站点,在每一个站点都会留下一些信息同时也会带上其他信息。
第一站:DispatcherServlet
从请求离开浏览器以后,第一站到达的就是DispatcherServlet,看名字的话是一个servlet,servlet是可以拦截并处理HTTP请求,DispatcherServlet会拦截所有的请求,并且把这些请求发给Spring Mvc控制器
<servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
DispatcherServlet的任务就是拦截请求发送给Spring Mvc控制器
第二站:处理映射器
应用程序中可能会有很多个控制器,那么这些请求是对应哪个控制器呢?
所以DispatcherServlet会查询一个或多个处理器来确定下一站是哪里,处理器映射会根据请求的地址来进行决定,例如simpleUrlHandlerMapping 来将/hello地址交给HelloController类进行处理
<bean id="simpleUrlHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <!-- /hello 路径的请求交给 id 为 helloController 的控制器处理--> <prop key="/hello">helloController</prop> </props> </property> </bean> <bean id="helloController" class="controller.HelloController"></bean>
第三站:控制器
一旦选择了合适的控制器,DispatcherServlet会将请求发送给选中的控制器,到了控制器,请求会将用户的请求发送到控制器等待控制器处理完这些信息然后返回
public class HelloController implements Controller { @Override public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception { //处理逻辑 } }
第四站:返回DispatcherServlet
当控制器在完成逻辑处理后,会产生一些信息,这些信息就是需要返回给用户在浏览器上显示的信息,它们被称作为模型(model)。这些信息需要以用户友好的方式进行格式化,一般是HTML,所以信息需要发送一个视图(view),通常会是jsp。
控制器所做的最后一件事情就是将数据模型打包,并且表示出用于渲染输出的视图名。接下来会将请求连同模型和视图名发送回DispatcherServlet。
第五站:视图解析器
这样一来,控制器就不会和特定的视图耦合,传递给DispatcherServlet的视图名并不直接表示某个特定的JSP。相反,它传递的仅仅是一个逻辑名称,这个名称将会用来查找产生结果的真正视图。
第六站:视图
既然DispatcherServlet已经知道哪个视图渲染结果,那请求的任务基本上已经完成了。视图交付模型数据,请求的任务也就完成了。视图使用模型数据渲染出结果,这个输出结果会通过影响对象传递给客户端