MVC模式
- 模式:解决某一问题的方法论。把解决某类问题的方法总结归纳到理论高度。
- MVC模式起源于Smalltalk语言。
- MVC:模型(Model)、视图(View)、控制器(Controller)。
- Model:应用的业务逻辑,包含应用程序的核心功能。模型封装了应用程序的状态,有时它包含的唯一功能就是状态,它对视图和控制器一无所知。
- View:应用的视图层,提供模型的表示。是应用程序的外观,视图可以访问模型的读方法,不能访问写方法。它对控制器一无所知。当更改模型时,视图应得到通知。
- Controller:应用的处理过程控制,控制器对用户的输入作出反应,它创建并设置模型。控制器的作用时从客户端接收请求,并且选择执行相应的业务逻辑,然后把相应结果送回到客户端。
MVC减弱了业务逻辑接口和数据接口之间的耦合。
MVC模式的好处:
- 可靠性:表示层和业务层分离,允许用户更改自己的表示层代码,而不用重新编译Model和Controller。
- 高重用和可适应性:MVC模型允许用户使用各种不同样式的视图(Web或WAP)来访问同一个服务器端的代码。
- 较低的生命周期成本:MVC使降低开发和维护用户接口的技术含量成为可能。
- 快速部署:开发时间得到很大的缩减。
- 可维护性:表示层和业务层分离,使得基于Struts的Web应用更易于维护和修改。
Model1规范
Model1:以JSP为中心的开发模型。
JSP页面中可以非常容易的结合业务逻辑(jsp:useBean)、服务端处理过程(jsp:scriplet)和HTML(<html>),在JSP页面中同时实现显示、业务逻辑和流程控制,从而可以快速地完成应用开发。
不足之处:
- 应用的实现一般是基于过程的,一组JSP页面实现一个业务流程,如果要进行改动,必须在多个地方进行修改。这样非常不利于应用扩展和更新。
- 由于应用不是建立在模块上的,业务逻辑和表示逻辑混合在JSP页面中没有进行抽象和分离,所有非常不利于应用系统业务的重用和改动。
Model2规范
Model2:基于MVC模式的框架。
Model2设计模型把应用逻辑、处理过程和显示逻辑分成不同的组件实现。这些组件可以进行交互和重用,从而弥补Model1的不足。
Model2具有组件化的优点,更易于实现对大规模系统的开发和管理,但是开发MVC比JSP复杂许多。
Sping MVC
Sping MVC:本质上就是在Model2的基础上实现的一个MVC架构。
Sping MVC的特点
- (1)清晰的角色划分。Spring的Model、View、Controller三个方面划分清晰,各司其职。
- (2)灵活的配置功能。Spring的核心是IoC,在实现MVC上,可以把各种类当作Bean来通过XML进行配置。
- (3)提供了大量的控制器接口和实现类。既可以使用也可以自己实现控制器接口。
- (4)Spring MVC是View层无关的。可以使用JSP、Velocity、Xslt等技术。
- (5)国际化支持。Spring的ApplicationContext提供了对国际化的支持。
- (6)面向接口编程。使得程序易于测试,管理方便。
- (7)Spring提供了Web应用开发的一整套流程,不仅是MVC,并且它们之间可以很方便的结合在一起。
一个在JSP页面输出“HelloWorld”的Spring MVC实例
- (1)编写web.xml文件
- (2)编写实现输出的JSP页面index.jsp
- (3)编写控制器HelloWorldAction.java
- (4)配置Spring文档dispatcherServlet-servlet.xml
下图分别时上述四个文件的存放位置:
(1)web.xml文件,放在WEB-INF文件夹下,与lib并列。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1"
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_3_1.xsd">
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--初始化参数-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/dispatcherServlet-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!--拦截所有以do结尾的请求-->
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
属性介绍:
- <servlet>用来定义一个Servlet
- <servlet-name>是<servlet>的属性,用来定义Servlet的名称。
- <servlet-class>是<servlet>的属性,用来指定的Servlet具体实现类。
- <init-param>是<servlet>的属性,用来定义Servlet的初始化参数。这里指定要初始化WEB-INF文件夹下的dispatcherServlet-servlet.xml,如果dispatcherServlet-servlet.xml的命名方式是前面定义servlet-name + “-servlet.xml”,则可以不用定义这个初始化参数,Spring默认会处理这个配置文件,这里其实是不用定义的。一个<servlet>可以有多个<init-param>。
- <load-on-startup>是<servlet>的属性,指定当Web启动时,加载Servlet的顺序,当它的值大于等于零时,Servlet容器先加载数值小的Servlet,再加载大的;如果值小于零或没有设定,则Servlet容器将再Web首次访问时加载这个Servlet。
- <servlet-mapping>用来指定访问Servlet时的URL。
- <servlet-name>用来定义Servlet的名称,和前面的<servlet>中定义的名称相对应。
- <url-pattern>指定访问Servlet时URL的相对路径,这里表示所有以do结尾的都用经过指定的dispatcherServlet。
(2)JSP 的 index.jsp 页面,再WEB-INF下新建 jsp 文件夹,将 index.jsp放在jsp文件夹下
<%@ page contentType="text/html; charset=GBK" language="java"%>
<html>
<head><title>第一个Spring MVC实例</title></head>
<%
String str = (String)request.getAttribute("helloWorld");
%>
<body>
<H1><%=str%></H1>
</body>
</html>
(3)编写控制器HelloWorldAction.java,放在com.gc.action下
package com.gc.action;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
public class HelloWorldAction implements Controller {
private Logger logger = Logger.getLogger(this.getClass().getName());
private String helloWorld;
private String viewPage;
@Override
public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse res) throws ServletException,IOException {
Map model = new HashMap();
model.put("helloWorld", getHelloWorld());
return new ModelAndView(getViewPage(),model);
}
//获取要显示在页面中的文字
public String getHelloWorld() {
return helloWorld;
}
//依赖注入显示在页面中的文字
public void setHelloWorld(String helloWorld) {
this.helloWorld = helloWorld;
}
//获取要返回的页面
public String getViewPage() {
return viewPage;
}
//依赖注入要返回的页面
public void setViewPage(String viewPage) {
this.viewPage = viewPage;
}
}
(4)配置Spring文档dispatcherServlet-servlet.xml,同样配置在WEB-INF下
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!--定义映射-->
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="helloWorld.do">helloWorldAction</prop>
</props>
</property>
</bean>
<!--定义视图-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass">
<value>org.springframework.web.servlet.view.InternalResourceView</value>
</property>
</bean>
<!--定义控制器-->
<bean id="helloWorldAction" class="com.gc.action.HelloWorldAction">
<property name="helloWorld">
<value>HelloWorld</value>
</property>
<property name="viewPage">
<value>/WEB-INF/jsp/index.jsp</value>
</property>
</bean>
</beans>
属性介绍:
- id为urlMapping的Bean,用来定义一个映射,对helloWorld.do的访问将会映射到id为helloWorldAction的Bean中。
- id为viewResolver的Bean,用来定义视图解析器,通过viewClass属性指定使用的视图。org.springframework.web.servlet.view.InternalResourceView表示使用的是JSP/Servlet技术。
- id为helloWorldAction的Bean,指定对helloWorld.do访问时使用的控制器为com.gc.action.HelloWorldAction。
- helloWorld属性依赖注入要在页面中显示的内容。
- viewPage属性依赖注入要返回的页面。
(5)启动tomcat,点击第一个猫
(6)在浏览器中输入 http://localhost:8080/myWebApp/helloWorld.do
此时应该得到输出结果为HelloWorld,但突然出错:“源服务器未能找到目标资源的表示或者是不愿公开一个已经存在的资源表示”。
好吧,几经周折。发现jsp编写的时候用的GBK编码格式,而通篇采用的时UTF-8格式,格式不兼容,导致文件查找不到,因此将index.jsp代码的编码方式修改以下即可,修改结果如下:
<%@ page contentType="text/html; charset=UTF-8" language="java"%>
<html>
<head><title>第一个Spring MVC实例</title></head>
<%
String str = (String)request.getAttribute("helloWorld");
%>
<body>
<H1><%=str%></H1>
</body>
</html>
(7)得到最终输出结果
(8)通过上面的代码,我们已经能够实现HelloWorld网页的输出。而不仅仅只有这一种输出方式, Jstl 给我们提供了在页面中输出内容的更方便的方式。把 index.jsp 改为使用 Jstl。在这之前需要引入Jstl的支持文件:
- 下载地址:http://archive.apache.org/dist/jakarta/taglibs/standard/binaries/
- 下载文件:jakarta-taglibs-standard-1.1.2.zip
- 将zip中的jstl.jar和standard.jar添加到项目的资源文件中,即WEB-INF\lib下,然后右击 Build Path。
添加资源文件后,修改index.jsp文件:
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<%@ page isELIgnored="false" %>
<html>
<head><title>第一个Spring MVC实例</title></head>
<body>
<H1><c:out value="${helloWorld}"/></H1>
</body>
</html>
- <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>表示使用的是Jstl的core_rt,前缀是c。
- <%@ page isELIgnored="false" %>表示是否使用EL语法,如果不写这句,则默认使用EL语法。
- <c:out value="${helloWorld}"/>:通过EL语法${helloWorld}输出处理器中的内容。
(9)修改配置文档 dispatcherServlet-servlet.xml
之前的配置可以看出,当页面较多,在Bean里都设定每个页面的具体路径 /WEB-INF/jsp/index.jsp时,如果将来要改变页面文件的存放位置,则每个这样的路径都要修改,比较麻烦。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!--定义映射-->
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="helloWorld.do">helloWorldAction</prop>
</props>
</property>
</bean>
<!--定义视图及JSP存放的路径-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass">
<value>org.springframework.web.servlet.view.JstlView</value>
</property>
<!--JSP存放的目录-->
<property name="prefix">
<value>/WEB-INF/jsp/</value>
</property>
<!--JSP文件的后缀-->
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<!--定义控制器-->
<bean id="helloWorldAction" class="com.gc.action.HelloWorldAction">
<property name="helloWorld">
<value>HelloWorld</value>
</property>
<property name="viewPage">
<value>index</value>
</property>
</bean>
</beans>