Spring MVC之简单入门

时间:2022-05-25 09:49:50

一、Spring MVC简介:

1、什么是MVC

模型-视图-控制器(MVC)是一个众所周知的以设计界面应用程序为基础的设计模式。它主要通过分离模型(Model)、视图(View)及控制器(Control)在应用程序中的角色,从而将业务逻辑从界面中解耦。通常,模型负责封装应用程序数据在视图层展示。视图仅仅只是展示这些数据,不包含任何业务逻辑。控制器负责接收来自用户的请求,并调用后台服务(manager或者dao)来处理业务逻辑。处理后,后台业务层可能会返回了一些数据在视图层展示。控制器收集这些数据及准备模型在视图层展示。MVC模式的核心思想是将业务逻辑从界面中分离出来,允许它们单独改变而不会相互影响。

2、Spring MVC

Spring MVC是当前最优秀的MVC框架,自从Spring 2.5版本发布后,由于支持注解配置,易用性有了大幅度的提高。Spring 3.0更加完善,实现了对Struts 2的超越。现在越来越多的开发团队选择了Spring MVC。

Spring MVC也是服务到工作者模式的实现,但进行可优化。前端控制器是DispatcherServlet;应用控制器其实拆为处理器映射器(Handler Mapping)进行处理器管理和视图解析器(View Resolver)进行视图管理;页面控制器/动作/处理器为Controller接口(仅包含ModelAndView handleRequest(request, response) 方法)的实现(也可以是任何的POJO类);支持本地化(Locale)解析、主题(Theme)解析及文件上传等;提供了非常灵活的数据验证、格式化和数据绑定机制;提供了强大的约定大于配置(惯例优先原则)的契约式编程支持。

Struts2也是非常优秀的MVC构架,优点非常多比如良好的结构,拦截器的思想,丰富的功能。但这里想说的是缺点,Struts2由于采用了值栈、OGNL表达式、struts2标签库等,会导致应用的性能下降,应避免使用这些功能。而Struts2的多层拦截器、多实例action性能都很好。 

Spring MVC的优点:

---Spring MVC使用简单,学习成本低。学习难度小于Struts2,Struts2用不上的多余功能太多。

---Spring MVC很容易就可以写出性能优秀的程序,Struts2要处处小心才可以写出性能优秀的程序(指MVC部分)

---Spring MVC的灵活是你无法想像的,Spring框架的扩展性有口皆碑,Spring MVC当然也不会落后,不会因使用了MVC框架而感到有任何的限制。

二、Spring MVC的处理请求的基本流程

一个基本的流程图如下:

Spring MVC之简单入门

Spring MVC处理一个用户的请求的基本流程如下:

1、首先用户发送请求——>web服务器,此时web服务器已经根据web.xml的配置信息完成了相关初始化;

2、web服务器——>总控制器DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制; 

3、DispatcherServlet——>HandlerMapping, HandlerMapping 将会把请求映射为 HandlerExecutionChain 对象(包含一 个 Handler 处理器(页面控制器)对象、多个 HandlerInterceptor 拦截器)对象,通过这种策略模式,很容易添加新 的映射策略; 

4、HandlerAdapter——>处理器功能处理方法的调用,HandlerAdapter 将会根据适配的结果调用真正的处理器的功能处 理方法,完成功能处理;并返回一个 ModelAndView 对象(包含模型数据、逻辑视图名); 

5、ModelAndView 的逻辑视图名——> ViewResolver, ViewResolver 将把逻辑视图名解析为具体的 View,通过这种策略模式,很容易更换其他视图技术; 

6、View——>渲染,View 会根据传进来的 Model 模型数据进行渲染,此处的 Model 实际是一个 Map 数据结构,因此 很容易支持其他视图技术; 

7、返回控制权给 DispatcherServlet,由 DispatcherServlet 返回响应给用户,到此一个流程结束。

我们需要关心的核心开发步骤: 

---DispatcherServlet 需要在 web.xml 中的部署描述,从而拦截请求到 Spring MVC。 

---HandlerMapping 的配置,从而将请求映射到处理器。 

---HandlerAdapter 的配置,从而支持多种类型的处理器 

---ViewResolver 的配置,从而将逻辑视图名解析为具体视图技术 

---处理器(页面控制器)的配置,从而进行功能处理





三、实例演示

这里利用Spring MVC来实现一个查询员工信息的程序。

1、首先建立一个maven web工程,编辑pom.xml导入依赖。

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kang</groupId>
<artifactId>SpringmvcTest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging> <dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency> <!-- Spring MVC support --> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.1.4.RELEASE</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.1.4.RELEASE</version>
</dependency> <!-- Tag libs support for view layer --> <dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
<scope>runtime</scope>
</dependency> <dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
<scope>runtime</scope>
</dependency> </dependencies>
</project>

2、配置web.xml

配置 DispatcherServlet :DispatcherServlet 默认加载 /WEB-INF/<servletName>-servlet.xml 的 Spring 配置文件, 启动 WEB 层的 Spring 容器。可以通过 contextConfigLocation 初始化参数自定义配置文件的位置和名称。

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" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="taotao" version="2.5">
<display-name>SpringmvcTest</display-name> <!-- 配置 DispatcherServlet -->
<servlet>
<!--
这个Servlet的名字是spring,可以有多个DispatcherServlet,是通过名字来区分的。
每一个DispatcherServlet有自己的WebApplicationContext上下文对象。
同时保存在ServletContext中和Request对象中
-->
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- load-on-startup标示的是启动顺序,让这个Servlet随Servlet容器一起启动 -->
<load-on-startup>1</load-on-startup>
<!--
配置 DispatcherServlet 的一个初始化参数: 配置 SpringMVC 配置文件的位置和名称
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
-->
<!-- 这里采用默认配置, SpringMVC会在WEB-INF目录下寻找spring-servlet.xml
(因为这里定义的servlet-name是spring)来完成初始化-->
</servlet> <!-- 定义拦截哪些请求 -->
<servlet-mapping>
<!-- 与上面定义的servlet-name保持一致 -->
<servlet-name>spring</servlet-name>
<!--
url-pattern:表示哪些请求交给Spring Web MVC处理, “/” 是用来定义默认servlet映射的。
也可以如“*.html”表示拦截所有以html为扩展名的请求。
-->
<url-pattern>/</url-pattern>
</servlet-mapping> </web-app>

3、配置spring的配置文件

上面配置好web.xml后,请求已交给Spring MVC框架处理,因此我们需要配置Spring的配置文件。我们需要在Spring配置文件中配置HandlerMapping、HandlerAdapter。注意此配置文件必须在WEB-INF目录下,且名为spring-servlet.xml。

spring-servlet.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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd"> <!-- 配置自定扫描的包 -->
<context:component-scan base-package="com.kang"></context:component-scan> <!--
Spring MVC 提供主要的 HanderMapping 有 DefaultAnnotationHandlerMapping,
SimpleUrlHandlerMapping 和 BeanNameUrlHandlerMapping。
-->
<bean
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" /> <!-- 配置视图解析器: 如何把 handler 方法返回值解析为实际的物理视图 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>

配置视图解析器中

InternalResourceViewResolver:用于支持Servlet、JSP视图解析;

prefix和suffix:查找视图页面的前缀和后缀(前缀[逻辑视图名]后缀),比如传进来的逻辑视图名为hello,则该该jsp视图页面应该存放在“WEB-INF/views/hello.jsp”;



4、编写实现代码





---建立员工模型信息:这个类作为MVC模式的模型。

EmployeeVO.java

package com.kang.model;

import java.io.Serializable;

public class EmployeeVO implements Serializable {
private static final long serialVersionUID = 1L; private Integer id;
private String firstName;
private String lastName; public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getFirstName() {
return firstName;
} public void setFirstName(String firstName) {
this.firstName = firstName;
} public String getLastName() {
return lastName;
} public void setLastName(String lastName) {
this.lastName = lastName;
} @Override
public String toString() {
return "EmployeeVO [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + "]";
}
}

---编写模拟与数据库交互的DAO代码:这个类位于三层架构中的第三层,负责与底层的数据库存储进行交互。

EmployeeDAO.java

package com.kang.dao;

import java.util.List;

import com.kang.model.EmployeeVO;

public interface EmployeeDAO {
public List<EmployeeVO> getAllEmployees();
}

EmployeeDAOImpl.java

package com.kang.dao;

import java.util.ArrayList;
import java.util.List; import org.springframework.stereotype.Repository; import com.kang.model.EmployeeVO; @Repository
public class EmployeeDAOImpl implements EmployeeDAO { public List<EmployeeVO> getAllEmployees() {
List<EmployeeVO> employees = new ArrayList<EmployeeVO>(); EmployeeVO vo1 = new EmployeeVO();
vo1.setId(1);
vo1.setFirstName("xiaokang");
vo1.setLastName("chen");
employees.add(vo1); EmployeeVO vo2 = new EmployeeVO();
vo2.setId(2);
vo2.setFirstName("lei");
vo2.setLastName("wang");
employees.add(vo2); return employees;
}
}

---编写DAO交互服务代码:这个类处于三层架构中的第二层,负责与DAO层交互。

EmployeeManager.java

package com.kang.service;

import java.util.List;

import com.kang.model.EmployeeVO;

public interface EmployeeManager {
public List<EmployeeVO> getAllEmployees();
}

EmployeeManagerImpl.java

package com.kang.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import com.kang.dao.EmployeeDAO;
import com.kang.model.EmployeeVO; @Service
public class EmployeeManagerImpl implements EmployeeManager { @Autowired
EmployeeDAO dao; public List<EmployeeVO> getAllEmployees() {
return dao.getAllEmployees();
}
}

---编写控制代码:注解@RequestMapping在类级别和方法级别层面确定将被调用方法的URL。

EmployeeController.java

package com.kang.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import com.kang.service.EmployeeManager; @Controller
@RequestMapping("/employee-module")
public class EmployeeController {
@Autowired
EmployeeManager manager; @RequestMapping(value = "/getAllEmployees", method = RequestMethod.GET)
public String getAllEmployees(Model model) {
model.addAttribute("employees", manager.getAllEmployees());
return "employeesListDisplay";
//对应在WEB-INF/views的目录下应该有一个employeesListDisplay.jsp。 }
}

5、编写jsp页面

首先写一个index.jsp页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Spring MVC Test</title>
</head>
<body>
<a href="employee-module/getAllEmployees">获取员工信息</a>
<!-- 以get的方式发送一个请求,名为employee-module/getAllEmployees -->
</body>
</html>

然后再正确的位置编写一个jsp页面来显示结果。其位置和名称都由之前的相关配置决定。

spring-servlet.xml中一下两句指明了视图的目录为/WEB-INF/views/,后缀名为.jsp。

<property name="prefix" value="/WEB-INF/views/" />

<property name="suffix" value=".jsp" />

EmployeeController.java中以下语句指定了这个视图的名为employeesListDisplay

return "employeesListDisplay";

综上,应该在/WEB-INF/views/目录下定义一个employeesListDisplay.jsp的文件。

employeesListDisplay.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%> <html>
<head>
<title>Spring MVC Hello World</title>
</head> <body>
<h2>All Employees in System</h2> <table border="1">
<tr>
<th>Employee Id</th>
<th>First Name</th>
<th>Last Name</th>
</tr>
<c:forEach items="${employees}" var="employee">
<tr>
<td>${employee.id}</td>
<td>${employee.firstName}</td>
<td>${employee.lastName}</td>
</tr>
</c:forEach>
</table> </body>
</html>

至此,整个项目构建完毕,完整目录结构如下:



Spring MVC之简单入门



6、测试

将项目部署到tomcat上,访问index.jsp,点击超链接,结果如下:

Spring MVC之简单入门

Spring MVC之简单入门