在这个Spring MVC教程中,我们将学习如何使用Spring Tool Suite开发Spring MVC Web应用程序。Spring MVC框架广泛用于Java Web应用程序。
Spring MVC
就像Struts框架一样,Spring MVC也基于Java EE Servlet和JSP技术,并实现了Model–View–Controller设计模式。
Spring MVC教程
我们之前已经看过Spring 依赖注入是如何工作的,在本教程中,我们将学习如何使用 Spring MVC 框架创建一个简单的 Web 应用程序。我们可以使用 Eclipse 或 IntelliJ IDE 进行 Spring 项目开发,但 SpringSource 提供了Spring 工具套件(STS),它是基于 Eclipse 的 IDE,并带有内置的VMware vFabric tc Server,该服务器建立在 Apache Tomcat 容器之上,并针对基于 Spring 的应用程序进行了优化。我将使用 STS 进行Spring MVC 教程和其他未来的教程,因为它通过提供以下功能使开发者的生活更轻松:
- 支持创建骨架 Spring 应用程序(MVC、Rest、批处理等),非常适合从头开始启动项目。我们很快将在这个 Spring MVC 教程中看到,创建一个 Spring MVC 项目是多么容易。
- 提供有用的功能,如创建 Spring 配置文件、解析配置文件和类以提供有关它们的有用信息。
- 自动验证 Spring 应用程序
- 支持重构,轻松进行项目更改,更改会反映在配置文件中。
- 不仅为类提供代码辅助功能,而且为配置文件提供代码辅助功能,我非常喜欢这个功能,因为大多数时候我们都需要知道我们可以使用什么及其详细信息。
- 通过集成 AspectJ,提供最佳的面向方面编程(AOP)支持。
看着STS提供的所有功能,我被它吸引了,并决定在Spring应用中使用它,到目前为止,我非常满意。只需从STS官方下载页面下载并安装它。我正在使用基于Eclipse 4.3.1发布的STS 3.4.0.RELEASE。如果您不想使用STS,而是想在现有的Eclipse中获得其功能,则需要从Eclipse Marketplace安装其插件。请参考下面的图片,并确保选择正确的STS版本进行安装。下面的插件适用于Eclipse Kepler。
如果您不想使用SpringSource服务器,可以将应用程序部署在任何其他Java EE容器中,例如Tomcat、JBoss等。对于本教程,我将使用随STS一起提供的服务器,但我已经通过将其导出为WAR文件到单独的Tomcat服务器进行了应用程序测试,一切都运行正常。现在我们的服务器环境和IDE已经准备就绪,让我们继续创建我们的第一个Spring MVC项目。以下步骤适用于STS以及带有STS插件的Eclipse。
在STS或Eclipse中创建Spring MVC应用程序
步骤1:从菜单中创建新的Spring项目。 步骤2:在新项目窗口中,将名称设置为“SpringMVCExample”,并选择模板为“Spring MVC 项目”。如果您是首次使用此模板,STS 将从 SpringSource 网站下载它。如果需要,您可以将项目添加到任何工作集中。
步骤3:当模板下载完成后,在下一个屏幕中您需要提供顶层包名称。此包将用作 Spring 组件的基础包。
步骤4:一旦通过 Spring MVC 模板创建项目,它将如下图所示。如果您没有看到 User.java 类、login.jsp 和 user.jsp 文件,那没关系,它们是我后来添加的。如果您的项目没有编译并显示一些错误,请运行 Maven/Update Project。确保勾选“Force update of Snapshots/Releases”选项,参考下图。
整个项目看起来就像是任何其他基于 Maven 的 Web 应用程序,带有一些 Spring 配置文件。现在是时候分析项目的不同部分并稍作扩展。
Spring MVC 依赖
我们生成的 pom.xml 文件如下所示。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.journaldev</groupId>
<artifactId>SpringMVCExample</artifactId>
<name>SpringMVCExample</name>
<packaging>war</packaging>
<version>1.0.0-BUILD-SNAPSHOT</version>
<properties>
<java-version>1.6</java-version>
<org.springframework-version>4.0.0.RELEASE</org.springframework-version>
<org.aspectj-version>1.7.4</org.aspectj-version>
<org.slf4j-version>1.7.5</org.slf4j-version>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>
<!-- @Inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<additionalProjectnatures>
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
</additionalProjectnatures>
<additionalBuildcommands>
<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
</additionalBuildcommands>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>org.test.int1.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
artifactId 将用于 Web 应用程序的 servlet-context,因此如果您想要其他内容,可以更改它。对于 Spring Framework、AspectJ 和 SLF4j 版本,定义了一些属性,我发现它们未反映最新版本,因此我已将它们更改为今天的最新稳定版本。我感兴趣的项目依赖关系如下:
- spring-context:Spring 核心依赖项。请注意,这里排除了 commons logging,而是使用 SLF4J。
- spring-webmvc:Spring MVC 支持的 Spring 依赖项
- aspectjrt:AspectJ API 参考
- SLF4J 和 Log4j:用于日志记录目的,Spring 非常容易配置为 log4j 或 Java Logging API,因为它与 SLF4J 集成。
- javax.inject – 用于依赖注入的 JSR330 API
还添加了其他一些依赖项,例如 Servlet、JSP、JSTL 和 JUnit API,但对于入门应用程序,我们可以忽略它们。
Spring MVC教程 – Log4j配置
生成的log4j.xml文件如下所示。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="https://jakarta.apache.org/log4j/">
<!-- Appenders -->
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p: %c - %m%n" />
</layout>
</appender>
<!-- Application Loggers -->
<logger name="com.journaldev.spring">
<level value="info" />
</logger>
<!-- 3rdparty Loggers -->
<logger name="org.springframework.core">
<level value="info" />
</logger>
<logger name="org.springframework.beans">
<level value="info" />
</logger>
<logger name="org.springframework.context">
<level value="info" />
</logger>
<logger name="org.springframework.web">
<level value="info" />
</logger>
<!-- Root Logger -->
<root>
<priority value="warn" />
<appender-ref ref="console" />
</root>
</log4j:configuration>
请注意,它将所有内容都打印到控制台,我们可以轻松地添加附加器以将日志重定向到文件。
Spring MVC教程 – 部署描述符配置
让我们看看我们的web.xml并分析它。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="https://java.sun.com/xml/ns/javaee"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
ContextLoaderListener
将ApplicationContext
的生命周期与ServletContext
的生命周期绑定,并自动创建ApplicationContext
。ApplicationContext
是Spring bean的放置位置,我们可以通过contextConfigLocation上下文参数提供其配置。root-context.xml文件提供了WebApplicationContext的配置细节。DispatcherServlet
是Spring MVC应用程序的控制器类,所有客户端请求都由此servlet处理。配置是从servlet-context.xml文件加载的。
Spring MVC教程 – 配置文件
root-context.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
</beans>
我们可以在这里定义共享的bean,目前还没有内容。servlet-context.xml代码:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="https://www.springframework.org/schema/mvc"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="https://www.springframework.org/schema/beans"
xmlns:context="https://www.springframework.org/schema/context"
xsi:schemaLocation="https://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.journaldev.spring" />
</beans:beans>
这就是标准的Spring配置文件的样子,想象一下自己写这么多内容,你会开始喜欢STS工具。使用annotation-driven元素告诉Controller servlet将使用注解进行bean配置。resources元素定义我们可以放置静态文件(如图像、HTML页面等)的位置,这些文件不希望通过Spring框架获取。`InternalResourceViewResolver`是视图解析器,我们可以通过前缀和后缀属性提供视图页面的位置。因此,我们所有的JSP页面应该在/WEB-INF/views/目录下。context:component-scan元素用于提供扫描Controller类的基础包位置。记住在项目创建时给出的顶级包的值,这里使用的值是相同的。
Spring MVC Controller类
HomeController 是自动创建的,具有 home() 方法,尽管我稍微扩展了它,添加了 loginPage() 和 login() 方法。
package com.journaldev.spring;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* Handles requests for the application home page.
*/
@Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
/**
* Simply selects the home view to render by returning its name.
*/
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.info("Welcome home! The client locale is {}.", locale);
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
return "home";
}
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String loginPage(Locale locale, Model model) {
return "login";
}
@RequestMapping(value = "/home", method = RequestMethod.POST)
public String login(@Validated User user, Model model) {
model.addAttribute("userName", user.getUserName());
return "user";
}
}
@Controller 注解用于指示这是一个Web控制器类。@RequestMapping 与类和方法一起使用,将客户端请求重定向到特定的处理程序方法。请注意,处理程序方法返回 String 类型,这应该是要用作响应的视图页面的名称。正如您所看到的,我们有三个方法返回不同的字符串,因此我们需要创建具有相同名称的JSP页面。请注意,login() 方法将使用 POST HTTP 方法调用,因此我们在这里期望一些表单数据。因此,我们有 User 模型类,并使用@Validated 注解对其进行验证标记。每个方法都包含 Model 作为参数,我们可以设置属性,以便稍后在 JSP 响应页面中使用。
Spring MVC 模型类
模型类用于保存表单变量,我们的 User 模型 Bean 如下所示。
package com.journaldev.spring;
public class User {
private String userName;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
A simple java bean with the variable name and its getter and setter methods.
Spring MVC 教程 – 视图页面
我们有三个JSP页面如下。home.jsp 代码:
<%@ taglib uri="https://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
<title>Home</title>
</head>
<body>
<h1>
Hello world!
</h1>
<P> The time on the server is ${serverTime}. </P>
</body>
</html>
注意使用JSP表达式语言来获取属性值。login.jsp 代码:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Login Page</title>
</head>
<body>
<form action="home" method="post">
<input type="text" name="userName"><br>
<input type="submit" value="Login">
</form>
</body>
</html>
A simple JSP page for the user to provide the userName as input. Notice that form variable name is same as User class variable name. Also, form action is “home” and method is “post”. It’s clear that HomeController login() method will handle this request. user.jsp code:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>User Home Page</title>
</head>
<body>
<h3>Hi ${userName}</h3>
</body>
</html>
用户的简单首页,显示用户名,注意我们在登录方法中设置了此属性。
Spring MVC示例应用程序测试
我们的应用程序已准备就绪,只需在 VMware tc Server 或您选择的任何其他 servlet 容器上运行它,您将会得到以下页面作为响应。
Spring MVC 教程就到这里,您可以看到使用 STS 插件创建 Spring MVC 应用程序是多么容易。代码大小非常小,大部分配置由 Spring MVC 处理,因此我们可以专注于业务逻辑。从下面的链接下载示例 Spring MVC 项目并进行尝试。
Source:
https://www.digitalocean.com/community/tutorials/spring-mvc-tutorial