跳至内容

Java 编程/Spring 框架

来自维基教科书,开放世界中的开放书籍

本教程旨在简要介绍使用 Spring 框架编写 Java 应用程序。请注意,本教程面向那些具有中等程度的Java 背景知识和对XML 的基本工作了解的人员。

在本教程中,我们将创建一个从 Spring bean 配置文件读取短篇故事的应用程序。(为了这个例子,这些短篇故事是非常短的故事。)将有三个 Java 类和一个 Spring 配置文件。所以让我们开始吧…

步骤 1:设置您的环境

[编辑 | 编辑源代码]

在我们直接创建文件之前,我们首先需要设置 Spring。我假设您已经安装了最新版本的 Java。如果没有,您可以从这里下载 Java 开发工具包。

Spring 建议使用 Maven 或 Gradle 来设置您的依赖项。[1]如果您尚未安装它们或它们没有由您的IDE(例如Eclipse)提供,您可以找到关于如何使用和下载它们的说明这里这里。Maven 或 Gradle 将确保您的依赖项及其依赖项在您的项目中加载。

请参阅http://projects.spring.io/spring-framework/中的“快速入门”部分,了解如何将 Spring 依赖项添加到您的项目。使用 Maven,您需要在项目根目录中提供一个包含以下内容的 pom.xml 文件

如果您使用的是 Maven,请确保您提供一个包含以下行的 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.mygroup</groupId>
  <artifactId>spring</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  
  <!-- Copy the following lines from http://projects.spring.io/spring-framework/ to depend on the latest version of spring -->
  <dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.1.3.RELEASE</version>
    </dependency>
</dependencies>
</project>

从这里开始,您可以将文本复制粘贴到步骤 2、3 和 4 的文件中;跳过说明;并自行运行程序。这些说明只是为了向您提供关于 Spring 将所有内容组合在一起的方式的背景信息。好的,现在让我们进入正题,story_configuration.xml

步骤 2:创建 Spring bean 配置文件

[编辑 | 编辑源代码]

在您计划放置 Java 文件的目录中创建一个新的 XML 文件。将其命名为 story_configuration.xml。然后将下面的文本复制粘贴到文件中并保存它

story_configuration.xml

[编辑 | 编辑源代码]
<?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="StoryList" class="spring.StoryList">
      <property name="stories">
         <list>
           <ref bean="HelloWorld"/>
           <ref bean="OnceUpon"/>
         </list>
       </property>
   </bean>

   <bean id="HelloWorld" class="spring.Story">
      <property name="title">
         <value>Hello World!</value>
      </property>
      <property name="author">
         <value>User:Hyad</value>
      </property>
      <property name="content">
         <value>This is a simple story.
This is a story about a man who said, "Hello, World."
See, now wasn't that simple.</value>
      </property>
   </bean>
	
   <bean id="OnceUpon" class="spring.Story">
      <property name="title">
         <value>Once Upon a Time</value>
      </property>
      <property name="author">
         <value>Rob Yates</value>
      </property>
      <property name="content">
         <value>Once upon a time there were some interesting things going on.
The end.</value>
      </property>
   </bean>
</beans>

前两行只是标准的 XML 声明。从技术上讲,我们并不真正需要它们,但无论如何我们会把它们放在这里。接下来,您会看到 <beans> 标签,这是所有 Java bean 的存放位置。

在它下面您会看到 <bean class="spring.StoryList">。这将是我们 Java 类 StoryList.java(位于 spring 包中)的 bean。这个类只是一个 List 的占位符,我们将在这里存放我们的故事。请注意 bean 元素的属性:必须始终有一个类属性来表示 bean 使用的 Java 类。id 属性是可选的;它由 XMLBeanFactory 类使用,来告诉它使用 getBean 方法获取哪个 bean:例如,getBean("这里是我的 id 属性名称")。如果没有提供 ID 属性,例如 <bean class="StoryList">,则类名将被用作它的 id 属性。想象一下:<bean id="StoryList" class="spring.StoryList">。还要注意,bean 的 id 值不能包含任何空格,例如,不要写 id="Story List"

接下来我们有 <property name="stories">。property 标签只是指定我们要用 bean 属性指定 Java bean 文件中的哪个属性变量。<list> 标签接下来用于告诉 Spring 我们正在处理一个 List 的东西,而不是仅仅一个东西。接下来我们有 <ref bean="HelloWorld"/>,它告诉 Spring 返回此 List 中的 <bean id="HelloWorld" class="spring.Story"> bean。在另一个示例中,您可能只需要一个值的列表,例如 String。对于购物清单,您可能会有类似以下的内容,

<list>
	<value>milk</value>
	<value>eggs</value>
	<value>bread</value>
</list>

无论哪种方式,您的属性都映射到一个 LIST

对于我们的 HelloWorld 故事,我们有 <bean id="HelloWorld" class="spring.Story">。希望这没什么太奇怪的。此 bean 有三个属性,<property name="title"><property name="author"><property name="content">。这些再次映射到属性变量:Story 类中的 title、author 和 content。在每个值中我们有:<value>Hello World!</value>、<value>User:Hyad</value>、<value>这是一个简单的故事。

这是一个关于一个男人说“你好,世界”的故事。

看吧,现在是不是很简单?</value>由于我们正在处理 String,因此开始和结束 value 标签之间的所有内容都被转换为 String。因此,要添加一个换行符,我们实际上必须将文本放在单独的行上,并且没有任何缩进。请注意,值不必映射到 String,它们可以是基本类型(如 int 或 char),也可以是对象(如 Integer 或 Float)。Spring 会自动知道如何转换它们。

我们不会介绍 OnceUpon bean,它基本上与 HelloWorld 相同,只是值不同。事实上,这就是使用 Spring 的主要目的,将 Java 类的不同值集存储为 bean,而不是创建一个新类。接下来是 Java Bean 类本身。

步骤 3:制作 JavaBean 类

[编辑 | 编辑源代码]

有两个 JavaBean 类:Story.javaStoryList.java,它们都在 spring 包中。将以下文本复制粘贴到各自的类中。

Story.java

[编辑 | 编辑源代码]
package spring;

public class Story {
	
	private String title;
	private String author;
	private String content;
	
	public Story () {
	}	
	public void setTitle(String title) {
		this.title = title;
	}
	public String getTitle() {
		return title;
	}
	public void setAuthor(String author) {
		this.author = author;
	}
	public String getAuthor() {
		return author;
	}
	public void setContent(String content) {
		this.content = content;
	}
	public String getContent() {
		return content;
	}
}

StoryList.java

[编辑 | 编辑源代码]
package spring;

import java.util.List;

public class StoryList {

	private List stories;
	
	public StoryList (){
	}
	public void setStories(List stories) {
		this.stories = stories;
	}
	public List getStories() {
		return stories;
	}
}

并不太复杂,对吧?这些是 JavaBean;简单的类,具有用于属性变量的 getter 和 setter,以及一个没有参数的构造函数。有关 JavaBean 的更深入讨论,请访问维基百科:JavaBeans。setter,如 setTitle(String title),是 Spring 用于在 XmlBeanFactory 中创建 bean 的内容。setter 必须遵循特定的 bean 命名约定。例如,settitle(String title)(使用小写的“t”)将不起作用。但是,作为示例,setURL(String url)(使用属性名称“URL”)将起作用,因为除了第一个“U”之外,第二个字母“R”也大写了。Spring 在此示例中实际上没有使用 getter,但是 StoryReader 需要它们,我们将在后面看到。此外,我们实际上不必指定一个无参数构造函数,我们可以将其省略,Java 编译器在编译时会自动将一个放到类中。但是,在没有无参数构造函数的情况下编写一个具有一个或多个参数的构造函数将使该类不再是一个 bean。

步骤 4:一个将所有内容组合在一起的 main 方法

[编辑 | 编辑源代码]

与之前一样,复制粘贴文本。并将您的类保存为 StoryReader.java

StoryReader.java

[编辑 | 编辑源代码]
package spring;

import java.util.List;

import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
 
public class StoryReader {
 
	public static void main(String args[]) {
		ClassPathXmlApplicationContext springApplicationContext = new ClassPathXmlApplicationContext("story_configuration.xml");
 
		StoryList storyList = (StoryList) springApplicationContext.getBean("StoryList");
 
		List myStories = storyList.getStories();
 
		for (int i = 0; i < myStories.size(); i++) {
			Story currentStory = (Story) myStories.get(i);
			System.out.println("\"" + currentStory.getTitle() + "\" by "
					+ currentStory.getAuthor() + ":");
			System.out.println(currentStory.getContent());
			System.out.println();
		}
	}//end main
 
}//end StoryReader

这是我们的主类,StoryReader.java,位于spring包中。首先,我们需要导入两个Spring类:XmlBeanFactoryClassPathResourceXmlBeanFactory本质上是Spring XML配置文件story_configuration.xml的Java类表示。但是,在我们获取XML文件之前,我们必须告诉Spring在我们的类路径中查找该文件。这就是ClassPathResource的作用。它会在类路径中搜索指定的story_configuration.xml文件,而我们的.class文件就存储在类路径中。任何其他实现了Resource接口的类都可以使用,比如org.springframework.core.io.FileSystemResource。因此,我们可以看到XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("story_configuration.xml"));story_configuration.xml创建一个新的bean工厂。

下一行,StoryList storyList = (StoryList) beanFactory.getBean("StoryList");,告诉我们接下来要获取哪个bean。getBean("StoryList")告诉bean工厂返回一个对应于id为“StoryList”的bean的对象,因为它是类名。由于它是一个Object,所以我们必须将其强制转换为StoryList类。

接下来,我们从StoryList类中获取故事列表,并遍历它们。由于这是一个bean,故事已经存在于列表中,在故事中已经存在的数值中。我们只需要将它们打印出来;这就是我们所做的。注意:\"用于转义字符串中的引号。

步骤 5:运行程序

[编辑 | 编辑源代码]

现在我们已经完成了类的创建和文件的创建,让我们运行程序!通过确保你正确地复制了所有内容来修复你遇到的任何错误。当你运行StoryReader的主方法时,你的输出应该如下所示

Mar 12, 2006 5:42:30 PM org.springframework.core.CollectionFactory <clinit>
INFO: JDK 1.4+ collections available
Mar 12, 2006 5:42:30 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [story_configuration.xml]
"Hello World!" by User:Hyad:
This is a simple story.
This is a story about a man who said, "Hello, World."
See, now wasn't that simple.

"Once Upon a Time" by Rob Yates:
Once upon a time there were some interesting things going on.
The end.

当你自己运行它时,日期显然会不同。此外,以日期或“INFO”开头的四行会打印到System.err中,可能出现在其他输出的上面、下面,甚至中间。这是因为一些操作系统可能在不同的时间打印到System.outSystem.err。请检查你的输出是否与显示的输出匹配,忽略Spring打印的四行的日期和顺序。现在,你已经拥有了一个功能完善的Spring应用程序,接下来呢?

需要记住的事项

[编辑 | 编辑源代码]

正如我之前提到的,Spring会自动将值转换为基本类型和对象;intfloatcharDoublebooleanByte等等。还要注意,<list>(只是一个值列表)可以映射到List对象、Array对象或基本类型数组(双方括号类型)。甚至还有<set><map>标签,可以分别映射到SetMap。并且,你可以随时用对bean的引用替换值,比如用<ref bean="myBeanId"/>替换<value>myValue</value>。这个引用将返回相应的JavaBean,Spring会将其存储为该变量。

此外,Spring还可以替代属性文件。它的优势在于Spring是基于XML的,因此任何XML解析器都可以读取它。同一个文件中可以存储同一类的多个bean。但是,你也可以将bean放置在多个文件中,并使用<import resource="myOtherBeanConfigFile.xml"/>“导入”其他bean,就像导入Java类一样。

最后,你可能还想了解的是,当你使用一个bean来引用其他bean、类、文件等等时,Spring最有帮助。你可能有一个bean包含一个bean列表,该列表包含一个bean列表,每个bean列表又包含另一个bean列表,……这样,只有最顶层bean的文件名和位置在Java类中“硬编码”,而其他所有内容都由XML配置文件指定。

自己尝试

[编辑 | 编辑源代码]

以下是一些可以使你的Spring应用程序更健壮的任务。你可以根据自己的喜好完成其中的一些或所有任务。

  • StoryList bean分离到另一个XML文件中,在新文件中使用<import resource="story_configuration.xml"/>
  • 为每个故事添加发布时间。你将如何存储日期?
  • 为作者创建一个单独的类。作者可能有哪些属性?
  • StoryList中添加额外的功能。如何添加一个可以由StoryReader的主方法调用的printStories()方法?
  • 创建一个写入器,以便所有输出都写入文件。并将该文件名存储为一个bean。
  • 添加更多故事。(我知道我的故事很烂。)
  • 除了故事之外,还可以添加电视剧或电子游戏吗?
  • 修改一些随机代码,直到它崩溃。玩得开心!:)

关于作者

[编辑 | 编辑源代码]

我在维基百科和维基教科书上被称为User:Hyad。因为其他Spring教程太长了,让我感到沮丧,所以我决定在工作中真正学习(和使用)Spring之后,自己创建自己的教程。这个教程最接近我在一个好的教程中寻找的东西,但它有点太短了。所以我想,为什么不举一个可以在现实世界中使用的例子呢?我认为维基教科书是发布它的最佳场所,因为如果我将它发布在我的网站上,1. 它将难以编辑,2. 其他用户将无法轻松地编辑和更新它。所以,请在我的维基百科讨论页面上给我留言,告诉我你的想法。

参考资料

[编辑 | 编辑源代码]
  1. Spring Boot 参考指南。 "构建系统".
华夏公益教科书