一、概述
最初,Java Web使用JSP+Java Bean的模式,两者之间存在严重的耦合。由于业务逻辑基本是由JSP完成的,Java和HTML也耦合在一起,前后端工作严重依赖和混杂在一起,两者都处理同一个JSP文件,前端等待后端完成,后端等待前端完成,然后才能进行测试,并且JSP很难复用。
JSP+Java Bean
由于上面的弊端,Servlet+JSP+Java Bean的MVC出现,取代了上述模式,Servlet作为控制器处理业务逻辑。Servlet接收用户请求,调度Java Bean取读写数据库,然后将结果放在JSP中。Servlet是Controller,Java Bean是专门操作数据库组件的模型层Model,JSP是向用户进行展示的的视图View。前后端在一定程度上分离,仍有所耦合。
由于控制器和模型层的分离,大量Java代码可以复用,MVC的经典框架Struts1/2和模型层的Hibernate纷纷崛起。但是,随着手机端的兴起,Web页面大部分使用Ajax请求,它们之间的交互只需要JSON数据而已,对于JSP的依赖大大减少。依赖于页面编程的Struts已经不能适合时代的发展。
MVC
不可优化SQL、不够灵活的Hibernate逐渐不敌MyBatis,但是MyBatis依然没处理好数据库事务的编程,同时随着各种NoSQL强势崛起,Java Web应用不仅能在数据库获取数据,也可以从NoSQL中获取数据,这些已不是持久层框架能够处理的了,而Spring MVC给出了方案。
如下图所示,传统的模型层被拆分为业务层(Service)和数据访问层(DAO,Data Access Object)。在Service下可以通过Spring的声明式事务操作数据访问层,而在业务层上还允许我们访问NoSQL,这样就能满足现今异军突起的NoSQL的使用,它的使用将大大提高互联网系统的性能。Spring MVC最大特色是结构松散,几乎可以使用各类视图,包括JSON、JSP、XML、PDF等,可满足手机端、页面端和平板电脑端的各类请求。
Spirng MVC
Sping MVC是一种基于Servlet的技术,它提供了核心控制器DispathcerServlet和相关的组件。
流程:
在Servlet初始化(调用init方法)时,Spring MVC会根据配置,获取配置信息,从而获得统一资源标识符(URI)和处理器(Handler,即controller),之间的映射关系(HandlerMapping),处理器可以有拦截器,我们还可以在处理器执行前加入自己的代码,于是,这些构成了处理器的执行链(HandlerContextChain)。
当一个请求到来时,DispatcherServlet首先通过请求和事先解析好的HandlerMapping配置,找到对应的处理器(Handler),准备开始运行处理器和拦截器组成的执行链。
处理器和拦截要通过适配器(HandlerAdapter)进行运行。
处理器返回模型和视图给DispatcherServlet,DispatcherServlet会把对应的视图信息传递给视图解析器(ViewResolver)。如果使用了逻辑视图,视图解析器会解析它,不过不是逻辑视图,视图解析器则不进行处理。
模型渲染到视图中去。
二、入门示例
步骤:
- 依赖添加
- 在web.xml中配置DispatcherServlet
- 配置Spring MVC配置文件
- 编写处理请求的处理器,并标识为处理器
- 编写视图
配置web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <!-- 配置DispatcherServlet --> <servlet> <servlet-name>springDispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 配置DispatcherServlet的一个初始化参数:配置SpringMVC配置文件的位置和名称 --> <!-- 实际上也可以不通过 contextConfigLocation 来配置 SpringMVC 的配置文件, 而使用默认的. 默认的配置文件为: /WEB-INF/<servlet-name>-servlet.xml --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <!-- 加载时创建 --> <load-on-startup>1</load-on-startup> </servlet> <!-- Map all requests to the DispatcherServlet for handling --> <servlet-mapping> <servlet-name>springDispatcherServlet</servlet-name> <url-pattern>/</url-pattern> <!-- /可以应答所有请求 --> </servlet-mapping> </web-app>
src下创建springmvc.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 配置自动扫描的包 --> <context:component-scan base-package="com.*"></context:component-scan> <!-- 配置视图解析器:如何把handler返回值(这里是success)解析为实际的物理视图 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"></property> <property name="suffix" value=".jsp"></property> </bean> </beans>
创建controller
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HelloWorld { /** * 1.使用@RequestMapping映射请求,JSP中超链接的名字 2.返回值会通过视图解析器解析为实际的物理视图,对于InternalResourceViewResolver视图解析, 会做如下的解析: 通过 * prefix+returnVal+suffix 的方式得到实际物理视图, 然后会转发操作 /WEB-INF/views/success.jsp */ @RequestMapping("/helloworld") public String hello() { System.out.println("Hello world!"); return "success"; } }
视图
创建/WEB-INF/views/success.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <h4>Success Page</h4> </body> </html>