Spring 框架入门教程
1. 1. Spring 框架 2. 2. Spring 5 3. 3. Spring WebFlux 4. 4. 先介绍一下 Spring 5. 5. 什么是 Spring 依赖注入 6. 6. 什么是 Spring IoC 容器 和 Bean 7. 7. Spring Bean 的生命周期 8. 8. Spring REST 开发 9. 9. Spring REST XML 10. 10. Spring RestTemplate 开发 11. 11. Spring AOP 切面编程 12. 12. Spring AOP 方法调优 13. 13. Spring 注解详解 14. 14. Spring 核心注解之 @Autowired 15. 15. Spring 核心注解之 @RequestMapping 16. 16. Spring MVC 开发样例 17. 17. Spring MVC 开发指南 18. 18. Spring MVC 异常处理机制 19. 19. Spring MVC Validator 20. 20. Spring MVC 拦截器 21. 21. Spring MVC 文件上传 22. 22. Spring MVC 国际化(i18n) 23. 23. Spring MVC Hibernate MqSQL 24. 24. Spring ORM 25. 25. Spring ORM JPA 26. 26. Spring Data JPA 27. 27. Spring 事务管理 28. 28. 常用的 Spring JdbcTemplate 29. 29. Spring Security 简介 30. 30. Spring Security 教程 31. 31. Spring Security UserDetailsService 32. 32. Spring MVC 登录注销简单案例 33. 33. Spring Security Roles 34. 34. Spring Boot Tutorial 35. 35. Spring Boot Components 36. 36. Spring Boot CLI Hello World 37. 37. Spring Boot Initilizr Web 38. 38. Spring Boot Initilizr IDE 39. 39. Spring Boot Initilizr CLI 40. 40. Spring Boot Initilizr Tools 41. 41. Spring Boot MongoDB 42. 42. Spring Boot Redis Cache 43. 43. Spring Boot 常见面试问题 44. 44. Spring Batch 45. 45. Spring Batch 批处理示例 46. 46. Spring AMQP 47. 47. Spring RabbitMQ 48. 48. Spring AMQP RabbitMQ 49. 49. Apache ActiveMQ 安装与启动 50. 50. Spring ActiveMQ 教程 51. 51. Spring ActiveMQ 示例 52. 52. Spring JDBC 53. 53. Spring DataSource JNDI 54. 54. Spring Hibernate 55. 55. Spring Primefaces JPA 56. 56. Spring Primefaces MongoDB 57. 57. Spring Primefaces Hibernate 58. 58. SpringRoo Primefaces Hibernate 59. 59. Spring JSF 60. 60. Spring JDF Hibernate 61. 61. Spring Data MongoDB 62. 62. Spring 常见面试问题

17. Spring MVC 开发指南

在这个Spring Mvc教程中,我们将学习如何使用springtoolsuite开发Spring Mvcweb应用程序。SpringMVC框架广泛用于java web应用程序.

SpringMVC

就像Struts框架,Spring Mvc也是基于J2EE的Servlet和JSP技术实施模型–个;视图–个;控制器设计模式。

SpringMVC教程

我们之前已经看到了Spring注射依赖在本教程中,我们将学习如何使用Spring Mvc框架创建一个简单的web应用程序。

我们可以使用Eclipse或intellijiide来开发Spring项目,但是SpringSource提供了Spring工具套件(STS)这是一个基于Eclipse的IDE,并带有内置的VMware vFabric tc服务器它构建在apachetomcat容器之上,并针对基于Spring的应用程序进行了优化。

我会用STSSpringMVC教程通过提供教程和其他功能,开发人员可以更轻松地使用以下功能:

  • 支持创建骨架式Spring应用程序(MVC、Rest、Batch等),有利于从头开始项目。在这个Spring Mvc教程中,我们很快就会看到创建Spring Mvc项目是多么容易。
  • 提供一些有用的特性,例如创建Spring配置文件、解析配置文件和类以提供有关它们的有用信息。
  • Spring应用的自动验证
  • 重构支持轻松地进行项目更改,更改也会反映在配置文件中。
  • 代码辅助不仅对类而且对配置文件也有帮助,我非常喜欢这个特性,因为大多数时候我们需要知道我们可以使用什么及其细节。
  • 通过AspectJ的集成对面向切面编程(AOP)的最佳支持。

看了STS提供的所有特性,我被卖了,并决定把它用于Spring应用程序,到现在为止,我对它非常满意。

只需从STS官方下载页面然后安装它。我使用的是基于Eclipse4.3.1版本的sts3.4.0.RELEASE。

如果您不想使用STS,并且希望在现有的Eclipse中获得它的功能,那么您需要从eclipsemarketplace安装它的插件。使用下面的图片作为参考,确保选择正确的STS版本进行安装。下面的插件对Eclipse开普勒很好。

如果您不想使用SpringSource服务器,您可以将该应用程序部署到任何其他J2EE容器中,如Tomcat、JBoss等。对于本教程,我将使用STS附带的服务器,但是我已经测试了该应用程序,将其作为WAR文件导出到单独的Tomcat服务器中,并且运行良好。

现在我们的服务器环境和IDE已经准备好了,让我们继续创建我们的第一个Spring Mvc项目。下面的步骤对STS以及Eclipse和STS插件都是有效的。

在STS或Eclipse中创建Spring Mvc应用程序

第1步:从菜单创建新的Spring项目。

第2步:在“新建项目”窗口中,将名称命名为&&8220;Spring Mvceexample&8221;并选择“模板”为&8220;Spring MVC project&8221;。如果您是第一次使用这个模板,STS将从SpringSource网站下载它。如果需要,可以将项目添加到任何工作集中。

第3步:下载模板时,您需要在下一个屏幕中提供顶级包名称。此包将用作Spring组件的基础包。

第4步:一旦项目由Spring Mvc模板创建,它将如下图所示。

如果你看不见,不要担心用户.java同学们,登录.jsp以及用户.jsp文件,它们是我后来添加的。

如果您的项目没有编译,并且您看到一些错误,请运行Maven/Update project。确保选中“;强制更新快照/版本”;选项,请参阅下图。

整个项目看起来就像任何其他基于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上下文,因此,如果需要其他内容,可以对其进行更改。

springframework,AspectJ和SLF4j版本定义的属性很少,我发现它们没有反映最新的版本,所以我把它们改成了今天最新的稳定版本。

我感兴趣的项目依赖性有:;

  • spring上下文:spring核心依赖项。注意,为了支持SLF4J而排除了commons日志记录。
  • springwebmvc:支持MVC的spring构件
  • aspectjrt:AspectJ API参考
  • SLF4J和Log4j:出于日志目的,Spring很容易为Log4j或Java日志API因为SLF4J集成。
  • javax.注入–;用于依赖注入的JSR330 API

还添加了一些其他依赖项,如Servlet、JSP、JSTL和junitapi,但对于初学者应用程序,我们可以忽略它们。

Spring Mvc教程和Log4j配置

生成的log4j文件如下所示。


<?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">
		<param name="Target" value="System.out" />
		<layout>
			<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 ties the ApplicationContext lifecycle to ServletContext lifecycle and automate the creation of ApplicationContext. ApplicationContext is the place for Spring beans and we can provide it’s configuration through 上下文配置位置上下文参数。根-上下文.xml文件提供WebApplicationContext的配置详细信息。

DispatcherServlet is the controller class for Spring MVC application and all the client requests are getting handled by this servlet. The configuration is being loaded from the servlet-context.xml file.

SpringMVC教程和配置文件

根-上下文.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-上下文.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>
		<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工具了。

注解驱动的元素用于让控制器servlet知道注解将用于bean配置。

资源元素定义了放置静态文件(如图像、HTML页面等)的位置,这些文件是我们不想通过Spring框架获得的。

InternalResourceViewResolver is the view resolver, we can provide view pages location through prefix and suffix properties. So all our JSP pages should be in /WEB-INF/views/ directory.

上下文:组件扫描元素用于提供扫描控制器类的基包位置。记住在创建项目时给出的顶层包的值,这里使用的值是相同的。

Spring MVC控制器类

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";
	}
}

@控制器注解用于指示它是一个web控制器类。

@RequestMapping与类和方法一起使用,将客户端请求重定向到特定的处理程序方法。注意,处理程序方法返回字符串,这应该是要用作响应的视图页的名称。

如您所见,我们有三个方法返回不同的字符串,因此我们需要创建具有相同名称的JSP页面。

请注意,login()方法将以POST的形式被HTTP方法调用,因此我们期望这里有一些表单数据。所以我们有了User model类,并使用@Validated注解对其进行了验证标记。

每个方法都包含Model作为参数,我们可以设置稍后在JSP响应页面中使用的属性。

Spring Mvc模型类

模型类用于保存表单变量,我们的用户模型bean如下所示。


package com.journaldev.spring;

public class User {

	private String userName;

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}
	
}

一个带有变量名及其getter和setter方法的简单javabean。

Spring MVC教程和查看页面

我们有三个JSP页面,如下所示。

主页.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表达式语言获取属性值。

登录.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>

一个简单的JSP页面,供用户提供用户名作为输入。注意,表单变量名和用户类变量名相同。另外,form action是“;home”;方法是“;post”;。很明显HomeController 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>User Home Page</title>
</head>
<body>
<h3>Hi ${userName}</h3>
</body>
</html>

显示用户名的用户的简单主页,请注意,我们在login方法中设置了此属性。

Spring Mvc示例应用程序测试

我们的应用程序已经准备好执行了,只需在vmwaretc服务器上运行它,或者您选择任何其他servlet容器,您将得到下面的页面作为响应。

精选推荐