MVC概述
比较Servlet和JSP可以看出,Servlet是在Java代码中嵌入HTML,而JSP则是在HTML中嵌入Java代码,两者的优缺点正好互补,如表7-1所示。
表7-1
Servlet
JSP
编写Java代码
容易
困难
编写HTML代码
困难
容易
如果仅使用Servlet,则虽然应用程序逻辑编写简单,但是,编码输出的页面极其难以维护;如果仅使用JSP,则虽然简化了页面设计,但大量的Java代码将使得应用程序逻辑难以维护。
因此,若能将Servlet和JSP结合使用,使得Servlet和JSP各司其职,就能大大降低Web应用程序的开发难度。
MVC(Model-View- Controller)即模型-视图-控制器,这种模式最早由Smalltalk语言引入,作为应用程序界面的标准设计模式,其应用范围极为广泛。MVC 模式通过将显示界面分为3个核心模块(模型、视图和控制器),分别负责不同的任务,协作完成一次完整的请求/响应。
图7-15显示了MVC模式的响应流程。
随着Web应用开发的兴起,MVC也被引入了 Web应用程序中。由于Servlet是纯Java代码,因此适合担任控制器,控制请求的流程。Servlet通过查询模型的状态,获得需要的数据,然后传递结果给视图,由视图将页面渲染出来,返回给用户。由于JSP主要是HTML标签,因此适合作为视图,仅负责渲染出结果页面。
受到HTTP协议的限制,模型的状态如果发生了更改,无法主动通知视图,因此,每次请求必须由浏览器发起。相对于传统的主动MVC模式,在Web应用程序中必须使用被动的MVC模式,如图7-16所示。
在JavaEE Web模型中,一个HTTP请求可以以3种转发方式。
(1)Forward:将一个请求传递给另一个组件处理,可以是Servlet或JSP,而当前的组件将不再继续处理请求。这也是MVC模式中转发请求让视图来渲染模型时使用的方式。
(2)Include:将一个请求传递给另一个组件处理,但是其处理结果将被包含在当前组件的输出页面中,通常,Include方式用来包含网站每个页面都共享的页眉和页脚,但是许多网页编辑工具本身就支持页面模板,因此,Include方式的使用并不多。
(3)Error:当处理请求发生了异常时,将被导向到指定的错误页面。
JavaEE平台上已经有许多成熟的Web MVC框架,例如,Struts和WebWork,其原理大同小异。在介绍如何使用Spring的MVC框架前,有必要首先弄清楚MVC的实现原理。
根据MVC的设计思想,一个完整的HTTP请求需要经过以下几步处理。
① 所有的HTTP请求都将映射到一个Servlet上。
② Servlet根据URL选择合适的Controller来处理请求,获得返回的Model和View。
③ Servlet将Model绑定到Request中,然后交给View渲染。
④ View将渲染后的页面返回给用户,完成请求处理。
由于存在多个控制器,如果直接用 Servlet作为控制器,则需要实现多个Servlet,这会导致非常复杂的配置和大量的重复代码。因此,通常将Servlet作为一个请求入口,或者称之为前置控制器(Front Controller),然后根据URL选择一个合适的控制器处理,具体流程如图7-17所示。
由于Servlet需要知道URL和控制器的映射关系,所以还需要首先抽象出Controller。通常,在Web MVC框架中,我们将抽象的Controller称为控制器,将负责接收用户请求的Servlet称为前置控制器或请求转发器(DispatcherServlet)。下面,我们在Eclipse中建立一个SimpleMVC项目,自己动手实现一个最简单的MVC流程,如图 7-18所示。
图7-18
7.2.1 设计Controller
根据面向接口编程的良好实践,首先定义一个Controller接口。
public interface Controller {
ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception;
}
Controller 需要返回视图和将要由视图渲染的Model。视图通常是JSP页面,因此,返回JSP页面的路径即可,而Model可以简单地使用Map来实现。由于一个方法只能返回一个对象,因此,有必要将Model和View一起返回。设计ModelAndView如下。
public class ModelAndView {
private String view;
private Map<String, Object> model;
public ModelAndView(String view, Map<String, Object> model) {
this.view = view;
this.model = model;
}
public String getView() { return view; }
public Map<String, Object> getModel() { return model; }
}
下一步是实现一个具体的TestController,它从request中获得URL的参数,然后生成Model并返回ModelAndView。
public class TestController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServlet Response response) throws Exception {
String name = request.getParameter("name");
if(name==null) name = "world";
Map<String, Object> model = new HashMap<String, Object>();
model.put("message", "This is a TestController.");
model.put("greet", "Hello, " + name + "!");
model.put("time", new Date().toString());
// 返回的JSP视图路径是"/test.jsp":
return new ModelAndView("/test.jsp", model);
}
}
在实现了Controller后,现在需要定义的就是如何在Servlet中控制整个请求的处理流程。
7.2.2 实现请求转发
通常,我们把接收所有请求的Servlet命名为DispatcherServlet,在SimpleMVC项目中,我们把所有以“.cmd”结尾的URL 都映射到DispatcherServlet,然后在DispatcherServlet中,根据URL选择合适的Controller,实现请求转发。我们假定现在定义了两个Controller:TestController和LoginController,其对应的URL分别是 “/test.cmd”和“/login.cmd”,在DispatcherServlet中处理如下。
public class DispatcherServlet extends HttpServlet {
private ServletContext context;
private Map<String, Controller> controllers;
// 初始化DispatcherServlet:
public void init(ServletConfig config) throws ServletException {
context = config.getServletContext();
// 将URL和对应的Controller关联起来:
controllers = new HashMap<String, Controller>();
controllers.put("/test.cmd", new TestController());
controllers.put("/login.cmd", new LoginController());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String contextPath = request.getContextPath();
String uri = request.getRequestURI().substring(contextPath.length());
Controller controller = controllers.get(uri);
if(controller==null) {
// 没有找到合适的Controller处理请求,直接返回一个404错误:
response.sendError(404);
return;
}
try {
// 将请求交给Controller处理:
ModelAndView mv = controller.handleRequest(request, response);
// 将Model绑定到Request中:
Map<String, Object> model = mv.getModel();
Set<String> keys = model.keySet();
for(String key : keys)
request.setAttribute(key, model.get(key));
// 获得JSP视图的路径:
String jsp = mv.getView();
// 转发给JSP视图渲染:
context.getRequestDispatcher(jsp).forward(request, response);
}
catch(Exception e) {
// 处理过程中发生异常,返回一个500错误:
response.sendError(500);
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// POST请求的处理方式和GET一样:
doGet(request, response);
}
}
DispatcherServlet 将Controller返回的Model绑定到Request,然后使用forward()将Request交给JSP页面渲染。在JSP页面中,只需要使用JSP标签把Model的数据显示出来,因此,不需要也不应该嵌入任何Java代码。test.jsp页面源码如下。
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>TestController -> test.jsp</title>
</head>
<body>
<p>/test.cmd (TestController) -> test.jsp </p>
<p>Message: <c:out value="${message}" /></p>
<p>Greet: <c:out value="${greet}" /></p>
<p>Time: <c:out value="${time}" /></p>
</body>
</html>
如果用户请求URL“/test.cmd?name=spring”,则整个请求按照以下流程处理,如图7-18所示。
LoginController则稍微复杂一点,它根据登录是否成功来决定返回哪一个ModelAnd View。
public class LoginController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServlet Response response) throws Exception {
String username = request.getParameter("username");
String password = request.getParameter("password");
if("admin".equals(username) && "password".equals(password)) {
// 登录成功,将转入/welcome.jsp:
Map<String, Object> model = new HashMap<String, Object>();
model.put("username", username);
model.put("greet", "Welcome!");
model.put("time", new Date().toString());
return new ModelAndView("/welcome.jsp", model);
}
// 登录失败,将转入/loginFailed.jsp:
Map<String, Object> error = new HashMap<String, Object>();
error.put("message", "Login failed.");
error.put("time", new Date().toString());
return new ModelAndView("/loginFailed.jsp", error);
}
}
为了能在Resin中测试我们自己实现的这个SimpleMVC,需要在web.xml中注册DispatcherServlet,由于JSP页面还使用了JSTL标签库,因此,还要在web.xml中注册标签库。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>example.chapter7.DispatcherServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.cmd</url-pattern>
</servlet-mapping>
<taglib>
<taglib-uri>http://java.sun.com/jsp/jstl/core</taglib-uri>
<taglib-location>/WEB-INF/c.tld</taglib-location>
</taglib>
</web-app>
分享到:
相关推荐
Servlet JSP和Spring MVC初学指南
Servlet、JSP和Spring MVC是Java Web开发中的三个重要技术,它们在构建动态网页和企业级应用程序中扮演着核心角色。下面将详细解释这三个技术及其相互关系。 **Servlet** 是Java编程语言中的一种接口,由Java ...
在这个名为“budi-kurniawan-servlet-jsp-springmvc-examples-4754f4ab5d5c”的压缩包中,可能包含了各种示例代码,涵盖了Servlet、JSP和Spring MVC的基本用法和组合应用。例如: 1. Servlet示例:展示了如何创建和...
servlet , jsp和spring MVC学习指南电子书,spring MVC学习指南系列书籍。
这个jar文件包含Spring MVC框架相关的所有类。 包含国际化、标签、Theme、视图展现的FreeMarker、JasperReports、Tiles、Velocity、XSLT相关类。 当然,如果你的应用使用了独立的MVC框架,则无需这个JAR文件里的...
这个简单的登录注册系统展示了Spring框架的强大功能,以及如何与其他技术如Spring MVC、Spring JDBC和MySQL协同工作,为开发者提供了一个完整的后端解决方案。通过深入理解并实践这些知识点,开发者能够构建更复杂的...
2. **portlet上下文**:与Servlet上下文类似,portlet上下文提供了portlet特有的配置和资源。 3. **portlet间通信**:通过PortletSession和PortletPreferences,portlet可以共享数据或设置用户偏好。 4. **portlet...
使用环境:MyEclipse/Eclipse + Tomcat + MySQL。 使用技术:Spring MVC + Spring + MyBatis / JSP + Servlet + JavaBean + JDBC。
1. **配置文件**:包括Spring的主配置文件(如`applicationContext.xml`),其中定义了Bean的配置,包括DataSource、JdbcTemplate或JpaTemplate等,以及Spring MVC的配置文件(如`servlet-context.xml`),定义了...
Servlet+JSP与Spring+MVC是两种在Java Web开发中常见的技术栈,它们用于构建动态、交互式的Web应用程序。本指南将深入介绍这两种技术及其整合应用,通过配套的源码帮助初学者更好地理解概念和实践操作。 Servlet是...
Servlet和MVC(Model-View-Controller)是Java Web开发中的两个重要概念,它们在构建动态网站和应用程序中起着核心作用。在这个学习实例中,我们将会深入理解这两个概念,并通过具体的代码示例来加深理解。 Servlet...
在本文中,我们将深入探讨如何将Spring MVC、Spring和Mybatis这三大流行框架整合到一个Java Web项目中,创建一个高效、灵活的数据访问层。这个整合的Demo项目名为"ssm-demo",它是一个基于Maven构建的项目,这意味着...
Spring MVC 是一个基于 DispatcherServlet 的 MVC 框架,它是当前主流的 Web 框架之一。要想灵活运用 Spring MVC 来应对大多数的 Web 开发,就必须要掌握它的配置及原理。 一、Spring MVC 环境搭建 1. jar 包引入 ...
这个案例可能包括了Spring MVC的Controller,Spring的配置文件,Mybatis的Mapper和XML文件,以及数据库相关的配置。通过分析这些文件,初学者可以了解SSM框架的基本结构和使用方法,例如请求处理、服务层调用、...
在Servlet与Spring整合时,首先我们需要创建一个Spring配置文件(如`beans.xml`),在这个文件中定义bean的配置。然后在Web应用的`web.xml`中,通过`ContextLoaderListener`配置Spring上下文,使得在应用启动时...
本文主要介绍使用注解方式配置的spring mvc,之前写的spring3.0 mvc和rest小例子没有介绍到数据层的内容,现在这一篇补上。下面开始贴代码。 文中用的框架版本:spring 3,hibernate 3,没有的,自己上网下。 先说...
3. `org.springframework.web.servlet-3.0.2.RELEASE.jar`:这是 Spring MVC 的核心模块,提供了控制器(Controller)、模型视图(ModelAndView)以及调度器Servlet(DispatcherServlet)等关键组件。...
虽然Servlet能实现MVC,但现代Java Web开发更多地使用Spring MVC、Struts等成熟的MVC框架,它们提供了更高级的功能,如自动绑定、拦截器、依赖注入等,使开发更高效,代码更简洁。 综上所述,"MVCDemo2"项目展示了...
与 Spring Web MVC 并行地,Spring Framework 5.0 引入了响应式栈——一个名为 Spring WebFlux 的 Web 框架,该框架的命名也是基于其源模块 `spring-webflux`。本节将重点讨论 Spring Web MVC。 #### 二、...