ZetCode-Spring-教程-一-
ZetCode Spring 教程(一)
原文:ZetCode
Spring @RequestHeader
教程
Spring @RequestHeader
教程展示了如何使用@RequestHeader
注解将方法参数绑定到请求标头。
Spring 是用于创建企业应用的流行 Java 应用框架。
Spring @RequestHeader
@RequestHeader
注解将请求标头值绑定到方法参数。 如果方法参数为Map
,MultiValueMap<String, String>
或HttpHeaders
,则将使用所有标头名称和值填充映射。
Spring @RequestHeader
示例
该应用将请求正文标头绑定到方法参数。 使用curl
工具创建请求。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ ├───config
│ │ │ MyWebInitializer.java
│ │ │ WebConfig.java
│ │ └───controller
│ │ MyController.java
│ └───resources
│ logback.xml
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>springrequestheader</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.14.v20181114</version>
</plugin>
</plugins>
</build>
</project>
我们在pom.xml
中声明必要的依赖关系。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
@Configuration
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
MyWebInitializer
注册 Spring DispatcherServlet
,它是 Spring Web 应用的前端控制器。
com/zetcode/config/WebConfig.java
package com.zetcode.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.zetcode"})
public class WebConfig implements WebMvcConfigurer {
}
WebConfig
通过@EnableWebMvc
启用 Spring MVC 注解,并为com.zetcode
包配置组件扫描。
com/zetcode/controller/MyController.java
package com.zetcode.controller;
package com.zetcode.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
public class MyController {
private static final Logger logger = LoggerFactory.getLogger(MyController.class);
@GetMapping(value = "/agent")
@ResponseStatus(value = HttpStatus.OK)
public void client(@RequestHeader(value="User-Agent") String userAgent) {
logger.info("User agent is: {}", userAgent);
}
@GetMapping(value = "/all")
@ResponseStatus(value = HttpStatus.OK)
public void all(@RequestHeader Map<String, String> headers) {
logger.info("All headers: {}", headers);
}
}
我们有两个映射。 第一个映射确定用户代理,第二个映射找出所有发送的请求标头。
public void client(@RequestHeader(value="User-Agent") String userAgent) {
使用@RequestHeader
的 value 参数,我们查找特定的标头; 在我们的例子中是User-Agent
。
public void all(@RequestHeader Map<String, String> headers) {
提供映射时,我们会检索所有标头。
$ mvn jetty:run
我们启动服务器。
$ curl localhost:8080/agent
我们创建对第一个映射的请求。
08:26:29.926 INFO com.zetcode.controller.MyController - User agent is: curl/7.55.1
我们得到这个日志。
$ curl localhost:8080/all
我们调用第二个映射。
08:27:26.564 INFO com.zetcode.controller.MyController - All headers: {User-Agent=curl/7.55.1, Accept=*/*, Host=localhost:8080}
我们记录了三个标头。
在本教程中,我们使用@RequestHeader
注解将请求标头绑定到方法参数。
您可能也对这些相关教程感兴趣: Spring @GetMapping 教程, Spring @RequestBody 教程, Java 教程或列出所有 Spring 教程。
Spring Cookies 教程
Spring Cookies 教程展示了如何在 Spring 应用中使用 Cookie。 使用@CookieValue
注解读取 Cookie。
Spring 是用于创建企业应用的流行 Java 应用框架。
Cookies
Cookie 是服务器发送到用户的 Web 浏览器的一小段数据。 浏览器可以存储它,并将其与下一个请求一起发送回同一服务器。
Cookies 主要用于会话管理,个性化和跟踪。
@CookieValue
@CookieValue
是一个注解,指示方法参数应绑定到 HTTP cookie。
HttpCookie
HttpCookie
将 HTTP cookie 表示为与"Cookie"
请求标头的内容一致的名称/值对。 ResponseCookie
子类具有"Set-Cookie"
响应标题中预期的其他属性。
Spring Cookie 的例子
以下示例创建一个写入和读取 Cookie 的 Spring Web 应用。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ ├───config
│ │ │ MyWebInitializer.java
│ │ │ WebConfig.java
│ │ └───controller
│ │ MyController.java
│ └───resources
│ logback.xml
└───test
└───java
这是 Spring 应用的项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>cookiesex</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.14.v20181114</version>
</plugin>
</plugins>
</build>
</project>
我们声明项目依赖项。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
@Configuration
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
DispatcherServlet
是 Spring Web 应用的前端控制器,已注册在MyWebInitializer
中。
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
getServletConfigClasses()
返回 Web 配置类。
com/zetcode/config/WebConfig.java
package com.zetcode.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.zetcode"})
public class WebConfig {
}
WebConfig
通过@EnableWebMvc
启用 Spring MVC 注解,并为com.zetcode
包配置组件扫描。
com/zetcode/MyController.java
package com.zetcode.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseCookie;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
private static final Logger logger = LoggerFactory.getLogger(MyController.class);
@ResponseStatus(value = HttpStatus.OK)
@GetMapping(value = "/readCookie")
public void readCookie(@CookieValue(value = "fav-col",
defaultValue = "unknown") String favColour) {
logger.info("Favourite colour: {}", favColour);
}
@ResponseStatus(value = HttpStatus.OK)
@GetMapping(value = "/writeCookie")
public ResponseEntity writeCookie() {
var favColour = "steelblue";
var cookie = ResponseCookie.from("fav-col", favColour).build();
return ResponseEntity.ok()
.header(HttpHeaders.SET_COOKIE, cookie.toString())
.build();
}
}
我们有两个 GET 映射。 第一个映射读取一个 cookie,第二个映射写入一个 cookie。
public void readCookie(@CookieValue(value = "fav-col",
defaultValue = "unknown") String favColour) {
我们使用@CookieValue
读取 Cookie 值。 如果未设置 cookie 或过期,则为默认值。
var favColour = "steelblue";
var cookie = ResponseCookie.from("fav-col", favColour).build();
return ResponseEntity.ok()
.header(HttpHeaders.SET_COOKIE, cookie.toString())
.build();
我们使用ResponseCookie
创建一个 cookie,并将其设置为响应头。
$ mvn jetty:run
我们启动 Jetty 服务器。 现在,首先将浏览器定位到localhost:8080/writeCookie
,然后通过导航到localhost:8080/readCookie
来读取 cookie。
在本教程中,我们在 Spring 中使用 cookie。 您可能也对相关教程感兴趣: Spring @RequestMapping
教程, Spring @RequestHeader
教程, Java 教程或列出所有 Spring 教程。
Spring 资源教程
Spring Resource
教程展示了如何使用Resource
在 Spring 应用中使用各种资源。
Spring 是用于创建企业应用的流行 Java 应用框架。
Spring 资源
Resource
从基础资源的实际类型中抽象出来,例如文件或类路径资源。 它可以用来标识本地或远程资源。
Spring ApplicationContext
包含getResource()
方法,该方法返回指定资源类型的资源句柄。 它可以是类路径,文件或 URL 资源。
Spring 资源示例
该应用使用 Spring 的Resource
来读取本地文件和远程网页。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ │ Application.java
│ │ └───service
│ │ MyService.java
│ └───resources
│ logback.xml
│ words.txt
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>resourceex</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.zetcode.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有基本的 Spring 依赖项spring-core
,spring-context
和日志记录logback-classic
依赖项。
exec-maven-plugin
用于在命令行上从 Maven 执行 Spring 应用。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
resources/words.txt
clean
sky
forest
blue
crystal
cloud
river
words.txt
文件包含几个单词。
com/zetcode/MyService.java
package com.zetcode.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
@Service
public class MyService {
private static final Logger logger = LoggerFactory.getLogger(MyService.class);
@Autowired
private ApplicationContext ctx;
public void readWebPage() {
var res = ctx.getResource("http://webcode.me");
try (var is = new InputStreamReader(res.getInputStream());
var bis = new BufferedReader(is)) {
bis.lines().forEach(System.out::println);
} catch (IOException ex) {
logger.warn("{}", ex);
}
}
public void readFile() {
// var res = ctx.getResource("file:C:/Users/Jano/Documents/words.txt");
var res = ctx.getResource("classpath:words.txt");
try (var is = new InputStreamReader(res.getInputStream());
var bis = new BufferedReader(is)) {
bis.lines().forEach(System.out::println);
} catch (IOException ex) {
logger.warn("{}", ex);
}
}
}
MyService
有两种读取网页和本地文本文件的方法。
@Autowired
private ApplicationContext ctx;
我们注入ApplicationContext
。 我们使用其getResource()
方法来获取资源处理器。
var res = ctx.getResource("http://webcode.me");
我们从网页上获得了Resource
。
// var res = ctx.getResource("file:C:/Users/Jano/Documents/words.txt");
var res = ctx.getResource("classpath:words.txt");
我们可以从绝对文件路径或类路径获取Resource
。
com/zetcode/Application.java
package com.zetcode;
import com.zetcode.service.MyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackages = "com.zetcode")
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
@Autowired
private MyService myService;
public static void main(String[] args) {
var ctx = new AnnotationConfigApplicationContext(Application.class);
var app = ctx.getBean(Application.class);
app.run();
ctx.close();
}
public void run() {
myService.readWebPage();
myService.readFile();
}
}
这是主要的应用类。
@Autowired
private MyService myService;
使用@Autowired
将服务 bean 注入到类中。
myService.readWebPage();
myService.readFile();
我们称为myService
方法。
在本教程中,我们展示了如何使用Resource
来读取本地文本文件和网页。
您可能也对这些相关教程感兴趣: Spring @Qualifier
注解教程, Spring 单例范围 bean , Spring C-命名空间教程, Spring BeanDefinitionBuilder
教程, Spring bean 引用教程和 Java 教程。
Spring 重定向教程
Spring 重定向教程展示了如何在 Spring Web 应用中重定向请求。
Spring 是用于创建企业应用的流行 Java 应用框架。
重定向
视图名称中的特殊redirect:
前缀将重定向到其他 URL。 最终效果与控制器已返回RedirectView
的效果相同。 重定向应用于发布/重定向/获取(PRG)场景; PGR 是一种 Web 开发设计模式,可防止重复提交表单。 默认情况下,发送状态代码 302。 如果要更改,可以使用@ResponseStatus
注解处理器方法的返回类型。
RedirectAttributes
是Model
接口的一种特殊化,控制器可以用来选择重定向方案的属性。
重定向与转发
基本上可以通过三种方式处理请求:a)由 Spring 在控制器动作中解决,b)转发至其他控制器动作,c)重定向至客户端以获取另一个 URL。
向前:
- 由 Spring 内部执行
- 浏览器完全不知道转发,因此其原始 URL 保持不变
- 浏览器重新加载结果页面会重复原始请求,并带有原始 URL
- 请求中发送的数据可用于转发的操作
重定向:
- 是一个两步过程
- Spring 指示浏览器获取另一个 URL,该 URL 与原始 URL 不同
- 浏览器重新加载第二个 URL 不会重复原始请求,而是获取第二个 URL
- 在原始请求范围内发送的数据不适用于第二个请求
Spring 重定向示例
提交表单后,以下应用使用重定向到其他 URL。 它使用redirect:
前缀执行重定向。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ ├───bean
│ │ │ User.java
│ │ ├───config
│ │ │ MyWebInitializer.java
│ │ │ WebConfig.java
│ │ └───controller
│ │ MyController.java
│ └───resources
│ │ logback.xml
│ │
│ └───templates
│ addUser.html
│ showUserAdded.html
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>springredirectex</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.14.v20181114</version>
</plugin>
</plugins>
</build>
</project>
在pom.xml
中,我们具有必要的依赖项。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
@Configuration
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
MyWebInitializer
注册 Spring DispatcherServlet
,它是 Spring Web 应用的前端控制器。
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
getServletConfigClasses()
返回 Web 配置类。
com/zetcode/config/WebConfig.java
package com.zetcode.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.zetcode"})
public class WebConfig implements WebMvcConfigurer {
@Autowired
private ApplicationContext applicationContext;
@Bean
public SpringResourceTemplateResolver templateResolver() {
var templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix("classpath:/templates/");
templateResolver.setSuffix(".html");
return templateResolver;
}
@Bean
public SpringTemplateEngine templateEngine() {
var templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
@Bean
public ViewResolver viewResolver() {
var resolver = new ThymeleafViewResolver();
var registry = new ViewResolverRegistry(null, applicationContext);
resolver.setTemplateEngine(templateEngine());
registry.viewResolver(resolver);
return resolver;
}
}
WebConfig
配置 Thymeleaf 模板引擎。 我们将模板文件的位置设置为classpath
上的templates
目录。 (resources
在类路径上。)
com/zetcode/bean/User.java
package com.zetcode.bean;
public class User {
private String name;
private String occupation;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getOccupation() {
return occupation;
}
public void setOccupation(String occupation) {
this.occupation = occupation;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("User{");
sb.append("name='").append(name).append('\'');
sb.append(", occupation='").append(occupation).append('\'');
sb.append('}');
return sb.toString();
}
}
这是User
bean。 它填充有来自表单的数据。
com/zetcode/controller/MyController.java
package com.zetcode.controller;
import com.zetcode.bean.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
@Controller
public class MyController {
private static final Logger logger = LoggerFactory.getLogger(MyController.class);
@GetMapping("/addUser")
public String sendForm(User user) {
return "addUser";
}
@PostMapping("/addUser")
public String processForm(User user, RedirectAttributes redirectAttrs) {
logger.info("User {} has been saved", user.getName());
redirectAttrs.addAttribute("name", user.getName());
return "redirect:userAdded";
}
@GetMapping("/userAdded")
public String userAdded() {
return "showUserAdded";
}
}
MyController
提供请求路径和处理器方法之间的映射。
@GetMapping("/addUser")
public String sendForm(User user) {
return "addUser";
}
该映射将表单发送给用户。
@PostMapping("/addUser")
public String processForm(User user, RedirectAttributes redirectAttrs) {
logger.info("User {} has been saved", user.getName());
redirectAttrs.addAttribute("name", user.getName());
return "redirect:userAdded";
}
此映射处理表单。 新用户被“保存”并执行重定向。 用户名通过addAttribute()
添加到重定向属性中。
resources/templates/addUser.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Add user</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h1>Add User</h1>
<form action="#" th:action="@{/addUser}" th:object="${user}" method="post">
<p>
Name: <input type="text" th:field="*{name}">
</p>
<p>
Occupation: <input type="text" th:field="*{occupation}">
</p>
<p>
<input type="submit" value="Submit"/> <input type="reset" value="Reset">
</p>
</form>
</body>
</html>
addUser.html
模板向用户提供表格。 输入的字段将自动插入到User's
属性中。
resources/templates/showUserAdded.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>User saved</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h2>User has been saved</h2>
<p th:text="'Name: ' + ${#request.getParameter('name')}"></p>
<a href="/addUser">Add another user</a>
</body>
</html>
提交表单后,此模板向用户显示一条消息。 它使用${#request.getParameter('name')}
读取redirect
属性。
$ mvn jetty:run
我们运行服务器并找到localhost:8080/addUser
。
在本教程中,我们在 Spring 控制器中执行了重定向。
您可能也对这些相关教程感兴趣: Spring 转发教程, Java 教程或列出所有 Spring 教程。
Spring 转发教程
Spring 转发教程展示了如何在 Spring Web 应用中转发请求。
Spring 是用于创建企业应用的流行 Java 应用框架。
转发
视图名称中的特殊forward:
前缀将转发到其他 URL。 转发 URL 可在同一服务器内部内部传输请求,而无需涉及客户端浏览器。 转发的执行频率少于重定向。
重定向与转发
基本上可以通过三种方式处理请求:a)由 Spring 在控制器动作中解决,b)转发至其他控制器动作,c)重定向至客户端以获取另一个 URL。
向前:
- 由 Spring 内部执行
- 浏览器完全不知道转发,因此其原始 URL 保持不变
- 浏览器重新加载结果页面会重复原始请求,并带有原始 URL
- 请求中发送的数据可用于转发的操作
重定向:
- 是一个两步过程
- Spring 指示浏览器获取另一个 URL,该 URL 与原始 URL 不同
- 浏览器重新加载第二个 URL 不会重复原始请求,而是获取第二个 URL
- 在原始请求范围内发送的数据不适用于第二个请求
Spring 转发的例子
提交表单后,以下应用使用转发到其他 URL。 它执行带有forward:
前缀的转发。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ ├───config
│ │ │ MyWebInitializer.java
│ │ │ WebConfig.java
│ │ └───controller
│ │ MyController.java
│ └───resources
│ │ logback.xml
│ │
│ └───templates
│ show.ftl
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>springforwardex</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.14.v20181114</version>
</plugin>
</plugins>
</build>
</project>
在pom.xml
中,我们具有必要的依赖项。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
@Configuration
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
MyWebInitializer
注册 Spring DispatcherServlet
,它是 Spring Web 应用的前端控制器。
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
getServletConfigClasses()
返回 Web 配置类。
com/zetcode/config/WebConfig.java
package com.zetcode.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.zetcode"})
public class WebConfig implements WebMvcConfigurer {
@Bean
public FreeMarkerViewResolver freemarkerViewResolver() {
var resolver = new FreeMarkerViewResolver();
resolver.setCache(true);
resolver.setSuffix(".ftl");
return resolver;
}
@Bean
public FreeMarkerConfigurer freemarkerConfig() {
var freeMarkerConfigurer = new FreeMarkerConfigurer();
freeMarkerConfigurer.setTemplateLoaderPath("classpath:/templates/");
return freeMarkerConfigurer;
}
}
WebConfig
配置 Freemarker。 我们将模板文件的位置设置为classpath
上的templates
目录。 (resources
在类路径上。)
com/zetcode/controller/MyController.java
package com.zetcode.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class MyController {
private static final Logger logger = LoggerFactory.getLogger(MyController.class);
@GetMapping(value = "/sendname")
public String send(@RequestParam(defaultValue = "guest") String name, Model model) {
logger.info("sendname called");
model.addAttribute("name", name);
return "forward:/newpage";
}
@GetMapping(value = "/newpage")
public String newpage() {
logger.info("newpage called");
return "show";
}
}
MyController
提供了两个 GET 映射。
@GetMapping(value = "/sendname")
public String send(@RequestParam(defaultValue = "guest") String name, Model model) {
logger.info("send name called");
model.addAttribute("name", name);
return "forward:/newpage";
}
的请求发送至/sendname
由send()
操作处理。 读取请求参数并将其添加到模型。 最后,它被转发到新的控制器操作。
@GetMapping(value = "/newpage")
public String newpage() {
logger.info("newpage called");
return "show";
}
newpage()
操作将请求解析为show
视图。
resources/templates/show.ftl
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Show</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<p>
User name: ${name}
</p>
</body>
</html>
show.ftl
显示用户名。
$ mvn jetty:run
我们运行服务器并找到localhost:8080/sendname?name=Peter
。
09:52:11.636 INFO com.zetcode.controller.MyController - sendname called
09:52:11.653 INFO com.zetcode.controller.MyController - newpage called
服务器日志包含这些行。
在本教程中,我们在 Spring 控制器中执行了正向操作。
您可能也对这些相关教程感兴趣: Spring 重定向教程, Java 教程或列出所有 Spring 教程。
Spring ModelAndView
教程
Spring ModelAndView
教程展示了如何在 Spring Web 应用的控制器中使用ModelAndView
。
Spring 是用于创建企业应用的流行 Java 应用框架。
ModelAndView
ModelAndView
是 Web MVC 框架中Model
和View
的持有者。 这两类是截然不同的。 ModelAndView
仅保留两者,以使控制器有可能在单个返回值中返回模型和视图。
该视图由ViewResolver
对象解析; 该模型是存储在Map
中的数据。
Spring ModelAndView
示例
以下应用使用ModelAndView
在 Spring 控制器中一步返回模型和视图。 我们使用 Freemarker 进行视图解析。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ ├───config
│ │ │ MyWebInitializer.java
│ │ │ WebConfig.java
│ │ └───controller
│ │ MyController.java
│ └───resources
│ │ logback.xml
│ └───templates
│ index.ftl
│ show.ftl
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>springmodelandview</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.14.v20181114</version>
</plugin>
</plugins>
</build>
</project>
在pom.xml
中,我们具有必要的依赖项。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
@Configuration
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
MyWebInitializer
注册 Spring DispatcherServlet
,它是 Spring Web 应用的前端控制器。
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
getServletConfigClasses()
返回 Web 配置类。
com/zetcode/config/WebConfig.java
package com.zetcode.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.zetcode"})
public class WebConfig implements WebMvcConfigurer {
@Bean
public FreeMarkerViewResolver freemarkerViewResolver() {
var resolver = new FreeMarkerViewResolver();
resolver.setCache(true);
resolver.setSuffix(".ftl");
return resolver;
}
@Bean
public FreeMarkerConfigurer freemarkerConfig() {
var freeMarkerConfigurer = new FreeMarkerConfigurer();
freeMarkerConfigurer.setTemplateLoaderPath("classpath:/templates/");
return freeMarkerConfigurer;
}
}
WebConfig
配置 FreeMarker 模板引擎。 我们将模板文件的位置设置为classpath
上的templates
目录。 (resources
在类路径上。)
com/zetcode/controller/MyController.java
package com.zetcode.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Controller
public class MyController {
@GetMapping(value = "/")
public String home() {
return "index";
}
@GetMapping(value = "/show")
public ModelAndView show() {
var mav = new ModelAndView();
var now = LocalDateTime.now();
var formatter = DateTimeFormatter.ISO_DATE_TIME;
var dateTimeFormatted = formatter.format(now);
mav.addObject("now", dateTimeFormatted);
mav.setViewName("show");
return mav;
}
}
MyController
提供了两个 GET 映射。
@GetMapping(value = "/show")
public ModelAndView show() {
show()
方法返回ModelAndView
。
var mav = new ModelAndView();
var now = LocalDateTime.now();
var formatter = DateTimeFormatter.ISO_DATE_TIME;
var dateTimeFormatted = formatter.format(now);
mav.addObject("now", dateTimeFormatted);
mav.setViewName("show");
return mav;
创建一个ModelAndView
并填充数据。 数据是格式化的日期时间对象。 视图名称由setViewName()
设置。 Spring 将视图名称解析为show.ftl
。
resources/templates/index.ftl
<!DOCTYPE html>
<html>
<head>
<title>Home</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<p>
<a href="show">Show today's datetime</a>
</p>
</body>
</html>
主页包含一个链接,以显示今天的日期时间。
resources/templates/show.ftl
<!DOCTYPE html>
<html>
<head>
<title>Today's date</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<p>
Today is: ${now}
</p>
</body>
</html>
在show.ftl
视图中,我们使用${}
语法显示当前日期时间。
$ mvn jetty:run
我们运行服务器并找到localhost:8080
以获取具有链接的主页。
在本教程中,我们使用ModelAndView
来组织模型和视图。
您可能也对这些相关教程感兴趣: Spring @Configuration
教程, Spring @GetMapping
教程, Java 教程或列出所有 Spring 教程。
Spring MessageSource
教程
Spring MessageSource
教程展示了如何在 Spring 应用中使用MessageSource
转换消息。
Spring 是用于创建企业应用的流行 Java 应用框架。
Spring MessageSource
MessageSource
用于解析消息,并支持消息的参数化和国际化。 Spring 包含两个内置的MessageSource
实现:ResourceBundleMessageSource
和ReloadableResourceBundleMessageSource
。 后者能够重新加载消息定义,而无需重新启动虚拟机。
Spring MessageSource
示例
以下应用包含英语和德语消息。 它使用内置的ResourceBundleMessageSource
。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ │ Application.java
│ │ └───config
│ │ AppConfig.java
│ └───resources
│ │ logback.xml
│ └───messages
│ label.properties
│ label_de.properties
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>messagesource</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.zetcode.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有基本的 Spring 依赖项spring-core
,spring-context
和日志记录logback-classic
依赖项。
exec-maven-plugin
用于在命令行上从 Maven 执行 Spring 应用。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
resources/messages/labels.properties
l1=Earth
l2=Hello {0}, how are you?
这些是英文信息。 第二个属性接收一个参数。
resources/messages/labels_de.properties
l1=Erde
l2=Hallo {0}, wie geht's?
这些是德语信息。
com/zetcode/config/AppConfig.java
package com.zetcode.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
@Configuration
public class AppConfig {
@Bean
public ResourceBundleMessageSource messageSource() {
var source = new ResourceBundleMessageSource();
source.setBasenames("messages/label");
source.setUseCodeAsDefaultMessage(true);
return source;
}
}
AppConfig
配置ResourceBundleMessageSource
。 setBasenames()
告诉在哪里查找消息定义。
com/zetcode/Application.java
package com.zetcode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import java.util.Locale;
@ComponentScan(basePackages = "com.zetcode")
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
@Autowired
private MessageSource messageSource;
public static void main(String[] args) {
var ctx = new AnnotationConfigApplicationContext(Application.class);
var app = ctx.getBean(Application.class);
app.run();
ctx.close();
}
public void run() {
logger.info("Translated messages:");
logger.info("{}", messageSource.getMessage("l1",
null, Locale.GERMAN));
logger.info("{}", messageSource.getMessage("l1",
null, Locale.ENGLISH));
logger.info("Translated parameterized messages:");
logger.info("{}", messageSource.getMessage("l2",
new Object[] {"Paul Smith"}, Locale.GERMAN));
logger.info("{}", messageSource.getMessage("l2",
new Object[] {"Paul Smith"}, Locale.ENGLISH));
}
}
该应用将普通消息和参数化消息打印到控制台。
@Autowired
private MessageSource messageSource;
我们注入在AppConfig
中生成的MessageSource
。
logger.info("{}", messageSource.getMessage("l1",
null, Locale.GERMAN));
getMessage()
将属性名称作为第一个参数。 第二个参数是null
,因为消息没有任何参数。 第三个参数是语言环境。
logger.info("{}", messageSource.getMessage("l2",
new Object[] {"Paul Smith"}, Locale.GERMAN));
在这里,我们还为消息提供了一个参数。
$ mvn -q exec:java
22:08:27.984 INFO com.zetcode.Application - Translated messages:
22:08:27.984 INFO com.zetcode.Application - Erde
22:08:27.984 INFO com.zetcode.Application - Earth
22:08:27.984 INFO com.zetcode.Application - Translated parameterized messages:
22:08:27.984 INFO com.zetcode.Application - Hallo Paul Smith, wie gehts?
22:08:27.984 INFO com.zetcode.Application - Hello Paul Smith, how are you?
我们运行该应用。
在本教程中,我们展示了如何在 Spring 应用中使用ResourceBundleMessageSource
。
您可能也对这些相关教程感兴趣: Java ResourceBundle
教程, Spring @ComponentScan
教程, Java 教程或列出所有 Spring 教程。
Spring AnnotationConfigApplicationContext
http://zetcode.com/spring/annotationconfigapplicationcontext/
Spring AnnotationConfigApplicationContext
教程展示了如何在 Spring 应用中使用AnnotationConfigApplicationContext
。
Spring 是流行的 Java 应用框架。
AnnotationConfigApplicationContext
AnnotationConfigApplicationContext
是一个独立的应用上下文,它接受带注解的类作为输入。 例如@Configuration
或@Component
。 可以使用scan()
查找 Bean,也可以使用register()
注册 Bean。
Spring AnnotationConfigApplicationContext
示例
以下示例使用AnnotationConfigApplicationContext
来构建独立的 Spring 应用。 它有一个 Spring bean DateTimeService
,位于scan()
中。
pom.mxl
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ │ Application.java
│ │ └───bean
│ │ DateTimeService.java
│ └───resources
│ logback.xml
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>annotappctx</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.zetcode.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
这是我们 Spring 应用的 Maven 构建文件。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
这是 Logback 配置文件。
com/zetcode/bean/DateTimeService.java
package com.zetcode.bean;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
@Service
public class DateTimeService {
public LocalDate getDate() {
return LocalDate.now();
}
public LocalTime getTime() {
return LocalTime.now();
}
public LocalDateTime getDateTime() {
return LocalDateTime.now();
}
}
DateTimeService
是提供数据和时间服务的服务类。 它以@Service
构造型装饰,这使它在扫描过程中被检测到。
com/zetcode/Application.java
package com.zetcode;
import com.zetcode.bean.DateTimeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;
@Component
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
@Autowired
private DateTimeService dateTimeService;
public static void main(String[] args) {
var ctx = new AnnotationConfigApplicationContext();
ctx.scan("com.zetcode");
ctx.refresh();
var bean = ctx.getBean(Application.class);
bean.run();
ctx.close();
}
public void run() {
logger.info("Current time: {}", dateTimeService.getTime());
logger.info("Current date: {}", dateTimeService.getDate());
logger.info("Current datetime: {}", dateTimeService.getDateTime());
}
}
我们设置了应用并注入了DateTimeService
。 我们称这三种服务方法。
@Component
public class Application {
Application
也是用原型装饰,这次是@Component
。 Spring 也会检测到它。 我们需要调用其run()
方法以超出静态上下文。
@Autowired
private DateTimeService dateTimeService;
服务类注入@Autowired
。
var ctx = new AnnotationConfigApplicationContext();
ctx.scan("com.zetcode");
ctx.refresh();
创建一个新的AnnotationConfigApplicationContext
。 scan()
方法扫描com.zetcode
包及其子包中的带注解的类,以生成 bean。 我们需要调用refresh()
方法来完成该过程。
public void run() {
logger.info("Current time: {}", dateTimeService.getTime());
logger.info("Current date: {}", dateTimeService.getDate());
logger.info("Current datetime: {}", dateTimeService.getDateTime());
}
我们获取当前日期,时间和日期时间。
$ mvn package
$ mvn -q exec:java
19:25:12.842 INFO com.zetcode.Application - Current time: 19:25:12.842639200
19:25:12.842 INFO com.zetcode.Application - Current date: 2019-01-05
19:25:12.842 INFO com.zetcode.Application - Current datetime: 2019-01-05T19:25:12.842639200
我们运行该应用。
在本教程中,我们使用AnnotationConfigApplicationContext
创建了一个新的独立 Spring 应用。
您可能也对相关教程感兴趣:独立的 Spring 应用, Spring @ComponentScan
教程和 Java 教程。
Spring BeanFactoryPostProcessor
教程
Spring BeanFactoryPostProcessor
教程展示了如何使用BeanFactoryPostProcessor
来修改应用上下文的 Bean 定义。
Spring 是用于创建企业应用的流行 Java 应用框架。
Spring BeanFactoryPostProcessor
在实际创建 bean 之前,Spring BeanFactoryPostProcessor
会处理 bean 的 bean 定义或配置元数据。 使用BeanFactoryPostProcessor
,我们可以修改现有的 bean 定义或创建新的 bean 定义。
Spring 提供了BeanFactoryPostProcessor
的一些内置实现。 例如,PropertyPlaceholderConfigurer
是一种后处理器,可以从外部文件读取属性。
Spring BeanFactoryPostProcessor
示例
以下应用使用BeanFactoryPostProcessor
添加新的 bean 定义。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ │ Application.java
│ │ │
│ │ └───config
│ │ AppConfig.java
│ └───resources
│ logback.xml
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>beanfactorypostprocessorex</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.zetcode.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有基本的 Spring 依赖项spring-core
,spring-context
和日志记录logback-classic
依赖项。
exec-maven-plugin
用于在命令行上从 Maven 执行 Spring 应用。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
com/zetcode/config/AppConfig.java
package com.zetcode.config;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
public static BeanFactoryPostProcessor beanFactoryPostProcessor() {
return factory -> {
var registry = (BeanDefinitionRegistry) factory;
registry.registerBeanDefinition("myBean",
BeanDefinitionBuilder.genericBeanDefinition(String.class)
.addConstructorArgValue("This is myBean")
.getBeanDefinition()
);
};
}
}
AppConfig
是应用配置类。 使用@Bean
创建一个BeanFactoryPostProcessor
,它注册一个内置的java.lang.String
类型的新简单 bean。 新 bean 已向registerBeanDefinition()
注册。
com/zetcode/Application.java
package com.zetcode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.GenericXmlApplicationContext;
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
var ctx = new GenericXmlApplicationContext("my-beans.xml");
logger.info("{}", ctx.getBean("myBean"));
ctx.close();
}
}
在Application
中,我们获取已注册的 bean 并进行打印。
$ mvn -q exec:java
18:53:19.233 INFO com.zetcode.Application - This is myBean
我们运行该应用。
在本教程中,我们展示了如何使用BeanFactoryPostProcessor
注册新 bean。
您可能也对这些相关教程感兴趣: Spring @Qualifier
注解教程, Spring 单例范围 bean , Spring C 命名空间教程, Spring context:property-placeholder
教程, Spring BeanDefinitionBuilder
教程, Spring bean 引用教程和 Java 教程。
Spring BeanFactory
教程
Spring BeanFactory
教程展示了如何在 Spring 应用中使用BeanFactory
处理 Bean
Spring 是用于创建企业应用的流行 Java 应用框架。
Spring BeanFactory
BeanFactory
是应用组件的中央注册表。 它集中了应用组件的配置。 BeanFactory
加载存储在配置源(例如 XML 文档或 Java 配置)中的 bean 定义。
Spring BeanFactory
示例
该应用创建一个 bean 工厂,从 XML 配置文件加载 bean 定义,并在 bean 上应用后处理器。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ Application.java
│ └───resources
│ database.properties
│ logback.xml
│ my-beans.xml
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>beanfactory</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.zetcode.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有基本的 Spring 依赖项spring-core
,spring-context
,spring-jdbc
和日志记录logback-classic
依赖项。
exec-maven-plugin
用于在命令行上从 Maven 执行 Spring 应用。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
resources/database.properties
db.url=jdbc:h2:mem:testdb
db.username=testuser
db.password=s$cret
这些属性将通过 bean 后处理工厂插入到 bean 中。
resources/my-beans.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
<property name="url" value="${db.url}"></property>
<property name="username" value="${db.username}"></property>
<property name="password" value="${db.password}"></property>
</bean>
</beans>
my-beans.xml
文件声明一个dataSource
bean。 ${}
语法从外部属性文件插入值。
com/zetcode/Application.java
package com.zetcode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
var factory = new DefaultListableBeanFactory();
var reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(new ClassPathResource("my-beans.xml"));
var cfg = new PropertyPlaceholderConfigurer();
cfg.setLocation(new ClassPathResource("database.properties"));
cfg.postProcessBeanFactory(factory);
var dataSource = (SimpleDriverDataSource) factory.getBean("dataSource");
logger.info("Url: {}", dataSource.getUrl());
logger.info("User name: {}", dataSource.getUsername());
logger.info("Password: {}", dataSource.getPassword());
}
}
该应用创建一个BeanFactory
并注册一个 bean。
var factory = new DefaultListableBeanFactory();
var reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(new ClassPathResource("my-beans.xml"));
创建了DefaultListableBeanFactory
,它是BeanFactory
的实现。 它使用XmlBeanDefinitionReader
从my-beans.xml
配置文件读取 bean。 Bean 定义已加载loadBeanDefinitions()
。
var cfg = new PropertyPlaceholderConfigurer();
cfg.setLocation(new ClassPathResource("database.properties"));
cfg.postProcessBeanFactory(factory);
PropertyPlaceholderConfigurer
将属性从database.properties
文件插入到 bean 中。
var dataSource = (SimpleDriverDataSource) factory.getBean("dataSource");
我们使用getBean()
从工厂获得了 Bean。
logger.info("Url: {}", dataSource.getUrl());
logger.info("User name: {}", dataSource.getUsername());
logger.info("Password: {}", dataSource.getPassword());
我们检索dataSource
bean 属性。
$ mvn -q exec:java
10:02:30.701 INFO com.zetcode.Application - Url: jdbc:h2:mem:testdb
10:02:30.701 INFO com.zetcode.Application - User name: testuser
10:02:30.701 INFO com.zetcode.Application - Password: s$cret
我们运行该应用。
在本教程中,我们展示了如何创建BeanFactory
以及如何加载和后期处理 bean 定义。
您可能也对这些相关教程感兴趣: Spring BeanDefinitionBuilder
教程, Spring 单例范围 bean , Spring 注入列表 XML 教程, Spring BeanDefinitionBuilder
教程 , Spring HikariCP 教程和 Java 教程。
Spring @Bean
注解教程
Spring @Bean
注解教程展示了如何使用@Bean
注解在 Java 配置类中声明 bean。
Spring 是用于创建企业应用的流行 Java 应用框架。
Spring @Bean
@Bean
注解指示带注解的方法产生要由 Spring 容器管理的 bean。 它是<bean/>
XML 标签的直接模拟。 @Bean
支持<bean/>
提供的大多数属性,例如:init-method
,destroy-method
,autowiring
,lazy-init
,dependency-check
,depends-on
,scope
。
Spring @Bean
示例
该应用生成带有@Bean
注解的 Spring 托管 bean。 它还为 bean 提供了一些别名。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ │ Application.java
│ │ ├───bean
│ │ │ HelloMessage.java
│ │ └───config
│ │ AppConfig.java
│ └───resources
│ logback.xml
│ messages.properties
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>beanannotation</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.zetcode.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有基本的 Spring 依赖项spring-core
,spring-context
和日志记录logback-classic
依赖项。
exec-maven-plugin
用于在命令行上从 Maven 执行 Spring 应用。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
resources/message.properties
motd="Hello there!"
message.properties
包含day
属性的消息,由我们的HelloMessage
bean 使用。 这为应用提供了更大的灵活性,并避免了将消息硬编码为 Java 代码。
com/zetcode/bean/HelloMessage.java
package com.zetcode.bean;
public class HelloMessage {
private String message;
public HelloMessage(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
HelloMessage
bean 是使用@Bean
注解方法创建的。
com/zetcode/config/AppCofig.java
package com.zetcode.config;
import com.zetcode.bean.HelloMessage;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource(value="messages.properties")
public class AppConfig {
@Value("${motd}")
private String message;
@Bean(name={"myMessage", "motd"})
public HelloMessage helloMessageProducer() {
var helloMessage = new HelloMessage(message);
return helloMessage;
}
}
我们在AppConfig
中定义了HelloMessage
生产者。
@Configuration
@PropertySource(value="messages.properties")
public class AppConfig {
使用@Configuration
,我们声明AppConfig
是配置类。 @PropertySource
注解允许我们通过@Value
轻松使用messages.properties
文件中的属性。
@Value("${motd}")
private String message;
我们将motd
属性注入到message
属性中。
@Bean(name={"myMessage", "motd"})
public HelloMessage helloMessageProducer() {
var helloMessage = new HelloMessage(message);
return helloMessage;
}
helloMessageProducer()
产生一个新的HelloMessage
bean。 它从外部属性获取消息。 @Bean
注解使HelloMessage
bean 由 Spring 生产和管理。 另外,我们给 Bean 两个别名。
com/zetcode/Application.java
package com.zetcode;
import com.zetcode.bean.HelloMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackages = "com.zetcode")
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
var ctx = new AnnotationConfigApplicationContext(Application.class);
var msgBean1 = ctx.getBean(HelloMessage.class);
logger.info("{}", msgBean1.getMessage());
var msgBean2 = (HelloMessage) ctx.getBean("myMessage");
logger.info("{}", msgBean2.getMessage());
var msgBean3 = (HelloMessage) ctx.getBean("motd");
logger.info("{}", msgBean3.getMessage());
ctx.close();
}
}
该应用带有@ComponentScan
注解。 basePackages
选项告诉 Spring 在com/zetcode
包及其子包中查找组件。
var ctx = new AnnotationConfigApplicationContext(Application.class);
AnnotationConfigApplicationContext
是 Spring 独立应用上下文。 它接受带注解的Application
作为输入; 因此启用了扫描。
var msgBean1 = ctx.getBean(HelloMessage.class);
logger.info("{}", msgBean1.getMessage());
我们通过其类型来获取 bean。
var msgBean2 = (HelloMessage) ctx.getBean("myMessage");
logger.info("{}", msgBean2.getMessage());
var msgBean3 = (HelloMessage) ctx.getBean("motd");
logger.info("{}", msgBean3.getMessage());
在这里,我们通过别名获得相同的 bean。
$ mvn -q exec:java
14:39:29.324 INFO com.zetcode.Application - "Hello there!"
14:39:29.324 INFO com.zetcode.Application - "Hello there!"
14:39:29.324 INFO com.zetcode.Application - "Hello there!"
我们运行该应用。
在本教程中,我们使用了@Bean
注解来生成托管的 Spring bean。
您可能也会对这些相关教程感兴趣: Spring 单例范围 bean , Spring @ComponentScan
教程, Spring @Autowired
教程, Java 教程,或列出所有 Spring 教程。
Spring context:property-placeholder
教程
Spring context:property-placeholder
教程展示了如何使用context:property-placeholder
标记来外部化 Spring 应用中的属性。
Spring 是用于创建企业应用的流行 Java 应用框架。
Spring 的context:property-placeholder
context:property-placeholder
标签用于外部化单独文件中的属性。 它会自动配置PropertyPlaceholderConfigurer
,从而替换${}
占位符,这些占位符针对指定的属性文件(作为 Spring 资源位置)进行解析。
Spring context:property-placeholder
示例
该应用使用context:property-placeholder
来配置数据源的属性。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ Application.java
│ └───resources
│ database.properties
│ logback.xml
│ my-beans.xml
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>propertyplaceholder</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.zetcode.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有基本的 Spring 依赖项spring-core
,spring-context
,spring-jdbc
和日志记录logback-classic
依赖项。
exec-maven-plugin
用于在命令行上从 Maven 执行 Spring 应用。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
resources/database.properties
db.url=jdbc:h2:mem:testdb
db.username=testuser
db.password=s$cret
这些值在database.properties
文件中外部化。 这种方法比将值直接放入 XML 文件中更为灵活。
resources/my-beans.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:database.properties"/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
<property name="url" value="${db.url}"></property>
<property name="username" value="${db.username}"></property>
<property name="password" value="${db.password}"></property>
</bean>
</beans>
context:property-placeholder
指定属性文件的位置; 在我们的例子中,它是任何类路径目录中的database.properties
文件。
<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
<property name="url" value="${db.url}"></property>
<property name="username" value="${db.username}"></property>
<property name="password" value="${db.password}"></property>
</bean>
定义了dataSource
bean。 它通过${}
语法从属性文件中获取其值。
com/zetcode/Application.java
package com.zetcode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
var ctx = new GenericXmlApplicationContext("my-beans.xml");
var dataSource = (SimpleDriverDataSource) ctx.getBean("dataSource");
logger.info("Url: {}", dataSource.getUrl());
logger.info("User name: {}", dataSource.getUsername());
logger.info("Password: {}", dataSource.getPassword());
ctx.close();
}
}
这是主要的应用类。 它检索dataSource
bean 并打印其属性。
$ mvn -q exec:java
11:27:43.790 INFO com.zetcode.Application - Url: jdbc:h2:mem:testdb
11:27:43.790 INFO com.zetcode.Application - User name: testuser
11:27:43.790 INFO com.zetcode.Application - Password: s$cret
我们运行该应用。
在本教程中,我们展示了如何使用context:property-placeholder
来外部化属性。
您可能也对这些相关教程感兴趣: Spring @Qualifier
注解教程, Spring 单例范围 bean , Spring C-命名空间教程, Spring BeanDefinitionBuilder
教程, Spring bean 引用教程和 Java 教程。
Spring @PropertySource
注解教程
Spring @PropertySource
注解教程显示了如何使用@PropertySource
注解将属性包括到环境中以及如何使用@Value
注入属性。
Spring 是用于创建企业应用的流行 Java 应用框架。
Spring @PropertySource
@PropertySource
是方便的注解,用于将PropertySource
包含到 Spring 的环境中,并允许通过@Value
将属性注入类属性中。 (PropertySource
是代表来自特定来源的一组属性对的对象。)
@PropertySource
与@Configuration
一起使用。
Spring @PropertySource
示例
该应用使用 Spring 的@PropertySource
将application.properties
文件中的属性包含到环境中,并将它们注入类属性中。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ │ Application.java
│ │ └───config
│ │ AppConfig.java
│ └───resources
│ application.properties
│ logback.xml
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>propertysource</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.zetcode.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有基本的 Spring 依赖项spring-core
,spring-context
和日志记录logback-classic
依赖项。
exec-maven-plugin
用于在命令行上从 Maven 执行 Spring 应用。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
resources/application.properties
app.name=My application
app.version=1.1
application.properties
文件中有两个属性。
com/zetcode/config/AppConfig.java
package com.zetcode.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource(value = "application.properties", ignoreResourceNotFound = true)
public class AppConfig {
}
AppConfig
是应用配置类。 @PropertySource
将属性从application.properties
注入到 Spring 的环境中。
com/zetcode/Application.java
package com.zetcode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.env.Environment;
@ComponentScan(basePackages = "com.zetcode")
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
@Autowired
private Environment env;
@Value("${app.name}")
private String appName;
@Value("${app.version}")
private String appVersion;
public static void main(String[] args) {
var ctx = new AnnotationConfigApplicationContext(Application.class);
var app = ctx.getBean(Application.class);
app.run();
ctx.close();
}
private void run() {
logger.info("From Environment");
logger.info("Application name: {}", env.getProperty("app.name"));
logger.info("Application version: {}", env.getProperty("app.version"));
logger.info("Using @Value injection");
logger.info("Application name: {}", appName);
logger.info("Application version: {}", appVersion);
}
}
在Application
中,我们使用两种方法获得属性。
@Autowired
private Environment env;
我们注入Environment
。 我们可以使用getProperty()
方法检索属性。
@Value("${app.name}")
private String appName;
@Value("${app.version}")
private String appVersion;
我们将带有@Value
注解的属性注入到属性中。
logger.info("From Environment");
logger.info("Application name: {}", env.getProperty("app.name"));
logger.info("Application version: {}", env.getProperty("app.version"));
检索属性的第一种方法是使用getProperty()
方法从Environment
。
logger.info("Using @Value injection");
logger.info("Application name: {}", appName);
logger.info("Application version: {}", appVersion);
第二种方法是使用注入的属性。
$ mvn -q exec:java
15:00:20.653 INFO com.zetcode.Application - From Environment
15:00:20.668 INFO com.zetcode.Application - Application name: My application
15:00:20.668 INFO com.zetcode.Application - Application version: 1.1
15:00:20.668 INFO com.zetcode.Application - Using @Value injection
15:00:20.668 INFO com.zetcode.Application - Application name: My application
15:00:20.668 INFO com.zetcode.Application - Application version: 1.1
我们运行该应用。
在本教程中,我们展示了如何使用@PropertySource
注解在 Spring 应用中方便地使用属性。
您可能也对这些相关教程感兴趣: Spring @Qualifier
注解教程, Spring @Configuration
注解教程, Spring context:property-placeholder
教程,Java 教程,或列出所有 Spring 教程。
Spring @ComponentScan
教程
Spring @ComponentScan
教程显示了如何在 Spring 应用中启用组件扫描。 通过组件扫描,可以通过 Spring 容器自动检测咖啡豆。
Spring 是用于创建企业应用的流行 Java 应用框架。
Spring @ComponentScan
@ComponentScan
注解启用 Spring 中的组件扫描。 Spring 会自动检测以@Component
,@Configuration
和@Service
等构造型修饰的 Java 类。 使用@ComponentScan
的basePackages
属性指定应扫描哪些包装中的装饰豆。
@ComponentScan
注解是<context:component-scan>
XML 标签的替代方法。
Spring @ComponentScan
示例
该应用允许使用@ComponentScan
进行组件扫描。 我们有一个返回当前时间的服务 bean。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ │ Application.java
│ │ └───service
│ │ TimeService.java
│ └───resources
│ logback.xml
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>componentscan</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.zetcode.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有基本的 Spring 依赖项spring-core
,spring-context
和日志记录logback-classic
依赖项。
exec-maven-plugin
用于在命令行上从 Maven 执行 Spring 应用。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
com/zetcode/service/TimeService.java
package com.zetcode.service;
import org.springframework.stereotype.Service;
import java.time.LocalTime;
@Service
public class TimeService {
public LocalTime getTime() {
var now = LocalTime.now();
return now;
}
}
TimeService
类带有@Service
注解。 Spring 在组件扫描的帮助下将其注册为托管 Bean。
com/zetcode/Application.java
package com.zetcode;
import com.zetcode.service.TimeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@ComponentScan(basePackages = "com.zetcode")
@Configuration
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
var ctx = new AnnotationConfigApplicationContext(Application.class);
var timeService = (TimeService) ctx.getBean("timeService");
logger.info("The time is {}", timeService.getTime());
ctx.close();
}
}
该应用带有@ComponentScan
注解。 basePackages
选项告诉 Spring 在com/zetcode
包及其子包中查找组件。
var ctx = new AnnotationConfigApplicationContext(Application.class);
AnnotationConfigApplicationContext
是 Spring 独立应用上下文。 它接受带注解的Application
作为输入; 因此启用了扫描。
var timeService = (TimeService) ctx.getBean("timeService");
logger.info("The time is {}", timeService.getTime());
我们获取注册的服务 bean 并调用其方法。
$ mvn -q exec:java
10:57:01.912 INFO com.zetcode.Application - The time is 10:57:01.912235800
我们运行该应用。
在本教程中,我们使用@ComponentScan
启用了组件扫描。
您可能也对这些相关教程感兴趣: Spring BeanDefinitionBuilder
教程, Spring AnnotationConfigApplicationContext
, Spring 单例范围 bean , Spring @Bean
注解教程, Spring @Configuration
注解教程, Spring 注入列表 XML 教程, Spring BeanDefinitionBuilder
教程, Spring HikariCP 教程和 Java 教程。
Spring @Configuration
教程
Spring @Configuration
注解教程展示了如何使用@Configuration
注解配置 Spring 应用。
Spring 是用于创建企业应用的流行 Java 应用框架。
Spring @Configuration
@Configuration
注解用于基于 Spring 注解的配置。 @Configuration
是标记注解,指示类声明了一个或多个@Bean
方法,并且可以由 Spring 容器处理以在运行时为这些 bean 生成 bean 定义和服务请求
Spring @Configuration
示例
以下应用使用@Configuration
来配置 Spring 应用。
pom.xml
src
└───src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ │ Application.java
│ │ └───config
│ │ AppConfig.java
│ │ H2Configurer.java
│ └───resources
│ application.properties
│ logback.xml
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>configurationex</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.zetcode.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有基本的 Spring 依赖项spring-core
,spring-context
和日志记录logback-classic
依赖项。
exec-maven-plugin
用于在命令行上从 Maven 执行 Spring 应用。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
resources/application.properties
app.name=My application
app.db=H2
这里我们有一些应用属性。
com/zetcode/config/AppConfig.java
package com.zetcode.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@ComponentScan(basePackages = "com.zetcode")
@PropertySource(value = "application.properties")
public class AppConfig {
@Bean
public H2Configurer databaseConfig() {
return new H2Configurer();
}
}
AppConfig
是应用配置类。 它装饰有@Configuration
注解,这是@Component
的一种特殊形式。
@Configuration
@ComponentScan(basePackages = "com.zetcode")
@PropertySource(value = "application.properties")
public class AppConfig {
通过@ComponentScan
启用组件扫描,并通过@PropertySource
加载资源。
@Bean
public H2Configurer databaseConfig() {
return new H2Configurer();
}
使用@Bean
注解,我们创建了H2Configurer
bean。
com/zetcode/config/H2Configurer.java
package com.zetcode.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class H2Configurer {
private static final Logger logger = LoggerFactory.getLogger(H2Configurer.class);
public H2Configurer() {
logger.info("Configuring H2 database");
}
}
H2Configurer
仅记录一条消息。
com/zetcode/Application.java
package com.zetcode;
import com.zetcode.config.AppConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;
@Component
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
var ctx = new AnnotationConfigApplicationContext(AppConfig.class);
var app = ctx.getBean(Application.class);
app.run();
ctx.close();
}
@Value("${app.name}")
private String applicationName;
@Value("${app.db}")
private String database;
private void run() {
logger.info("Application name: {}", applicationName);
logger.info("Database: {}", database);
}
}
应用类显示应用属性。 这些属性通过@Value
注入到属性中。
var ctx = new AnnotationConfigApplicationContext(AppConfig.class);
AppConfig
被加载到应用上下文中。
$ mvn -q exec:java
20:07:39.769 INFO com.zetcode.config.H2Configurer - Configuring H2 database
20:07:39.801 INFO com.zetcode.Application - Application name: My application
20:07:39.816 INFO com.zetcode.Application - Database: H2
我们运行该应用。
在本教程中,我们使用@Configuration
配置了一个 Spring 应用。
您可能也对这些相关教程感兴趣: Spring @Bean
教程, Spring @PropertySource
教程, Spring @ComponentScan
教程, Java 教程,或列出所有 Spring 教程。
Spring C 命名空间教程
Spring 构造器名称空间教程展示了如何在 Spring 应用的基于构造器的注入中使用 C-命名空间。
Spring 是用于创建企业应用的流行 Java 应用框架。
Spring C 命名空间
Spring C-命名空间是 XML 快捷方式,并且替代了<bean/>
标记的<constructor-arg/>
子元素。 要启用 C 命名空间功能,我们需要将xmlns:c="http://www.springframework.org/schema/c"
添加到 XML 文件中。 请注意,此命名空间没有单独的 XSD 文件。 因此,诸如 IntelliJ 之类的 IDE 无法识别它。
Spring C 命名空间示例
该应用包含两个User
bean。 一个注入旧的<constructor-arg/>
,另一个注入新的 C-命名空间属性。
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ │ Application.java
│ │ └───bean
│ │ User.java
│ └───resources
│ logback.xml
│ my-beans.xml
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>cnamespace</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.zetcode.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有基本的 Spring 依赖项spring-core
和spring-context
和日志记录logback-classic
依赖项。
exec-maven-plugin
用于在命令行上从 Maven 执行 Spring 应用。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
resources/my-beans.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:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name="user1" class="com.zetcode.bean.User">
<constructor-arg name="name" value="John Doe"/>
<constructor-arg name="occupation" value="gardener"/>
</bean>
<bean name="user2" class="com.zetcode.bean.User"
c:name="Peter Smith" c:occupation="teacher"/>
</beans>
my-beans.xml
文件声明了两个 bean:user1
和user2
。 user1
使用<constructor-arg/>
注入其值,而user2
使用c:name
和c:occupation
属性。
com/zetcode/bean/User.java
package com.zetcode.bean;
public class User {
private String name;
private String occupation;
public User(String name, String occupation) {
this.name = name;
this.occupation = occupation;
}
@Override
public String toString() {
final var sb = new StringBuilder("User{");
sb.append("name='").append(name).append('\'');
sb.append(", occupation='").append(occupation).append('\'');
sb.append('}');
return sb.toString();
}
}
这是由 Spring 容器管理的User
类。 它必须包含一个构造器,因为我们在应用中使用了基于构造器的注入。
com/zetcode/Application.java
package com.zetcode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.GenericXmlApplicationContext;
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
var ctx = new GenericXmlApplicationContext("my-beans.xml");
var u1 = ctx.getBean("user1");
var u2 = ctx.getBean("user2");
logger.info("{}", u1);
logger.info("{}", u2);
ctx.close();
}
}
这是主要的应用类。 它检索两个 bean 并将它们打印到控制台。
$ mvn -q exec:java
16:40:39.632 INFO com.zetcode.Application - User{name='John Doe', occupation='gardener'}
16:40:39.632 INFO com.zetcode.Application - User{name='Peter Smith', occupation='teacher'}
我们运行该应用。
在本教程中,我们展示了如何在 C-命名空间中使用基于构造器的注入。
您可能也对这些相关教程感兴趣: Spring @Qualifier
注解教程, Spring 单例范围 bean , Spring P-命名空间教程, Spring BeanDefinitionBuilder
教程, Spring HikariCP 教程和 Java 教程。
Spring P 命名空间教程
Spring 属性名称空间教程展示了如何在 Spring 应用的基于属性的注入中使用 P-命名空间。
Spring 是用于创建企业应用的流行 Java 应用框架。
Spring P 命名空间
Spring P-命名空间是 XML 快捷方式,并且替代了<bean/>
标记的<property/>
子元素。 要启用 P-命名空间功能,我们需要将xmlns:p="http://www.springframework.org/schema/p"
添加到 XML 文件中。 请注意,此命名空间没有单独的 XSD 文件。 因此,诸如 IntelliJ 之类的 IDE 无法识别它。
Spring p 命名空间示例
该应用包含两个HelloMessage
bean。 一个注入旧的<property/>
,另一个注入新的 P-命名空间属性。
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ │ Application.java
│ │ └───bean
│ │ HelloMessage.java
│ └───resources
│ logback.xml
│ my-beans.xml
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>cnamespace</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.zetcode.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有基本的 Spring 依赖项spring-core
和spring-context
和日志记录logback-classic
依赖项。
exec-maven-plugin
用于在命令行上从 Maven 执行 Spring 应用。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
resources/my-beans.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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name="msg1" class="com.zetcode.bean.HelloMessage">
<property name="message" value="How are you?"/>
</bean>
<bean name="msg2" class="com.zetcode.bean.HelloMessage" p:message="Hello there"/>
</beans>
my-beans.xml
文件声明了两个 bean:msg1
和msg2
。 msg1
使用<property/>
标签注入其值,而msg2
使用p:message
属性。
com/zetcode/bean/HelloMessage.java
package com.zetcode.bean;
public class HelloMessage {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
这是由 Spring 容器管理的HelloMessage
类。 它必须包含一个设置器方法,因为我们在应用中使用了基于属性的注入。
com/zetcode/Application.java
package com.zetcode;
import com.zetcode.bean.HelloMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.GenericXmlApplicationContext;
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
var ctx = new GenericXmlApplicationContext("my-beans.xml");
var msg1 = (HelloMessage) ctx.getBean("msg1");
logger.info("{}", msg1.getMessage());
var msg2 = (HelloMessage) ctx.getBean("msg2");
logger.info("{}", msg2.getMessage());
ctx.close();
}
}
这是主要的应用类。 它检索两个HelloMessage
bean,并将它们打印到控制台。
$ mvn -q exec:java
16:52:11.257 [main] INFO com.zetcode.Application - How are you?
16:52:11.273 [main] INFO com.zetcode.Application - Hello there
我们运行该应用。
在本教程中,我们展示了如何在 P 名称空间中使用基于属性的注入。
您可能也对这些相关教程感兴趣: Spring @Qualifier
注解教程, Spring 单例范围 bean , Spring C-命名空间教程, Spring BeanDefinitionBuilder
教程, Spring HikariCP 教程和 Java 教程。
Spring bean 引用教程
Spring bean 引用教程展示了如何在 Spring 应用的 XML 配置文件中引用 bean。
Spring 是用于创建企业应用的流行 Java 应用框架。
Spring ref
属性
ref
属性是<ref>
标签的快捷方式,用于引用其他注入的 bean。
Spring bean 引用示例
该应用包含两个 bean:infoMessage
和mesageRenderer
。 mesageRenderer
通过ref
属性引用infoMessage
。
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ │ Application.java
│ │ ├───bean
│ │ │ IMessage.java
│ │ │ InfoMessage.java
│ │ └───service
│ │ MessageRenderer.java
│ └───resources
│ logback.xml
│ my-beans.xml
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>beanreference</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.zetcode.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有基本的 Spring 依赖项spring-core
和spring-context
和日志记录logback-classic
依赖项。
exec-maven-plugin
用于在命令行上从 Maven 执行 Spring 应用。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} [%thread] %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
resources/my-beans.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="infoMessage" class="com.zetcode.bean.InfoMessage"/>
<bean name="messageRenderer" class="com.zetcode.service.MessageRenderer">
<constructor-arg name="message" ref="infoMessage"/>
</bean>
</beans>
my-beans.xml
文件声明了两个 bean:info
和messageRenderer
。 infoMessage
通过ref
属性引用infoMessage
。 Spring 通过构造器注入将infoMessage
bean 注入message
属性。
com/zetcode/bean/IMessage.java
package com.zetcode.bean;
public interface IMessage {
String getMessage();
}
IMessage
接口具有一个方法声明。
com/zetcode/bean/InfoMessage.java
package com.zetcode.bean;
public class InfoMessage implements IMessage {
public String getMessage() {
return "This is information message";
}
}
InfoMessage
bean 返回一条信息消息。
com/zetcode/service/MessageRenderer.java
package com.zetcode.service;
import com.zetcode.Application;
import com.zetcode.bean.IMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MessageRenderer {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
private IMessage message;
public MessageRenderer(IMessage message) {
this.message = message;
}
public void renderMessage() {
logger.info("{}", message.getMessage());
}
}
MessageRenderer
呈现一条消息。 它期望注入一个 bean。 Spring 通过构造器注入将infoMessage
bean 注入MessageRenderer
。
com/zetcode/Application.java
package com.zetcode;
import com.zetcode.service.MessageRenderer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.GenericXmlApplicationContext;
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
var ctx = new GenericXmlApplicationContext("my-beans.xml");
var renderer = (MessageRenderer) ctx.getBean("messageRenderer");
renderer.renderMessage();
ctx.close();
}
}
这是主要的应用类。 它检索MessageRenderer
bean 并调用其renderMessage()
方法。
$ mvn -q exec:java
12:05:23.567 [com.zetcode.Application.main()] INFO com.zetcode.Application - This is information message
我们运行该应用。
在本教程中,我们展示了如何使用 Spring 的 XML ref
属性引用其他 bean。
您可能也对这些相关教程感兴趣: Spring @Qualifier
注解教程, Spring context:property-placeholder
教程, Spring 单例范围 bean , Spring 注入列表 XML 教程, Spring BeanDefinitionBuilder
教程, Spring HikariCP 教程和 Java 教程。
Spring @Qualifier
注解教程
Spring @Qualifier
注解教程显示了如何使用@Qualifier
来区分 Spring 应用中的 bean。
Spring 是用于创建企业应用的流行 Java 应用框架。
Spring @Qualifier
注解
如果 Spring 不能这样做,则@Qualifier
注解有助于消除 Bean 引用的歧义。
Spring @Qualifier
示例
该应用具有不同类型的消息 bean。 我们用@Qualifier
区分它们。
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ │ Application.java
│ │ ├───bean
│ │ │ IMessage.java
│ │ │ Info.java
│ │ │ Warning.java
│ │ └───service
│ │ MessageProducer.java
│ └───resources
│ logback.xml
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>qualifierannotation</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.zetcode.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有基本的 Spring 依赖项spring-core
和spring-context
和日志记录logback-classic
依赖项。
exec-maven-plugin
用于在命令行上从 Maven 执行 Spring 应用。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} [%thread] %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
com/zetcode/bean/IMessage.java
package com.zetcode.bean;
public interface IMessage {
String getMessage();
}
IMessage
接口具有一个方法声明。
com/zetcode/bean/Info.java
package com.zetcode.bean;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
@Qualifier("info")
public class Info implements IMessage {
@Override
public String getMessage() {
return "This is an information message";
}
}
接口的第一个实现提供了一条信息消息。 @Qualifier
用于标识 bean。
com/zetcode/bean/Warning.java
package com.zetcode.bean;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
@Qualifier("warning")
public class Warning implements IMessage {
public String getMessage() {
return "This is a warning message";
}
}
第二种实现给出警告消息。 它也以@Qualifier
命名。
com/zetcode/service/MessageProducer.java
package com.zetcode.service;
import com.zetcode.bean.IMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service
public class MessageProducer {
private static final Logger logger = LoggerFactory.getLogger(MessageProducer.class);
@Autowired
@Qualifier("info")
private IMessage infoMessage;
@Autowired
@Qualifier("warning")
private IMessage warningMessage;
public void produce() {
logger.info("{}", infoMessage.getMessage());
logger.warn("{}", warningMessage.getMessage());
}
}
MessageProducer
注入两个IMessage
bean。 为了区分它们,我们使用@Qualifier
注解。
com/zetcode/Application.java
package com.zetcode;
import com.zetcode.service.MessageProducer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackages = "com.zetcode.bean;com.zetcode.service")
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
logger.info("Application starting");
try (var ctx = new AnnotationConfigApplicationContext(Application.class)) {
var messageProducer = (MessageProducer) ctx.getBean("messageProducer");
messageProducer.produce();
}
}
}
这是主要的应用类。 它检索messageProducer
bean 并调用其produce()
方法。
$ mvn -q exec:java
10:50:03.309 [com.zetcode.Application.main()] INFO com.zetcode.Application - Application starting
10:50:03.574 [com.zetcode.Application.main()] INFO com.zetcode.service.MessageProducer - This is an information message
10:50:03.574 [com.zetcode.Application.main()] WARN com.zetcode.service.MessageProducer - This is a warning message
我们运行该应用。
在本教程中,我们使用了 Spring 的@Qualifier
注解。
您可能也对这些相关教程感兴趣: Spring @Bean
教程, Spring Boot @Qualifier
注解, Spring @ComponentScan
教程, Java 教程或列出所有 Spring 教程。
Spring ClassPathResource
教程
Spring ClassPathResource
教程显示了如何在 Spring 应用中使用ClassPathResource
读取资源。
Spring 是用于创建企业应用的流行 Java 应用框架。
Spring ClassPathResource
ClassPathResource
允许从 Java 类路径获取资源。
Spring ClassPathResource
示例
该应用从 Java 类路径中的文件读取文本数据。
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ │ Application.java
│ │ └───service
│ │ ReadWordsService.java
│ └───resources
│ logback.xml
│ my-beans.xml
│ words.txt
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>classpathres</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.zetcode.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有基本的 Spring 依赖项spring-core
和spring-context
和日志记录logback-classic
依赖项。
exec-maven-plugin
用于在命令行上从 Maven 执行 Spring 应用。
resources/my-beans.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name="readWordsService" class="com.zetcode.service.ReadWordsService"/>
</beans>
在my-beans.xml
文件中,我们配置readWordsService
bean。 它成为 Spring 托管的 bean。
resources/words.txt
sky
blue
mountain
fresh
cloud
rock
water
melon
resources
目录包含在类路径中。 该应用从words.txt
文件中读取单词。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} [%thread] %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
com/zetcode/service/ReadWordsService.java
package com.zetcode.service;
import org.springframework.core.io.ClassPathResource;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
public class ReadWordsService {
public List<String> readWords() throws IOException {
var res = new ClassPathResource("words.txt");
var myFile = res.getFile();
var lines = Files.readAllLines(myFile.toPath());
return lines;
}
}
ReadWordsService
将单词读入列表,并将列表返回给客户端。
var res = new ClassPathResource("words.txt");
ClassPathResource
用于定位文本文件。
com/zetcode/Application.java
package com.zetcode;
import com.zetcode.service.ReadWordsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.GenericXmlApplicationContext;
import java.io.IOException;
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) throws IOException {
var ctx = new GenericXmlApplicationContext("my-beans.xml");
var wordsService = (ReadWordsService) ctx.getBean("readWordsService");
var words = wordsService.readWords();
words.forEach(word -> logger.info(word));
ctx.close();
}
}
这是主要的应用类。
var wordsService = (ReadWordsService) ctx.getBean("readWordsService");
var words = wordsService.readWords();
words.forEach(word -> logger.info(word));
我们从容器中检索readWordsService
bean,并调用其readWords()
方法。 文字将打印到控制台。
$ mvn -q exec:java
00:25:49.008 [com.zetcode.Application.main()] INFO com.zetcode.Application - sky
00:25:49.008 [com.zetcode.Application.main()] INFO com.zetcode.Application - blue
00:25:49.008 [com.zetcode.Application.main()] INFO com.zetcode.Application - mountain
00:25:49.008 [com.zetcode.Application.main()] INFO com.zetcode.Application - fresh
00:25:49.008 [com.zetcode.Application.main()] INFO com.zetcode.Application - cloud
00:25:49.008 [com.zetcode.Application.main()] INFO com.zetcode.Application - rock
00:25:49.008 [com.zetcode.Application.main()] INFO com.zetcode.Application - water
00:25:49.008 [com.zetcode.Application.main()] INFO com.zetcode.Application - melon
我们运行该应用。
在本教程中,我们使用了 Spring 的ClassPathResource
。
您可能也对这些相关教程感兴趣:经典 Spring 应用中的JdbcTemplate
, Spring 单例范围 bean , Spring 注入列表 XML 教程, Spring BeanDefinitionBuilder
教程, Spring HikariCP 教程和 Java 教程。
Spring 原型作用域 bean
Spring Prototype 作用域 bean 教程展示了如何在 Spring 应用中使用 Prototype 作用域 bean。
Spring 是用于创建企业应用的流行 Java 应用框架。
Spring 原型 bean
原型 bean 每次针对该 bean 发出新请求时都会创建。
其他 bean 范围是:单例,请求,会话,全局会话和应用。
Spring 原型 bean 示例
该应用将创建两个原型范围内的 bean,并检查它们是否相同。 该应用是经典的 Spring 5 控制台应用。
────src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ │ Application.java
│ │ │
│ │ └───bean
│ │ Message.java
│ │
│ └───resources
│ logback.xml
│ my-beans.xml
│
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>prototypescopedbean</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.zetcode.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有基本的 Spring 依赖项spring-core
和spring-context
和日志记录logback-classic
依赖项。
exec-maven-plugin
用于在命令行上从 Maven 执行 Spring 应用。
resources/my-beans.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.zetcode"/>
</beans>
通过context:component-scan
标签,我们指示 Spring 在com.zetcode
包中查找 bean。 它将找到我们唯一的Message
bean,并用@Component
装饰。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} [%thread] %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
com/zetcode/bean/Message.java
package com.zetcode.bean;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope("prototype")
public class Message {
private String message;
public String getMessage() {
return message;
}
}
Message
是由 Spring 容器管理的 Spring bean。 它具有原型范围。
@Component
@Scope("prototype")
public class Message {
@Scope("prototype")
将 bean 的范围设置为原型。 默认值为单例。
com/zetcode/Application.java
package com.zetcode;
import com.zetcode.bean.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.GenericXmlApplicationContext;
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
var ctx = new GenericXmlApplicationContext("my-beans.xml");
var beanA = ctx.getBean(Message.class);
var beanB = ctx.getBean(Message.class);
if (beanA.equals(beanB)) {
logger.info("The beans are identical");
} else {
logger.info("The beans are not identical");
}
ctx.close();
}
}
这是主要的应用类。
var ctx = new GenericXmlApplicationContext("my-beans.xml");
我们使用GenericXmlApplicationContext
从my-beans.xml
文件创建 Spring 应用上下文。
var bean1 = ctx.getBean(Message.class);
var bean2 = ctx.getBean(Message.class);
app.run(bean1, bean2);
我们从应用上下文中获得两个 bean,并将它们传递给run()
方法进行比较。
logger.info(a.getMessage());
我们从 bean 中读取消息。
if (a.equals(b)) {
logger.info("The beans are the same");
} else {
logger.info("The beans are not the same");
}
我们测试两个豆是否相同。
$ mvn -q exec:java
21:26:03.089 [com.zetcode.Application.main()] INFO com.zetcode.Application - The beans are not identical
我们运行该应用。 将Message
bean 的范围更改为单例并比较结果。
在本教程中,我们使用了原型 Spring bean。
您可能也对这些相关教程感兴趣:经典的 Spring 应用中的 JdbcTemplate
, Spring 单例范围 bean , Spring ClassPathResource
教程, Spring 注入列表 XML 教程, Spring BeanDefinitionBuilder
教程, Spring HikariCP 教程和 Java 教程。
Spring @Autowired
教程
Spring @Autowired
教程展示了如何使用@Autowired
注解在 Spring 应用中注入依赖项。
Spring 是用于创建企业应用的流行 Java 应用框架。
Spring @Autowired
@Autowired
注解标记将由 Spring 的依赖项注入工具自动装配的构造器,字段,设置器方法或配置方法。 它是 JSR-330 @Inject
注解的替代方法。
Spring @Autowired
示例
应用使用@Autowired
注入依赖项。 依赖关系是一个返回单词的服务对象。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ │ Application.java
│ │ └───service
│ │ WordService.java
│ └───resources
│ logback.xml
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>springautowired</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.zetcode.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有基本的 Spring 依赖项spring-core
,spring-context
和日志记录logback-classic
依赖项。
exec-maven-plugin
用于在命令行上从 Maven 执行 Spring 应用。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
com/zetcode/service/WordService.java
package com.zetcode.service;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Random;
@Service
public class WordService {
private final List<String> words = List.of("pen", "sky",
"rock", "forest", "falcon", "eagle");
public List<String> all() {
return words;
}
public String randomWord() {
return words.get(new Random().nextInt(words.size()));
}
}
WordService
类带有@Service
注解。 Spring 在组件扫描的帮助下将其注册为托管 Bean。 稍后将此服务对象与@Autowired
一起注入Application
中。
com/zetcode/Application.java
package com.zetcode;
import com.zetcode.service.WordService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;
@Component
@ComponentScan(basePackages="com.zetcode")
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
@Autowired
private WordService wordService;
public static void main(String[] args) {
var ctx = new AnnotationConfigApplicationContext(Application.class);
var bean = ctx.getBean(Application.class);
bean.run();
ctx.close();
}
public void run() {
logger.info("{}", wordService.randomWord());
logger.info("{}", wordService.randomWord());
var words = wordService.all();
words.stream().forEach(word -> logger.info("{}", word));
}
}
使用WordService
使用输出字注解应用。 服务依赖项与@Autowired
一起注入Application
中。
@Autowired
private WordService wordService;
这称为场注入。
注意:虽然字段注入简短而有趣,但通常建议使用构造器注入或设置器注入。
$ mvn -q exec:java
17:15:34.504 INFO com.zetcode.Application - falcon
17:15:34.507 INFO com.zetcode.Application - eagle
17:15:34.508 INFO com.zetcode.Application - pen
17:15:34.508 INFO com.zetcode.Application - sky
17:15:34.509 INFO com.zetcode.Application - rock
17:15:34.509 INFO com.zetcode.Application - forest
17:15:34.510 INFO com.zetcode.Application - falcon
17:15:34.510 INFO com.zetcode.Application - eagle
我们运行该应用。
在本教程中,我们使用@Autowired
在 Spring 中注入了依赖项。
您可能也对这些相关教程感兴趣: Spring @Bean
注解教程, Spring @ComponentScan
教程, Java 教程或列出所有 Spring 教程。
Spring List
XML 注入教程
Spring 注入列表 XML 教程展示了如何在 XML 配置中将列表注入到应用上下文中。
Spring 是用于创建企业应用的流行 Java 应用框架。
util 模式
util XML 模式处理常见的工具配置问题,例如配置集合或引用常量。
Spring 注入列表示例
该应用从 Spring XML 配置注入一个 List 集合。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>injectlistex</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.zetcode.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有基本的 Spring 依赖项spring-core
和spring-context
和日志记录logback-classic
依赖项。
exec-maven-plugin
用于在命令行上从 Maven 执行 Spring 应用。
src/main/resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} [%thread] %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
src/main/resources/my-beans.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:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<context:component-scan base-package="com.zetcode"/>
<util:list id="myColours" value-type="java.lang.String">
<value>red</value>
<value>green</value>
<value>blue</value>
<value>yellow</value>
<value>brown</value>
<value>orange</value>
</util:list>
</beans>
在my-beans.xml
配置文件中,我们定义了颜色列表。 列表类型为java.util.String
,并使用value
标签指定值。 我们需要导入适当的架构定义。
src/main/java/com/zetcode/Application.java
package com.zetcode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.GenericXmlApplicationContext;
import java.util.List;
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
var ctx = new GenericXmlApplicationContext("my-beans.xml");
var colours = (List<String>) ctx.getBean("myColours");
logger.info(colours.toString());
ctx.close();
}
}
在Application
类中,我们使用getBean()
检索 bean 列表并将其记录到控制台。
$ mvn -q exec:java
21:28:19.770 [com.zetcode.Application.main()] INFO com.zetcode.Application - [red, green, blue, yellow, brown, orange]
我们运行该应用。
在本教程中,我们展示了如何使用 XML 配置将值列表注入到应用中。
您可能对以下相关教程感兴趣:经典 Spring 应用中的 JdbcTemplate , Spring 单例范围 bean , Spring BeanDefinitionBuilder 教程, Spring HikariCP 教程 和 Java 教程。
Spring 概要文件 XML 教程
Spring 概要文件 XML 教程显示了如何为 Spring 应用配置 XML 概要文件。
Spring 是用于创建企业应用的流行 Java 应用框架。
Spring 简介
概要文件是为特定环境(例如开发或生产)声明的一组命名 Bean。 可以使用 XML 或使用注解来配置配置文件。
Spring 配置文件示例
该应用定义了两个配置文件:生产和开发。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ Application.java
│ └───resources
│ database-dev.properties
│ database-prod.properties
│ logback.xml
└───test
└───java
这是项目结构。 我们有两个属性文件:database-dev.properties
和database-prod.properties
。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>profileex</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.zetcode.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有基本的 Spring 依赖项spring-core
,spring-context
,spring-jdbc
和日志记录logback-classic
依赖项。
exec-maven-plugin
用于在命令行上从 Maven 执行 Spring 应用。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
resources/database-dev.properties
db.url=jdbc:h2:mem:testdb
db.username=testuser
db.password=s$cret
这些是开发属性。
resources/database-prod.properties
db.url=jdbc:postgresql://localhost/mydb
db.username=user7
db.password=s$cret
这些是生产属性。
resources/my-beans.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:database-${spring.profiles.active}.properties"/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
<property name="url" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</bean>
</beans>
my-beans.xml
包含dataSource
bean。 <context:property-placeholder>
标签基于活动的 Spring 配置文件为数据源配置属性。
com/zetcode/Application.java
package com.zetcode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
System.setProperty("spring.profiles.active", "prod");
var ctx = new GenericXmlApplicationContext("my-beans.xml");
var dataSource = (SimpleDriverDataSource) ctx.getBean("dataSource");
logger.info("Url: {}", dataSource.getUrl());
logger.info("User name: {}", dataSource.getUsername());
logger.info("Password: {}", dataSource.getPassword());
ctx.close();
}
}
该应用检索dataSource
bean 并打印其属性。 激活属性是通过System.setProperty()
方法设置的。 另外,我们可以将属性设置为 VM 变量-Dspring.profiles.active=prod
或在 IDE 设置中。
$ mvn -q -Dspring.profiles.active=dev exec:java
20:30:45.832 INFO com.zetcode.Application - Url: jdbc:h2:mem:testdb
20:30:45.832 INFO com.zetcode.Application - User name: testuser
20:30:45.832 INFO com.zetcode.Application - Password: s$cret
我们在命令行上设置了配置文件的情况下运行应用
在本教程中,我们为 Spring 应用创建了开发和生产数据。
您可能也对这些相关教程感兴趣: Spring @Bean
注解教程, Spring 单例范围 bean , Spring @ComponentScan
教程, Spring 注入列表 XML 教程, Spring BeanDefinitionBuilder
教程, Spring HikariCP 教程和 Java 教程。
Spring BeanDefinitionBuilder
教程
Spring BeanDefinitionBuilder
教程展示了如何使用BeanDefinitionBuilder
以编程方式创建新的 Spring Bean。
Spring 是用于创建企业应用的流行 Java 应用框架。
BeanDefinitionBuilder
BeanDefinitionBuilder
用于以编程方式创建新的 Spring bean。 它利用了构建器模式。
Spring BeanDefinitionBuilder
示例
该应用创建一个简单的字符串 bean。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>beanbuilderex</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.zetcode.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有基本的 Spring 依赖项spring-core
和spring-context
和日志记录logback-classic
依赖项。
exec-maven-plugin
用于在命令行上从 Maven 执行 Spring 应用。
src/main/resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} [%thread] %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
src/main/java/com/zetcode/Application.java
package com.zetcode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackages = "com.zetcode")
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
var ctx = new AnnotationConfigApplicationContext(Application.class);
var beanFactory = (BeanDefinitionRegistry) ctx.getBeanFactory();
beanFactory.registerBeanDefinition("myBean",
BeanDefinitionBuilder.genericBeanDefinition(String.class)
.addConstructorArgValue("This is my bean")
.setScope("prototype")
.getBeanDefinition()
);
logger.info("{}", ctx.getBean("myBean"));
ctx.close();
}
}
该示例使用BeanDefinitionBuilder
创建一个类型为String
的简单 bean。
var beanFactory = (BeanDefinitionRegistry) ctx.getBeanFactory();
使用getBeanFactory()
从应用上下文中检索 bean 工厂。
beanFactory.registerBeanDefinition("myBean",
BeanDefinitionBuilder.genericBeanDefinition(String.class)
.addConstructorArgValue("This is my bean")
.setScope("prototype")
.getBeanDefinition()
);
我们向registerBeanDefinition()
注册了一个新 bean。
logger.info("{}", ctx.getBean("myBean"));
我们使用getBean()
从应用上下文中获取 bean 并将其记录下来。
$ mvn -q exec:java
20:51:05.970 [com.zetcode.Application.main()] INFO com.zetcode.Application - This is my bean
我们运行该应用。
在本教程中,我们使用BeanDefinitionBuilder
以编程方式注册了一个新的 Spring bean。
您可能也对这些相关教程感兴趣: Spring 注入列表 XML 教程, Spring BeanFactory
教程,经典 Spring 应用中的JdbcTemplate
, Spring 单例范围 bean , Spring HikariCP 教程和 Java 教程。
Spring 单例作用域 bean
Spring 单例作用域 bean 教程展示了如何在 Spring 应用中使用单例作用域 bean。
Spring 是用于创建企业应用的流行 Java 应用框架。
Spring 单例 bean
单例 bean 是在创建 Spring 容器时创建的,在销毁容器时会被销毁。 单例 bean 是共享的; 每个 Spring 容器仅创建一个单例 bean 实例。 单例范围是 Spring bean 的默认范围。
其他 bean 范围是:原型,请求,会话,全局会话和应用。
Spring 单例 bean 示例
该应用创建两个单例作用域 Bean,并检查它们是否相同。 该应用是经典的 Spring 5 控制台应用。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>scopesingletonex</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.zetcode.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有基本的 Spring 依赖项spring-core
和spring-context
和日志记录logback-classic
依赖项。
exec-maven-plugin
用于在命令行上从 Maven 执行 Spring 应用。
resources/my.properties
myapp.name=ScopeSingleton
myapp.author=Jan Bodnar
my.properties
文件中有两个基本属性。 它们正在Message
bean 中使用。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} [%thread] %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
com/zetcode/bean/Message.java
package com.zetcode.bean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope("单例") // change to prototype
@PropertySource("classpath:my.properties")
public class Message {
@Value("${myapp.name}")
private String name;
@Value("${myapp.author}")
private String author;
public String getMessage() {
return String.format("Application %s was created by %s", name, author);
}
}
Message
是由 Spring 容器管理的 Spring bean。 它具有单例范围。
@Component
@Scope("单例") // change to prototype
@PropertySource("classpath:my.properties")
public class Message {
不需要@Scope("单例")
注解; 如果未指定,默认范围是单例。 使用@PropertySource
注解,我们指定属性文件。 稍后使用@Value
读取属性。
com/zetcode/Application.java
package com.zetcode;
import com.zetcode.bean.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackages = "com.zetcode")
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
var ctx = new AnnotationConfigApplicationContext(Application.class);
var app = ctx.getBean(Application.class);
var bean1 = ctx.getBean(Message.class);
var bean2 = ctx.getBean(Message.class);
app.run(bean1, bean2);
ctx.close();
}
public void run(Message a, Message b) {
logger.info("running Application");
logger.info(a.getMessage());
if (a.equals(b)) {
logger.info("The beans are the same");
} else {
logger.info("The beans are not the same");
}
}
}
这是主要的应用类。
var bean1 = ctx.getBean(Message.class);
var bean2 = ctx.getBean(Message.class);
app.run(bean1, bean2);
我们从应用上下文中获取这两个 bean,并将它们传递给run()
方法进行比较。
logger.info(a.getMessage());
我们从 bean 中读取消息。
if (a.equals(b)) {
logger.info("The beans are the same");
} else {
logger.info("The beans are not the same");
}
我们测试两个 bean 是否相同。
$ mvn -q exec:java
21:28:35.573 [com.zetcode.Application.main()] INFO com.zetcode.Application - running Application
21:28:35.575 [com.zetcode.Application.main()] INFO com.zetcode.Application - Application ScopeSingleton was created by Jan Bodnar
21:28:35.576 [com.zetcode.Application.main()] INFO com.zetcode.Application - The beans are the same
我们运行该应用。 将Message
bean 的范围更改为原型并比较结果。
在本教程中,我们使用了单例 Spring bean。
您可能也对这些相关教程感兴趣: Spring 原型作用域 bean , Spring 应用的JdbcTemplate
, Spring 注入列表 XML 教程, Spring 中BeanDefinitionBuilder
教程, Spring HikariCP 教程和 Java 教程。
独立的 Spring 应用
在本教程中,我们将创建两个简单的 Java Spring 独立应用。 我们将使用 NetBeans 来构建应用。
Spring 是流行的 Java 应用框架。 它提供了用于企业应用编程的各种库和工具。 这也是一个非常好的集成系统,可以帮助将各种企业组件粘合在一起。
Spring ApplicationContext
是用于为应用提供配置的中央接口。 ClassPathXmlApplicationContext
是ApplicationContext
的实现,该实现从位于类路径上的 XML 文件加载配置定义。 AnnotationConfigApplicationContext
创建一个新的应用上下文,该上下文从给定的带注解的类派生 Bean 定义。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>SpringStandaloneEx2</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring-version>4.3.0.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
</project>
我们将 Maven 构建文件用于两个应用。 它包含必要的 Spring 依赖关系。
具有ClassPathXmlApplicationContext
的 Spring 应用
我们在 NetBeans IDE 中创建一个新的 Maven Java SE 应用。
图:NetBeans 中的 Spring 项目结构
在项目中,有四个文件:Message.java
,Application.java
,my-beans.xml
和pom.xml
。
Message.java
package com.zetcode.bean;
public class Message {
private String message;
public void setMessage(String message){
this.message = message;
}
public String getMessage(){
return message;
}
}
Message
是我们的应用中使用的简单 Java Bean。
my-beans.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="mymessage" class="com.zetcode.bean.Message">
<property name="message" value="Hello there!"/>
</bean>
</beans>
我们将Message
类制成 Spring Bean; 现在,它由 Spring 容器管理。 我们还为message
属性提供了一个值。 my-beans.xml
位于src/main/resources
子目录中。
Application.java
package com.zetcode.main;
import com.zetcode.bean.Message;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Application {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("my-beans.xml");
Message obj = (Message) context.getBean("mymessage");
String msg = obj.getMessage();
System.out.println(msg);
}
}
Application
设置 Spring 应用。
ApplicationContext context =
new ClassPathXmlApplicationContext("my-beans.xml");
从my-beans.xml
文件,创建ApplicationContext
。
Message obj = (Message) context.getBean("mymessage");
从应用上下文中,我们检索Message
bean。
String msg = obj.getMessage();
System.out.println(msg);
我们调用 bean 的getMessage()
方法,并将消息打印到控制台。
Hello there!
这是应用的输出。
具有AnnotationConfigApplicationContext
的 Spring 应用
在第二个示例中,我们将使用AnnotationConfigApplicationContext
创建 Spring ApplicationContext
。
Message.java
package com.zetcode.bean;
import org.springframework.stereotype.Component;
@Component
public class Message {
private String message = "Hello there!";
public void setMessage(String message){
this.message = message;
}
public String getMessage(){
return message;
}
}
Message
bean 用@Component
注解修饰。 此类由 Spring 自动检测。
Application.java
package com.zetcode.main;
import com.zetcode.bean.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackages = "com.zetcode")
public class Application {
public static void main(String[] args) {
ApplicationContext context
= new AnnotationConfigApplicationContext(Application.class);
Application p = context.getBean(Application.class);
p.start();
}
@Autowired
private Message message;
private void start() {
System.out.println("Message: " + message.getMessage());
}
}
这是主要的Application
类。
@ComponentScan(basePackages = "com.zetcode")
使用@ComponentScan
注解,我们告诉 Spring 在哪里寻找组件。
ApplicationContext context
= new AnnotationConfigApplicationContext(Application.class);
ApplicationContext
由注解创建。
@Autowired
private Message message;
private void start() {
System.out.println("Message: " + message.getMessage());
}
使用@Autowired
注解,Message
bean 被注入到message
变量中。
在本教程中,我们创建了两个独立的 Spring 应用。 第一个使用 XML 文件,第二个使用注解。 您可能也对相关教程感兴趣: Spring Web 应用简介, Spring Boot 优先 Web 应用或 Java 教程。
经典 Spring 应用中的JdbcTemplate
在本教程中,我们展示了如何使用JdbcTemplate
创建经典的 Spring 应用。 该应用连接到 MySQL 数据库,并使用JdbcTemplate
发出 SQL 语句。
Spring 是用于在 Java 中开发企业应用的流行 Java 应用框架。 这也是一个非常好的集成系统,可以帮助将各种企业组件粘合在一起。
JdbcTemplate
是一个库,可帮助程序员创建与关系数据库和 JDBC 一起使用的应用。 它处理许多繁琐且容易出错的底层细节,例如处理事务,清理资源以及正确处理异常。 JdbcTemplate
在 Spring 的spring-jdbc
模块中提供。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>SpringJdbcTemplateEx</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring-version>4.3.0.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
</project>
在 Maven 构建文件中,我们提供了 Spring 应用核心,JdbcTemplate
库和 MySQL 驱动程序的依赖关系。
Friend.java
package com.zetcode.bean;
public class Friend {
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Friend{" + "id=" + id + ", name=" +
name + ", age=" + age + '}';
}
}
这是一个Friend
类。 数据库表中的一行将映射到此类。
my-beans.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/testdb?useSSL=false"/>
<property name="username" value="testuser"/>
<property name="password" value="test623"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
在我们称为my-beans.xml
的应用上下文 XML 文件中,我们定义了两个 bean:数据源 bean 和jdbcTemplate
bean。 数据源 bean 包含数据源属性。 jdbcTemplate
通过ref
属性引用dataSource
bean。 my-beans.xml
位于src/main/resources
子目录中。
SpringJdbcTemplateEx.java
package com.zetcode;
import com.zetcode.bean.Friend;
import java.util.List;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
public class SpringJdbcTemplateEx {
public static void main(String[] args) {
ApplicationContext ctx
= new ClassPathXmlApplicationContext("my-beans.xml");
JdbcTemplate jdbcTemplate = (JdbcTemplate) ctx.getBean("jdbcTemplate");
jdbcTemplate.execute("DROP TABLE IF EXISTS Friends");
jdbcTemplate.execute("CREATE TABLE Friends(Id INT, Name VARCHAR(30), "
+ "Age INT)");
jdbcTemplate.update("INSERT INTO Friends VALUES(1, 'Paul', 27)");
jdbcTemplate.update("INSERT INTO Friends VALUES(2, 'Monika', 34)");
jdbcTemplate.update("INSERT INTO Friends VALUES(3, 'Peter', 20)");
jdbcTemplate.update("INSERT INTO Friends VALUES(4, 'Lucy', 45)");
jdbcTemplate.update("INSERT INTO Friends VALUES(5, 'Roman', 57)");
int id = 1;
String sql = "SELECT * FROM Friends WHERE Id=?";
Friend f = (Friend) jdbcTemplate.queryForObject(sql, new Object[]{id},
new BeanPropertyRowMapper(Friend.class));
System.out.println(f);
List<Friend> allFriends = jdbcTemplate.query("SELECT * FROM Friends",
new BeanPropertyRowMapper(Friend.class));
allFriends.stream().forEach(System.out::println);
}
}
SpringJdbcTemplateEx
设置 Spring 应用。
ApplicationContext context =
new ClassPathXmlApplicationContext("my-beans.xml");
从my-beans.xml
文件,创建ApplicationContext
。 Spring ApplicationContext
是为应用提供配置的中央接口。 ClassPathXmlApplicationContext
是ApplicationContext
的实现,可从位于类路径上的 XML 文件加载配置定义。
JdbcTemplate jdbcTemplate = (JdbcTemplate) ctx.getBean("jdbcTemplate");
从应用上下文中,我们获得jdbcTemplate
bean。
jdbcTemplate.execute("DROP TABLE IF EXISTS Friends");
jdbcTemplate.execute("CREATE TABLE Friends(Id INT, Name VARCHAR(30), "
+ "Age INT)");
使用JdbcTemplate
的execute()
方法,我们创建了Friends
表。
jdbcTemplate.update("INSERT INTO Friends VALUES(1, 'Paul', 27)");
我们使用JdbcTemplate
的update()
方法插入一条语句。
int id = 1;
String sql = "SELECT * FROM Friends WHERE Id=?";
在此 SQL 语句中,我们选择一个由其 ID 标识的朋友。
Friend f = (Friend) jdbcTemplate.queryForObject(sql, new Object[]{id},
new BeanPropertyRowMapper(Friend.class));
JdbcTemplate
的queryForObject()
方法执行 SQL 查询并返回结果对象。 使用BeanPropertyRowMapper
将结果对象映射到Friend
对象。
List<Friend> allFriends = jdbcTemplate.query("SELECT * FROM Friends",
new BeanPropertyRowMapper(Friend.class));
allFriends.stream().forEach(System.out::println);
使用JdbcTemplate
的query()
方法,我们检索所有朋友并将其打印到控制台。
Friend{id=1, name=Paul, age=27}
Friend{id=1, name=Paul, age=27}
Friend{id=2, name=Monika, age=34}
Friend{id=3, name=Peter, age=20}
Friend{id=4, name=Lucy, age=45}
Friend{id=5, name=Roman, age=57}
这是示例的输出。
在本教程中,我们创建了一个经典的 Spring 应用,该应用使用JdbcTemplate
发出了 SQL 语句。 Spring 应用是用 XML 配置的。 您可能也对这些相关教程感兴趣: JdbcTemplate
教程, Spring Web 应用简介, Spring Boot 第一个 Web 应用或 Java 教程。
Spring EmbeddedDatabaseBuilder
教程
Spring EmbeddedDatabaseBuilder
教程展示了如何使用EmbeddedDatabaseBuilder
在 Spring 应用中创建 H2 嵌入式数据库。
Spring 是流行的 Java 应用框架。
EmbeddedDatabaseBuilder
EmbeddedDatabaseBuilder
是一个 Spring 构建器,它提供方便的 API 在 Spring 应用中创建嵌入式数据库。
Spring EmbeddedDatabaseBuilder
示例
以下示例使用EmbeddedDatabaseBuilder
构建嵌入式 H2 数据库。 我们使用 Spring JdbcTemplate
与数据库进行交互。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ │ Application.java
│ │ ├───config
│ │ │ DBConfig.java
│ │ └───model
│ │ Car.java
│ └───resources
│ │ logback.xml
│ └───db
│ create-db.sql
│ insert-data.sql
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>embeddeddatabasebuilderex</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.197</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.zetcode.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
这是我们 Spring 应用的 Maven 构建文件。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
这是 Logback 配置文件。
EmbeddedDatabaseBuilder
将使用以下两个 SQL 脚本来创建cars
表并将数据插入其中。
resources/db/schema.sql
CREATE TABLE cars(id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(150), price INT);
schema.sql
创建数据库表。
resources/db/data.sql
INSERT INTO cars(name, price) VALUES('Audi', 52642);
INSERT INTO cars(name, price) VALUES('Mercedes', 57127);
INSERT INTO cars(name, price) VALUES('Skoda', 9000);
INSERT INTO cars(name, price) VALUES('Volvo', 29000);
INSERT INTO cars(name, price) VALUES('Bentley', 350000);
INSERT INTO cars(name, price) VALUES('Citroen', 21000);
INSERT INTO cars(name, price) VALUES('Hummer', 41400);
INSERT INTO cars(name, price) VALUES('Volkswagen', 21600);
data.sql
将数据插入表中。
com/zetcode/model/Car.java
package com.zetcode.model;
import java.util.Objects;
public class Car {
private Long id;
private String name;
private int price;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Car car = (Car) o;
return price == car.price &&
Objects.equals(id, car.id) &&
Objects.equals(name, car.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name, price);
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("Car{");
sb.append("id=").append(id);
sb.append(", name='").append(name).append('\'');
sb.append(", price=").append(price);
sb.append('}');
return sb.toString();
}
}
这是一个Car
类。
com/zetcode/config/DBConfig.java
package com.zetcode.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import javax.sql.DataSource;
@Configuration
public class DBConfig {
@Bean
public DataSource dataSource() {
var builder = new EmbeddedDatabaseBuilder();
var db = builder
.setType(EmbeddedDatabaseType.H2) // HSQL or DERBY
.addScript("db/schema.sql")
.addScript("db/data.sql")
.build();
return db;
}
@Bean
public JdbcTemplate createJdbcTeamplate() {
var template = new JdbcTemplate();
template.setDataSource(dataSource());
return template;
}
}
DBConfig
使用EmbeddedDatabaseBuilder
创建嵌入式 H2 数据库。 我们还创建了一个JdbcTemplate
bean。
@Bean
public DataSource dataSource() {
var builder = new EmbeddedDatabaseBuilder();
var db = builder
.setType(EmbeddedDatabaseType.H2) // HSQL or DERBY
.addScript("db/schema.sql")
.addScript("db/data.sql")
.build();
return db;
}
该方法使用EmbeddedDatabaseBuilder
的build()
方法创建数据源。 我们使用setType()
指定数据库类型,并使用addScript()
方法添加 SQL 脚本。
@Bean
public JdbcTemplate createJdbcTeamplate() {
var template = new JdbcTemplate();
template.setDataSource(dataSource());
return template;
}
此方法生成一个新的JdbcTemplate
。 我们使用setDataSource()
将生成的数据源设置为模板。
com/zetcode/Application.java
package com.zetcode;
import com.zetcode.model.Car;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
@ComponentScan(basePackages = "com.zetcode")
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
var ctx = new AnnotationConfigApplicationContext(Application.class);
var app = ctx.getBean(Application.class);
app.run();
ctx.close();
}
@Autowired
private JdbcTemplate jdbcTemplate;
private void run() {
var sql = "SELECT * FROM cars";
var cars = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Car.class));
cars.forEach(car -> logger.info("{}", car));
}
}
在应用中,我们执行查询以查找所有汽车。
@Autowired
private JdbcTemplate jdbcTemplate;
注入了JdbcTemplate
bean。
var cars = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Car.class));
使用JdbcTemplate
的query()
方法执行 SQL 查询。
cars.forEach(car -> logger.info("{}", car));
检索到的汽车将写入控制台。
$ mvn -q exec:java
19:13:35.753 INFO com.zetcode.Application - Car{id=1, name='Audi', price=52642}
19:13:35.768 INFO com.zetcode.Application - Car{id=2, name='Mercedes', price=57127}
19:13:35.768 INFO com.zetcode.Application - Car{id=3, name='Skoda', price=9000}
19:13:35.768 INFO com.zetcode.Application - Car{id=4, name='Volvo', price=29000}
19:13:35.768 INFO com.zetcode.Application - Car{id=5, name='Bentley', price=350000}
19:13:35.768 INFO com.zetcode.Application - Car{id=6, name='Citroen', price=21000}
19:13:35.768 INFO com.zetcode.Application - Car{id=7, name='Hummer', price=41400}
19:13:35.768 INFO com.zetcode.Application - Car{id=8, name='Volkswagen', price=21600}
我们运行该应用。
在本教程中,我们使用EmbeddedDatabaseBuilder
在 Spring 应用中创建嵌入式 H2 数据库。
您可能也对相关教程感兴趣: JdbcTemplate
教程, Spring @ComponentScan
教程和 Java 教程,
Spring HikariCP 教程
在本教程中,我们将展示如何在经典的 Spring 应用中使用 HikariCP 连接池。 在应用中,我们使用 Spring JdbcTemplate
连接到 MySQL 数据库。 我们使用 FreeMarker 作为模板引擎。 该应用已部署在 Tomcat 服务器上。
Spring 是用于在 Java 中开发企业应用的流行 Java 应用框架。 这也是一个非常好的集成系统,可以帮助将各种企业组件粘合在一起。
HikariCP 是可靠的高性能 JDBC 连接池。 连接池是数据库系统维护的数据库连接的高速缓存,用于在需要将来对数据库的请求时重用连接。 使用连接池,我们可以大大减少整体资源的使用。
JdbcTemplate
是一个 Spring 库,可以帮助程序员创建与关系数据库和 JDBC 一起使用的应用。 它会处理许多繁琐且容易出错的底层细节,例如处理事务,清理资源以及正确处理异常。 JdbcTemplate
在 Spring 的spring-jdbc
模块中提供。
cars.sql
-- SQL for the Cars table
START TRANSACTION;
DROP TABLE IF EXISTS Cars;
CREATE TABLE Cars(Id INTEGER PRIMARY KEY, Name VARCHAR(50), Price INTEGER);
INSERT INTO Cars VALUES(1, 'Audi', 52642);
INSERT INTO Cars VALUES(2, 'Mercedes', 57127);
INSERT INTO Cars VALUES(3, 'Skoda', 9000);
INSERT INTO Cars VALUES(4, 'Volvo', 29000);
INSERT INTO Cars VALUES(5, 'Bentley', 350000);
INSERT INTO Cars VALUES(6, 'Citroen', 21000);
INSERT INTO Cars VALUES(7, 'Hummer', 41400);
INSERT INTO Cars VALUES(8, 'Volkswagen', 21600);
COMMIT;
在代码示例中,我们使用此表。
mysql> source cars.sql
使用mysql
命令行工具及其source
命令,创建Cars
表。 MySQL 教程提供了有关如何设置和使用 MySQL 数据库的更多信息。
├── pom.xml
└── src
├── main
│ ├── java
│ │ └── com
│ │ └── zetcode
│ │ ├── bean
│ │ │ └── Car.java
│ │ ├── service
│ │ │ └── CarService.java
│ │ └── web
│ │ └── MyController.java
│ ├── resources
│ │ └── application-context.xml
│ └── webapp
│ ├── META-INF
│ │ └── context.xml
│ └── WEB-INF
│ ├── spring-servlet.xml
│ ├── views
│ │ ├── allCars.ftl
│ │ └── index.ftl
│ └── web.xml
└── test
└── java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>SpringJdbcTemplateWebEx</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>SpringJdbcTemplateWebEx</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring-version>4.3.7.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.25-incubating</version>
</dependency>
<!--Needed for freemarker FreeMarkerConfigurer-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.22</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
</project>
在此 Maven 构建文件中,我们为 Spring 应用的核心,HikariCP 连接池,FreeMarker 模板引擎,JdbcTemplate
库和 MySQL 驱动程序提供依赖关系。
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
</web-app>
在web.xml
文件中,我们设置了 Spring DispatcherServlet
。 DispatcherServlet
是 HTTP 请求处理器的中央调度器。
context.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/SpringJdbcTemplateWebEx">
<Resource name="jdbc/myDs" auth="Container"
factory="com.zaxxer.hikari.HikariJNDIFactory"
dataSourceClassName="com.mysql.jdbc.jdbc2.optional.MysqlDataSource"
dataSource.url="jdbc:mysql://localhost/testdb?useSSL=false"
type="javax.sql.DataSource"
minimumIdle="5"
maximumPoolSize="10"
connectionTimeout="300000"
database="testdb"
server="localhost"
dataSource.user="testuser"
dataSource.password="test623"
dataSource.cachePrepStmts="true"
dataSource.prepStmtCacheSize="250"
dataSource.prepStmtCacheSqlLimit="2048"
closeMethod="close"
/>
</Context>
Tomcat 的context.xml
文件包含数据源定义。 数据源使用 HikariCP 连接池。
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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.zetcode" />
<import resource="classpath:application-context.xml" />
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/views/"/>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="cache" value="true"/>
<property name="prefix" value=""/>
<property name="suffix" value=".ftl"/>
</bean>
</beans>
在 spring servlet 上下文 XML 文件中,我们定义了两个 bean:freemarkerConfig
和viewResolver
。 这些是 FreeMarker 的配置 bean。 spring-servlet.xml
位于WEB-INF
子目录中。
<context:component-scan base-package="com.zetcode" />
我们启用com.zetcode
封装的组件扫描。
<import resource="classpath:application-context.xml" />
我们导入另一个上下文文件,称为application-context.xml
。 它位于src/main/resources
目录中的类路径上。
application-context.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/myDs"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
在application-context.xml
中,我们定义了两个 bean:dataSource
和jdbcTemplate
。
Car.java
package com.zetcode.bean;
public class Car {
private int Id;
private String Name;
private int Price;
public int getId() {
return Id;
}
public void setId(int Id) {
this.Id = Id;
}
public String getName() {
return Name;
}
public void setName(String Name) {
this.Name = Name;
}
public int getPrice() {
return Price;
}
public void setPrice(int Price) {
this.Price = Price;
}
@Override
public String toString() {
return "Car{" + "Id=" + Id + ", Name=" +
Name + ", Price=" + Price + '}';
}
}
这是一个Car
类。 数据库表中的一行将映射到此类。
CarService.java
package com.zetcode.service;
import com.zetcode.bean.Car;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
@Service
public class CarService {
@Autowired
public JdbcTemplate jdbcTemplate;
public List<Car> getAllCars() {
String sql = "SELECT * FROM Cars";
List<Car> cars = jdbcTemplate.query(sql,
new BeanPropertyRowMapper(Car.class));
return cars;
}
}
CarService
是一个服务类,其中包含一种从数据库中检索所有汽车的方法。
@Autowired
public JdbcTemplate jdbcTemplate;
JdbcTemplate
注入了@Autowired
注解。
List<Car> cars = jdbcTemplate.query(sql,
new BeanPropertyRowMapper(Car.class));
使用JdbcTemplate
的query()
方法,我们执行 SQL 查询。 使用BeanPropertyRowMapper
将结果对象映射到Car
对象。
MyController.java
package com.zetcode.web;
import com.zetcode.bean.Car;
import com.zetcode.service.CarService;
import java.util.List;
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 org.springframework.web.servlet.ModelAndView;
@Controller
public class MyController {
@Autowired
private CarService carService;
@RequestMapping("/index")
public String index(Model model) {
return "index";
}
@RequestMapping(value = "/all", method = RequestMethod.GET)
public ModelAndView all() {
List<Car> cars = carService.getAllCars();
ModelAndView model = new ModelAndView("allCars");
model.addObject("cars", cars);
return model;
}
}
MyController
是控制器类。 它具有两个请求 URL 的映射:/index
和/all
。
@Autowired
private CarService carService;
注入CarService
。
@RequestMapping("/index")
public String index(Model model) {
return "index";
}
通过返回index.ftl
文件来解决此请求。 这些视图位于WEB-INF/views
目录中。
@RequestMapping(value = "/all", method = RequestMethod.GET)
public ModelAndView all() {
List<Car> cars = carService.getAllCars();
ModelAndView model = new ModelAndView("allCars");
model.addObject("cars", cars);
return model;
}
在这里,我们调用CarService
的getAllCars()
方法并创建ModelAndView
对象。 所检索的数据被发送到allCars.ftl
模板。
index.ftl
<!DOCTYPE html>
<html>
<head>
<title>Home page</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<p>Showing <a href="all.html">all cars</a></p>
</body>
</html>
这是index.ftl
文件。
allCars.ftl
<!DOCTYPE html>
<html>
<head>
<title>Cars</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<table>
<tr>
<th>Id</th>
<th>Name</th>
<th>Price</th>
</tr>
<#list cars as car>
<tr>
<td>${car.id}</td>
<td>${car.name}</td>
<td>${car.price}</td>
</tr>
</#list>
</table>
</body>
</html>
该模板文件处理从数据库发送的数据。
<#list cars as car>
#list
指令列出了数据集合。
图:显示所有汽车
MySQL 数据库中的数据显示在 Opera 浏览器中。
在本教程中,我们创建了一个经典的 Spring 应用,该应用使用JdbcTemplate
对 MySQL 数据库执行了 SQL 语句。 我们使用了 HikariCP 连接池。 Spring 应用使用 FreeMarker 模板引擎,并已部署在 Tomcat 服务器上。 您可能也对这些相关教程感兴趣:使用 HikariCP 连接池, JdbcTemplate
教程, Spring 单例范围 bean 教程, Spring Web 应用简介 , Spring Boot 第一个 Web 应用或 Java 教程。
Spring Web 应用简介
在本教程中,我们将在 Spring 中创建简单的 Web 应用。 创建了三个 Web 应用。 每个应用都以不同的方式配置。
在我们的 Spring Web 应用中,我们使用 Spring 5 和 Thymeleaf 3。
Spring 是流行的 Java 应用框架。 Spring Boot 致力于以最小的努力来创建独立的,生产级的基于 Spring 的应用。
有三种配置 Spring Web 应用的基本方法:
- XML 格式
- Java 配置
- Spring Boot 自动配置
传统上,Spring 使用 XML 文件来配置应用。 后来,创建了一种新方法,其中在 Java 配置类中完成配置。 Spring Boot 自动配置魔术是配置 Spring Web 应用的最新方法。
使用 XML 的 Spring Web 应用配置
在第一个示例中,我们创建一个以 XML 文件配置的 Spring Web 应用。
pom.mxl
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ └───controller
│ │ HomeController.java
│ ├───resources
│ └───webapp
│ │ index.html
│ └───WEB-INF
│ │ spring-servlet.xml
│ │ web.xml
│ └───templates
│ showMessage.html
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>springwebfirst</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
</plugins>
</build>
</project>
这是 Maven 构建文件。 我们具有以下依赖关系:slf4j-api
和slf4j-simple
用于日志记录,javax.servlet-api
用于 Java Servlet 技术,thymeleaf-spring5
和thymeleaf
用于 Thymeleaf 模板引擎,以及spring-webmvc
用于创建 Spring Web MVC 应用。
maven-war-plugin
创建 Web 存档(WAR)。
WEB-INF/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: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/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.zetcode"/>
<mvc:annotation-driven/>
<mvc:default-servlet-handler/>
<bean id="templateResolver"
class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<property name="prefix" value="/WEB-INF/templates/"/>
<property name="suffix" value=".html"/>
<property name="templateMode" value="HTML"/>
</bean>
<bean class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="templateEngine" ref="templateEngine"/>
</bean>
<bean id="templateEngine" class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver"/>
</bean>
</beans>
spring-servlet.xml
配置 Spring Web 应用。 它启用组件扫描,Spring Web 注解(@Controller
)并配置 Thymeleaf 模板。
<context:component-scan base-package="com.zetcode" />
这告诉 Spring 在哪里寻找带有@Controller
,@Repository
,@Service
,@Component
注解的类并进行注册。 在我们的例子中,我们有一个带有@Controller
注解的控制器。
<mvc:annotation-driven/>
<mvc:annotation-driven/>
启用基于 Web 的 Spring 注解。
<mvc:default-servlet-handler/>
我们需要此标记来启用静态 HTML 文件。 主页上有一个静态的index.html
。
<bean id="templateResolver"
class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<property name="prefix" value="/WEB-INF/templates/"/>
<property name="suffix" value=".html"/>
<property name="templateMode" value="HTML"/>
</bean>
<bean class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="templateEngine" ref="templateEngine"/>
</bean>
<bean id="templateEngine" class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver"/>
</bean>
这些行用模板引擎,模板视图解析器和模板解析器配置 Thymeleaf。 在模板解析器中,我们指定模板的位置及其扩展名。
WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
</web-app>
在web.xml
文件中,我们设置了 Spring DispatcherServlet
并选择了欢迎文件。 DispatcherServlet
是 Spring 的前端控制器。 该 Servlet 映射到扩展名为*.html
的 URL。
com/zetcode/controller/HomeController.java
package com.zetcode.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HomeController {
@GetMapping("/message")
public String message() {
return "showMessage";
}
}
HTTP 请求由控制器处理。 它准备一个模型并返回一个视图。 返回的showMessage
字符串映射到位于WEB-INF/templates/
目录中的showMessage.html
文件。
WEB-INF/templates/showMessage.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Message</title>
</head>
<body>
<p>
Hello there
</p>
</body>
</html>
showMessage.html
文件显示一条消息。
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Home page</title>
</head>
<body>
<p>
<a href="message">Show message</a>
</p>
</body>
</html>
index.html
是主页。 它包含一个链接。
使用 Java 配置进行 Spring Web 应用配置
在第二个示例中,我们创建一个在 Java 配置类中配置的 Spring Web 应用。 在该示例中,web.xml
和spring-servlet.xml
被替换为MyWebInitializer.java
和WebConfig.java
。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ ├───config
│ │ │ MyWebInitializer.java
│ │ │ WebConfig.java
│ │ └───controller
│ │ MyController.java
│ ├───resources
│ └───webapp
│ └───WEB-INF
│ └───templates
│ index.html
│ showMessage.html
└───test
└───java
这是项目结构。 pom.xml
文件与第一个示例中的相同。
com/zetcode/config/WebConfig.java
package com.zetcode.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.zetcode"})
public class WebConfig implements WebMvcConfigurer {
@Autowired
private ApplicationContext applicationContext;
@Bean
public SpringResourceTemplateResolver templateResolver() {
var templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix("/WEB-INF/templates/");
templateResolver.setSuffix(".html");
return templateResolver;
}
@Bean
public SpringTemplateEngine templateEngine() {
var templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
@Bean
public ViewResolver viewResolver() {
var resolver = new ThymeleafViewResolver();
var registry = new ViewResolverRegistry(null, applicationContext);
resolver.setTemplateEngine(templateEngine());
registry.viewResolver(resolver);
return resolver;
}
}
使用WebConfig.java
代替spring-servlet.xml
文件。 在WebConfig
中,我们使用@EnableWebMvc
启用 Spring Web 注解,使用@ComponentScan
启用组件扫描,并配置 Thymeleaf 模板引擎。
com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
使用MyWebInitializer
类代替web.xml
文件。 我们指定 servlet 配置类的名称。
com/zetcode/controller/MyController.java
package com.zetcode.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MyController {
@GetMapping("/")
public String index() {
return "index";
}
@GetMapping("/message")
public String message() {
return "showMessage";
}
}
这是控制器。 我们有主页和showMessage
页面的映射。
WEB-INF/templates/showMessage.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Message</title>
</head>
<body>
<p>Today is a sunny day!</p>
</body>
</html>
showMessage.html
文件显示一条消息。
WEB-INF/templates/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Home page</title>
</head>
<body>
<p>
<a href="message.html">Show message</a>
</p>
</body>
</html>
index.html
是主页。 它包含一个链接。
Spring Boot Web 应用
在第三个示例中,我们使用 Spring Boot 创建一个 Web 应用。 Spring Boot 使用另一种默认方法。 它通过嵌入式 Web 服务器使用 JAR 存档。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ │ Application.java
│ │ └───controller
│ │ MyController.java
│ └───resources
│ │ application.properties
│ ├───static
│ │ index.html
│ └───templates
│ showMessage.html
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>springbootwebfirst</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
这是 Maven 构建文件。 spring-boot-starter-web
是使用 Spring MVC 构建 Web(包括 RESTful)应用的入门 POM。 spring-boot-starter-thymeleaf
是 Thymeleaf 模板引擎的启动器 POM。
请注意,包装设置为 JAR。
com/zetcode/controller/MyController.java
package com.zetcode.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MyController {
@GetMapping("/message")
public String message() {
return "showMessage";
}
}
这是 Spring Boot Web 应用的控制器类。 控制器以@Controller
注解修饰。 控制器具有一个映射。 映射解析为showMessage.html
模板,该模板位于WEB-INF/templates
目录中。
Application.java
package com.zetcode;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Application
设置 Spring Boot 应用。
WEB-INF/templates/showMessage.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Message</title>
</head>
<body>
<p>Today is a cold day</p>
</body>
</html>
showMessage.html
显示一条简单消息。
WEB-INF/static/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Home page</title>
</head>
<body>
<p>
<a href="message">Show message</a>
</p>
</body>
</html>
index.html
是包含链接的应用的主页。 静态资源(例如,纯 HTML 文件)被放入static
目录。
在本教程中,我们创建了第一个 Spring Web 应用。 您可能也对相关教程感兴趣:独立的 Spring 应用, FreeMarker 教程, Java 教程, Spring DefaultServlet
教程, Spark 简介或Strips 简介。
Spring BeanPropertyRowMapper
教程
Spring BeanPropertyRowMapper
教程展示了如何使用BeanPropertyRowMapper
将表行转换为指定 Bean 类的新实例。
Spring 是用于创建企业应用的流行 Java 应用框架。
Spring BeanPropertyRowMapper
BeanPropertyRowMapper
是RowMapper
执行该表的行转换成指定的映射的目标类的一个新实例。 映射的目标类必须是顶级类,并且必须具有默认或无参数构造器。
Spring BeanPropertyRowMapper
示例
以下应用使用BeanPropertyRowMapper
从coutries
表中读取所有行。 在示例中,我们使用 MySQL 数据库。
countries.sql
CREATE TABLE countries(id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255), population INT);
INSERT INTO countries(name, population) VALUES('China', 1382050000);
INSERT INTO countries(name, population) VALUES('India', 1313210000);
INSERT INTO countries(name, population) VALUES('USA', 324666000);
INSERT INTO countries(name, population) VALUES('Indonesia', 260581000);
INSERT INTO countries(name, population) VALUES('Brazil', 207221000);
INSERT INTO countries(name, population) VALUES('Pakistan', 196626000);
INSERT INTO countries(name, population) VALUES('Nigeria', 186988000);
INSERT INTO countries(name, population) VALUES('Bangladesh', 162099000);
INSERT INTO countries(name, population) VALUES('Nigeria', 186988000);
INSERT INTO countries(name, population) VALUES('Russia', 146838000);
INSERT INTO countries(name, population) VALUES('Japan', 126830000);
INSERT INTO countries(name, population) VALUES('Mexico', 122273000);
INSERT INTO countries(name, population) VALUES('Philippines', 103738000);
这是我们示例的一些测试数据。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ │ Application.java
│ │ ├───config
│ │ │ DBConfig.java
│ │ └───model
│ │ Country.java
│ └───resources
│ db.properties
│ logback.xml
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>springbeanpropertyrowmapperex</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.zetcode.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们声明了基本的 Spring 依赖关系。 BeanPropertyRowMapper
是spring-jdbc
的一部分。
resources/db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mydb
jdbc.username=user7
jdbc.password=s$cret
我们在外部文件中具有基本的数据库属性。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} [%thread] %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
com/zetcode/model/Country.java
package com.zetcode.model;
import java.util.Objects;
public class Country {
private Long id;
private String name;
private int population;
public Country() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPopulation() {
return population;
}
public void setPopulation(int population) {
this.population = population;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Country country = (Country) o;
return population == country.population &&
Objects.equals(id, country.id) &&
Objects.equals(name, country.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name, population);
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("Country{");
sb.append("id=").append(id);
sb.append(", name='").append(name).append('\'');
sb.append(", population=").append(population);
sb.append('}');
return sb.toString();
}
}
这是Country
bean。 它具有id
,name
和population
属性。
com/zetcode/config/DBConfig.java
package com.zetcode.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
@Configuration
@PropertySource(value="classpath:db.properties", ignoreResourceNotFound=true)
public class DBConfig {
@Autowired
private Environment env;
@Bean
public DataSource dataSource() {
var dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driver"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.username"));
dataSource.setPassword(env.getProperty("jdbc.password"));
return dataSource;
}
@Bean
public JdbcTemplate jdbcTemplate() {
var template = new JdbcTemplate();
template.setDataSource(dataSource());
return template;
}
}
DBConfig
配置dataSource
和jdbcTemplate
bean。 它从db.properties
文件读取配置数据。
com/zetcode/Application.java
package com.zetcode;
import com.zetcode.model.Country;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
@ComponentScan("com.zetcode")
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
var ctx = new AnnotationConfigApplicationContext(Application.class);
var app = ctx.getBean(Application.class);
app.run();
ctx.close();
}
@Autowired
private JdbcTemplate jdbcTemplate;
private void run() {
var sql = "SELECT * FROM countries";
var rowMapper = BeanPropertyRowMapper.newInstance(Country.class);
var countries = jdbcTemplate.query(sql, rowMapper);
countries.forEach(country -> logger.info("{}", country));
}
}
这是主要的应用类。
var sql = "SELECT * FROM countries";
我们定义一个查询以从countries
表中检索所有行。
var rowMapper = BeanPropertyRowMapper.newInstance(Country.class);
我们为Country
类创建BeanPropertyRowMapper
的新实例。
var countries = jdbcTemplate.query(sql, rowMapper);
JdbcTemplate
的query()
执行 SQL 查询。 由于BeanPropertyRowMapper
,表列自动映射到 bean 属性。
$ mvn -q exec:java
12:47:37.079 INFO com.zetcode.Application - Country{id=1, name='China', population=1382050000}
12:47:37.082 INFO com.zetcode.Application - Country{id=2, name='India', population=1313210000}
12:47:37.083 INFO com.zetcode.Application - Country{id=3, name='USA', population=324666000}
12:47:37.084 INFO com.zetcode.Application - Country{id=4, name='Indonesia', population=260581000}
12:47:37.084 INFO com.zetcode.Application - Country{id=5, name='Brazil', population=207221000}
12:47:37.085 INFO com.zetcode.Application - Country{id=6, name='Pakistan', population=196626000}
12:47:37.086 INFO com.zetcode.Application - Country{id=7, name='Nigeria', population=186988000}
12:47:37.087 INFO com.zetcode.Application - Country{id=8, name='Bangladesh', population=162099000}
12:47:37.088 INFO com.zetcode.Application - Country{id=9, name='Nigeria', population=186988000}
12:47:37.088 INFO com.zetcode.Application - Country{id=10, name='Russia', population=146838000}
12:47:37.089 INFO com.zetcode.Application - Country{id=11, name='Japan', population=126830000}
12:47:37.090 INFO com.zetcode.Application - Country{id=12, name='Mexico', population=122273000}
12:47:37.090 INFO com.zetcode.Application - Country{id=13, name='Philippines', population=103738000}
我们运行该应用。
在本教程中,我们使用BeanPropertyRowMapper
将表行映射到 bean 属性。
您可能也对这些相关教程感兴趣:经典的 Spring 应用中的 JdbcTemplate
, Spring HikariCP 教程和 Java 教程,或列出了整个 Spring 教程。
Spring @GetMapping
教程
Spring @GetMapping
教程展示了如何使用@GetMapping
注解将 HTTP GET 请求映射到特定的处理器方法。
Spring 是用于创建企业应用的流行 Java 应用框架。
@GetMapping
@GetMapping
注解将 HTTP GET 请求映射到特定的处理器方法。 它是一个组合的注解,用作@RequestMapping(method = RequestMethod.GET)
的快捷方式。
Spring @GetMapping
示例
以下应用使用@GetMapping
将两个请求路径映射到处理器方法。 在此示例中,我们使用注解来设置 Spring Web 应用。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ ├───config
│ │ │ MyWebInitializer.java
│ │ │ WebConfig.java
│ │ └───controller
│ │ MyController.java
│ └───resources
│ logback.xml
└───test
└───java
└───com
└───zetcode
└───controller
MyControllerTest.java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>getmapping</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.14.v20181114</version>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有以下依存关系:logback-classic
,javax.servlet-api
,junit
,spring-webmvc
和spring-test
。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
@Configuration
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
MyWebInitializer
注册 Spring DispatcherServlet
,它是 Spring Web 应用的前端控制器。
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
getServletConfigClasses()
返回 Web 配置类。
com/zetcode/config/WebConfig.java
package com.zetcode.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.zetcode"})
public class WebConfig {
}
WebConfig
通过@EnableWebMvc
启用 Spring MVC 注解,并为com.zetcode
包配置组件扫描。
com/zetcode/controller/MyController.java
package com.zetcode.controller;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@GetMapping(value="/", produces = MediaType.TEXT_PLAIN_VALUE)
public String index() {
return "This is Home page";
}
@GetMapping(value="/hello", produces = MediaType.TEXT_PLAIN_VALUE)
public String sayHello() {
return "Hello there!";
}
}
MyController
提供请求路径和处理器方法之间的映射。
@RestController
public class MyController {
@RestController
用于创建不使用视图技术的静态控制器。 这些方法通常返回 XML,JSON 或纯文本。
@GetMapping(value="/", produces = MediaType.TEXT_PLAIN_VALUE)
public String index() {
return "This is Home page";
}
@GetMapping
将从 GET 请求到index()
方法的/
根路径映射。 它返回纯文本。
com/zetcode/controller/MyControllerTest.java
package com.zetcode.controller;
import org.junit.Before;
import org.junit.Test;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
public class MyControllerTest {
private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.standaloneSetup(new MyController()).build();
}
@Test
public void testHomePage() throws Exception {
this.mockMvc.perform(get("/")).andExpect(status().isOk())
.andExpect(content().string("This is Home page"));
}
@Test
public void testHelloPage() throws Exception {
this.mockMvc.perform(get("/hello")).andExpect(status().isOk())
.andExpect(content().string("Hello there!"));
}
}
MyControllerTest
测试两个页面。
$ curl localhost:8080
This is Home page
$ curl localhost:8080/hello
Hello there!
我们运行该应用,并使用curl
工具创建两个 GET 请求。
在本教程中,我们介绍了@GetMapping
注解。
您可能也对这些相关教程感兴趣: Spring @PostMapping
教程, Spring 单例范围 bean , Spring @ComponentScan
教程, Spring 配置文件 XML 教程 或 Java 教程或列出所有 Spring 教程。
Spring DefaultServlet
教程
Spring DefaultServlet
教程展示了如何在 Spring 应用中启用默认 servlet。
Spring 是流行的 Java 应用框架。 在本教程中,我们使用 Spring 5 版本。
DefaultServlet
DefaultServlet
是大多数 Web 应用的默认资源服务 Servlet,用于提供 HTML 页面和图像等静态资源。
DefaultServletHttpRequestHandler
尝试在启动时自动检测容器的默认 Servlet,例如 Tomcat,Jetty,Wildfly 和 Resin。 如果默认 Servlet 是使用其他名称自定义配置的,则必须明确提供默认 Servlet 的名称。
如果我们重写DefaultServlet
的路由(/
),则可以使用DefaultServletHandlerConfigurer
的enable()
方法启用它,以便我们仍然可以使用容器的默认 Servlet 提供静态资源。
Spring DefaultServlet
示例
在以下应用中,我们将 Spring 调度器 servlet 配置为/
路径,该路径将重写默认 servlet 的路径。 我们使用DefaultServletHandlerConfigurer
启用默认 servlet。
该应用提供一个简单的 HTML 主页,这是一个静态资源。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ └───config
│ │ MyWebInitializer.java
│ │ WebConfig.java
│ ├───resources
│ │ logback.xml
│ └───webapp
│ index.html
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>defaultservletex</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
</plugins>
</build>
</project>
这是 Maven 构建文件。 我们具有以下依赖项:用于 Java Servlet 技术的javax.servlet-api
,用于日志记录的logback-classic
和用于创建 Spring Web MVC 应用的spring-webmvc
。
maven-war-plugin
创建 Web 存档(WAR)。
com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
MyWebInitializer
初始化 Spring Web 应用。
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
我们将Spring DispatcherServlet
注册到/
路径。 这代替了DefaultServlet
; 因此,我们必须在配置文件中注册一个默认的 servlet 处理器。
com/zetcode/config/WebConfig.java
package com.zetcode.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
WebConfig
通过@EnableWebMvc
启用 Spring MVC,并通过DefaultServletHandlerConfigurer
的enable()
方法配置DefaultServlet
。
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
configureDefaultServletHandling()
使用 URL 映射/**
和相对于其他 URL 映射的最低优先级来配置DefaultServletHttpRequestHandler
。 这样,静态资源请求由容器的默认 Servlet 处理。
webapp/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Home page</title>
</head>
<body>
<p>
This is home page.
</p>
</body>
</html>
这是主页。 它是静态资源,由DefaultServlet
自动提供服务。
$ curl localhost:8080
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Home page</title>
</head>
<body>
<p>
This is home page.
</p>
</body>
</html>
当我们运行应用时,将提供主页。
在本教程中,我们展示了如何在 Spring 应用中注册默认 servlet。 您可能也对相关教程感兴趣:独立的 Spring 应用,Spring WebSocket 教程,Spring 自定义 404 错误页面教程,Spring WebApplicationInitializer
教程,Spring Web 应用简介,Java 教程。
Spring WebSocket 教程
Spring WebSocket 教程展示了如何在 Spring Web 应用中使用 WebSocket。
Spring 是用于创建企业应用的流行 Java 应用框架。
WebSocket
WebSocket 是一种计算机通信协议,可通过单个 TCP 连接提供全双工通信通道。 WebSocket 用于高度互动的应用,例如游戏,聊天或股票市场。
TextWebSocketHandler
Spring 使用WebSocketHandler
处理 WebSocket 消息和生命周期事件。 TextWebSocketHandler
是用于处理文本消息的WebSocketHandler
实现。
Spring TextWebSocketHandler
示例
以下应用使用TextWebSocketHandler
通过 WebSocket 处理文本消息。
web.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ ├───config
│ │ │ MyWebInitializer.java
│ │ │ WebConfig.java
│ │ │ WebSocketConfig.java
│ │ └───handler
│ │ MyWebSocketHandler.java
│ ├───resources
│ └───webapp
│ │ index.html
│ └───WEB-INF
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>textwebsocketex</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>5.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有以下依存关系:spring-webmvc
,javax.servlet-api
和spring-websocket
。
com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class, WebSocketConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
MyWebInitializer
初始化 Spring Web 应用。 它提供了两个配置类:WebConfig
和WebSocket
。
com/zetcode/config/WebConfig.java
package com.zetcode.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
@ComponentScan("com.zetcode")
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
WebConfig
配置DefaultServlet
。 在我们的应用中,我们有一个静态的index.html
页面,该页面由DefaultServlet
处理。
com/zetcode/config/WebSocketConfig.java
package com.zetcode.config;
import com.zetcode.handler.MyWebSocketHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Autowired
private MyWebSocketHandler myWebSocketHandler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myWebSocketHandler, "/socketHandler");
}
}
WebSocketConfig
使用@EnableWebSocket
在 Spring Web 应用中配置 WebSocket。
@Autowired
private MyWebSocketHandler myWebSocketHandler;
我们注入MyWebSocketHandler
。 已在registerWebSocketHandlers()
中注册。
com/zetcode/config/MyWebSocketHandler.java
package com.zetcode.handler;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import java.time.LocalTime;
@Component
public class MyWebSocketHandler extends TextWebSocketHandler {
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message)
throws Exception {
var clientMessage = message.getPayload();
if (clientMessage.startsWith("hello") || clientMessage.startsWith("greet")) {
session.sendMessage(new TextMessage("Hello there!"));
} else if (clientMessage.startsWith("time")) {
var currentTime = LocalTime.now();
session.sendMessage(new TextMessage(currentTime.toString()));
} else {
session.sendMessage(new TextMessage("Unknown command"));
}
}
}
在MyWebSocketHandler
中,我们对套接字消息做出反应。
var clientMessage = message.getPayload();
通过getPayLoad()
方法,我们获得了客户端消息。
if (clientMessage.startsWith("hello") || clientMessage.startsWith("greet")) {
session.sendMessage(new TextMessage("Hello there!"));
} else if (clientMessage.startsWith("time")) {
var currentTime = LocalTime.now();
session.sendMessage(new TextMessage(currentTime.toString()));
} else {
session.sendMessage(new TextMessage("Unknown command"));
}
根据消息,我们将TextMessage
发送回客户端。
webapp/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Home page</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.3.1/semantic.min.css"
rel="stylesheet">
</head>
<body>
<div class="ui container">
<h1>Spring MVC 5 WebSocket</h1>
<div class="two column grid">
<div class="row">
<div class="column">
<label for="myMessage">Message</label>
</div>
<div class="column">
<div class="ui input">
<input type="text" id="myMessage">
</div>
</div>
</div>
<div class="row">
<div class="column">
<label for="output">Response from Server</label>
</div>
<div class="column">
<textarea rows="8" cols="50" id="output" readonly="readonly"></textarea>
</div>
</div>
<div class="row">
<button class="ui button" onclick="send()">Send</button>
</div>
</div>
</div>
<script>
const socketConn = new WebSocket('ws://localhost:8080/socketHandler');
function send() {
const clientMsg = document.getElementById('myMessage');
if (clientMsg.value) {
socketConn.send(clientMsg.value);
}
}
socketConn.onmessage = (e) => {
const output = document.getElementById('output');
output.value += `${e.data}\n`;
}
</script>
</body>
</html>
index.html
包含应用的客户端接口。
const socketConn = new WebSocket('ws://localhost:8080/socketHandler');
在 JavaScript 中,我们创建一个套接字连接。
function send() {
const clientMsg = document.getElementById('myMessage');
if (clientMsg.value) {
socketConn.send(clientMsg.value);
}
}
单击按钮后,我们将发送带有send()
的短信。
socketConn.onmessage = (e) => {
const output = document.getElementById('output');
output.value += `${e.data}\n`;
}
收到响应后,将调用onmessage()
事件处理器。 我们获得响应数据并将其添加到文本区域。
在本教程中,我们创建了一个支持 WebSocket 的简单 Spring Web 应用。
您可能也对这些相关教程感兴趣: Spring @GetMapping
教程, Spring DefaultServlet
教程, Spring Web 应用简介和 Java 教程。
Spring WebJars 教程
Spring WebJars 教程展示了如何在 Spring Web 应用中使用 WebJars。
Spring 是用于创建企业应用的流行 Java 应用框架。
Webjars
WebJars 是打包到 JAR(Java 存档)文件中的客户端 Web 库(例如 jQuery 或 Semantic UI)。 WebJars 使前端库和资产的工作自动化。
Spring WebJar 示例
在以下示例中,我们使用 Semantic-UI WebJar。 语义 UI 是一种流行的 CSS 框架。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ ├───config
│ │ │ MyWebInitializer.java
│ │ │ WebConfig.java
│ │ └───controller
│ │ MyController.java
│ └───resources
│ │ logback.xml
│ └───templates
│ index.html
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>WebJarEx</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.4.RELEASE</spring-version>
<thymeleaf-version>3.0.11.RELEASE</thymeleaf-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>Semantic-UI</artifactId>
<version>2.4.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator</artifactId>
<version>0.34</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>${thymeleaf-version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>${thymeleaf-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
</plugins>
</build>
</project>
在pom.xml
中,我们具有项目依赖项。
<dependency>
<groupId>org.webjars</groupId>
<artifactId>Semantic-UI</artifactId>
<version>2.4.1</version>
</dependency>
我们使用语义 UI WebJar。
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator</artifactId>
<version>0.34</version>
</dependency>
webjars-locator
允许我们引用资产而不引用资产的版本,该版本会自动检测到。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
这是logback.xml
配置
com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.FrameworkServlet;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
@Configuration
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
MyWebInitializer
初始化 Spring Web 应用。 它包含一个配置类:WebConfig
。
com/zetcode/config/WebConfig.java
package com.zetcode.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.zetcode"})
public class WebConfig implements WebMvcConfigurer {
@Autowired
private ApplicationContext applicationContext;
@Bean
public SpringResourceTemplateResolver templateResolver() {
var templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix("classpath:templates/");
templateResolver.setSuffix(".html");
return templateResolver;
}
@Bean
public SpringTemplateEngine templateEngine() {
var templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
@Bean
public ViewResolver viewResolver() {
var resolver = new ThymeleafViewResolver();
var registry = new ViewResolverRegistry(null, applicationContext);
resolver.setTemplateEngine(templateEngine());
registry.viewResolver(resolver);
return resolver;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/webjars/**")
.addResourceLocations("/webjars/").resourceChain(false);
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
WebConfig
配置 Thymeleaf 模板引擎,告诉 Spring 在哪里寻找 WebJars,并启用转发到默认 servlet 来处理静态资源的功能。
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/webjars/**")
.addResourceLocations("/webjars/").resourceChain(false);
}
我们将通过/webjars/
路径引用 WebJars。 对于版本无关的 WebJars,必须调用resourceChain()
方法。
com/zetcode/controller/MyController.java
package com.zetcode.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.List;
@Controller
public class MyController {
@GetMapping(value = "/")
public String home(Model model) {
var words = List.of("wood", "star", "cloud", "water",
"river", "spring");
model.addAttribute("words", words);
return "index";
}
}
MyController
包含主页的一种路由。 我们向模板发送一些数据。 数据将显示在 HTML 表中,该表将使用 Semantic-UI 设置样式。
resources/templates/index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Home page</title>
<link rel="stylesheet" th:href="@{/webjars/Semantic-UI/semantic.css}">
</head>
<body>
<section class="ui container">
<h2>English words</h2>
<table class="ui striped celled table">
<thead>
<tr>
<th>Index</th>
<th>Word</th>
</tr>
</thead>
<tbody>
<tr th:each="word : ${words}">
<td th:text="${wordStat.index + 1}">Index</td>
<td th:text="${word}">A word</td>
</tr>
</tbody>
</table>
</section>
</body>
</html>
这是主页。
<link rel="stylesheet" th:href="@{/webjars/Semantic-UI/semantic.css}">
我们链接到semantic.css
文件,该文件来自 WebJar。
<table class="ui striped celled table">
CSS 类来自 Semantic-UI 库。
在本教程中,我们创建了一个使用 Semantic-UI WebJar 样式化 HTML 表的样式。
您可能也对这些相关教程感兴趣: Spring Jetty 教程, Spring @GetMapping
教程, Spring DefaultServlet
教程, Spring Web 应用简介和 Java 教程。
Spring @MatrixVariable
教程
Spring @MatrixVariable
教程展示了如何使用@MatrixVariable
解析 URL 参数。
Spring 是用于创建企业应用的流行 Java 应用框架。
@MatrixVariable
@MatrixVariable
用于解析路径段中的名称-值对,并将它们绑定到方法参数。 多对用分号分隔。 必须首先启用矩阵变量。
Spring @MatrixVariable
示例
以下应用解析 URL 路径段中的名称/值对。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ ├───config
│ │ │ MyWebInitializer.java
│ │ │ WebConfig.java
│ │ └───controller
│ │ MyController.java
│ ├───resources
│ └───webapp
│ index.html
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>matrixvariableex</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.14.v20181114</version>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有项目依赖项。
com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.FrameworkServlet;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
@Configuration
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
MyWebInitializer
初始化 Spring Web 应用。 它包含一个配置类:WebConfig
。
com/zetcode/config/WebConfig.java
package com.zetcode.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.util.UrlPathHelper;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.zetcode"})
public class WebConfig implements WebMvcConfigurer {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
var urlPathHelper = new UrlPathHelper();
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
WebConfig
配置 Spring Web 应用。
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
var urlPathHelper = new UrlPathHelper();
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
在这里,我们启用矩阵变量。
com/zetcode/controller/MyController.java
package com.zetcode.controller;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.MatrixVariable;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
public class MyController {
@GetMapping(value = "/user/{first}/{last}",
produces = MediaType.TEXT_PLAIN_VALUE)
public String handler1(@MatrixVariable("first") String first,
@MatrixVariable("last") String last) {
return String.format("Hello %s %s", first, last);
}
@GetMapping(value = "/data/{user:.*}",
produces = MediaType.TEXT_PLAIN_VALUE)
public String handler2(@MatrixVariable Map<String, String> data) {
return String.format("Id: %s\nFirst name: %s\nLast Name: %s\nEmail: %s\n",
data.get("id"), data.get("first"), data.get("last"), data.get("email"));
}
@GetMapping(value = "/geo/{continent}",
produces = MediaType.TEXT_PLAIN_VALUE)
public String handler3(@PathVariable("continent") String continent,
@MatrixVariable("country") String country,
@MatrixVariable("capital") String capital) {
return String.format("Continent: %s\nCountry: %s\nCapital: %s\n",
continent, country, capital);
}
}
MyController
包含请求路径到处理器方法的映射。
@GetMapping(value = "/user/{first}/{last}",
produces = MediaType.TEXT_PLAIN_VALUE)
public String handler1(@MatrixVariable("first") String first,
@MatrixVariable("last") String last) {
return String.format("Hello %s %s", first, last);
}
在这里,我们使用@MatrixVariable
将多个矩阵变量绑定到方法参数。
@GetMapping(value = "/data/{user:.*}",
produces = MediaType.TEXT_PLAIN_VALUE)
public String handler2(@MatrixVariable Map<String, String> data) {
return String.format("Id: %s\nFirst name: %s\nLast Name: %s\nEmail: %s\n",
data.get("id"), data.get("first"), data.get("last"), data.get("email"));
}
在这里,我们将多个名称/值对映射到一个映射中。
@GetMapping(value = "/geo/{continent}",
produces = MediaType.TEXT_PLAIN_VALUE)
public String handler3(@PathVariable("continent") String continent,
@MatrixVariable("country") String country,
@MatrixVariable("capital") String capital) {
return String.format("Continent: %s\nCountry: %s\nCapital: %s\n",
continent, country, capital);
}
在第三种情况下,我们将@MatrixVariable
与@PathVariable
结合在一起。
webapp/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Home page</title>
</head>
<body>
<p>
<a href="http://localhost:8080/user/first=John/last=Doe">Greet user</a>
</p>
<p>
<a href="http://localhost:8080/data/id=1;first=John;last=Doe;email=johndoe@gmail.com">Show user data</a>
</p>
<p>
<a href="http://localhost:8080/geo/Europe;country=Slovakia;capital=Bratislava">Show country info</a>
</p>
</body>
</html>
这是主页。 我们有三个链接,这些链接包含使用@MatrixVariable
注解解析的名称/值对。
在本教程中,我们使用@MatrixVariable
解析路径段上的名称/值对并将其绑定到方法参数。
您可能也对这些相关教程感兴趣: Spring @GetMapping
教程, Spring DefaultServlet
教程, Spring Web 应用简介和 Java 教程。
Spring Jetty 教程
Spring Jetty 教程显示了如何在 Jetty Web 服务器上运行 Spring Web 应用。
Spring 是用于创建企业应用的流行 Java 应用框架。
Jetty
Jetty Web 服务器是一个 HTTP 服务器和 Servlet 容器,能够通过独立或嵌入式实例提供静态和动态内容。
Spring Jetty 的例子
在以下示例中,我们创建一个简单的 Spring Web 应用并将其部署在 Jetty Web 服务器上。 为此,我们使用jetty-maven-plugin
。
该应用显示几个英语单词。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ ├───config
│ │ │ MyWebInitializer.java
│ │ │ WebConfig.java
│ │ └───controller
│ │ MyController.java
│ └───resources
│ │ logback.xml
│ └───templates
│ index.html
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>SpringJettyEx</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
<thymeleaf-version>3.0.11.RELEASE</thymeleaf-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>${thymeleaf-version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>${thymeleaf-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.14.v20181114</version>
</plugin>
</plugins>
</build>
</project>
在pom.xml
中,我们具有项目依赖项。
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.14.v20181114</version>
</plugin>
jetty-maven-plugin
允许我们使用mvn jetty:run
运行嵌入式 Jetty 服务器。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
这是logback.xml
配置
com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.FrameworkServlet;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
@Configuration
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
MyWebInitializer
初始化 Spring Web 应用。 它包含一个配置类:WebConfig
。
com/zetcode/config/WebConfig.java
package com.zetcode.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.zetcode"})
public class WebConfig implements WebMvcConfigurer {
@Autowired
private ApplicationContext applicationContext;
@Bean
public SpringResourceTemplateResolver templateResolver() {
var templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix("classpath:/templates/");
templateResolver.setSuffix(".html");
return templateResolver;
}
@Bean
public SpringTemplateEngine templateEngine() {
var templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
@Bean
public ViewResolver viewResolver() {
var resolver = new ThymeleafViewResolver();
var registry = new ViewResolverRegistry(null, applicationContext);
resolver.setTemplateEngine(templateEngine());
registry.viewResolver(resolver);
return resolver;
}
}
WebConfig
配置 Thymeleaf 模板引擎。
com/zetcode/controller/MyController.java
package com.zetcode.controller;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.List;
@Controller
public class MyController {
@GetMapping(value = "/", produces = MediaType.TEXT_HTML_VALUE)
public String home(Model model) {
var words = List.of("mountain", "noon", "rock", "river", "spring");
model.addAttribute("words", words);
return "index";
}
}
MyController
包含主页的一种路由。 我们向模板发送一些数据。 数据将显示在 HTML 表中。
resources/templates/index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Home page</title>
</head>
<body>
<h2>English words</h2>
<table">
<thead>
<tr>
<th>Index</th>
<th>Word</th>
</tr>
</thead>
<tbody>
<tr th:each="word : ${words}">
<td th:text="${wordStat.index + 1}">Index</td>
<td th:text="${word}">A word</td>
</tr>
</tbody>
</table>
</body>
</html>
这是主页。
$ mvn jetty:run
我们运行 Jetty 服务器。 我们导航到localhost:8080
以获取主页。
在本教程中,我们创建了一个 Spring Web 应用并将其部署在嵌入式 Jetty 服务器上。
您可能也对这些相关教程感兴趣: Spring WebJars 教程, Spring DefaultServlet
教程, Spring Web 应用简介和 Java 教程。
Spring 自定义 404 错误页面教程
Spring 自定义 404 错误页面教程展示了如何在 Spring Web 应用中创建自定义 404 错误页面。
Spring 是用于创建企业应用的流行 Java 应用框架。
404 代码
HTTP 404 或 404 未找到是计算机网络通信中的超文本传输协议(HTTP)标准响应代码,用于指示客户端能够与给定服务器进行通信,但是服务器找不到所请求的资源。
Spring 自定义 404 错误页面示例
以下应用使用创建自定义 404 错误页面。 默认情况下,当找不到资源时,将显示 Tomcat 的 404 错误页面。
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ ├───config
│ │ │ MyWebInitializer.java
│ │ │ WebConfig.java
│ │ └───controller
│ │ ControllerAdvisor.java
│ │ MyController.java
│ └───resources
│ │ logback.xml
│ └───templates
│ │ index.html
│ └───error
│ 404.html
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>custom404page</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有以下依存关系:logback-classic
,javax.servlet-api
,spring-webmvc
和thymeleaf-spring5
以及thymeleaf
。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
这是logback.xml
配置文件。
com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.FrameworkServlet;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
@Configuration
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
@Override
protected FrameworkServlet createDispatcherServlet(WebApplicationContext servletAppContext) {
var dispatcher = (DispatcherServlet) super.createDispatcherServlet(servletAppContext);
dispatcher.setThrowExceptionIfNoHandlerFound(true);
return dispatcher;
}
}
MyWebInitializer
初始化 Spring Web 应用。 它包含一个配置类:WebConfig
。
@Override
protected FrameworkServlet createDispatcherServlet(WebApplicationContext servletAppContext) {
var dispatcher = (DispatcherServlet) super.createDispatcherServlet(servletAppContext);
dispatcher.setThrowExceptionIfNoHandlerFound(true);
return dispatcher;
}
使用setThrowExceptionIfNoHandlerFound()
,我们将 Spring 配置为在找不到资源时抛出NoHandlerFoundException
。 如果我们在此行中添加注释,则会显示 Web 服务器的 404 错误页面。
com/zetcode/config/WebConfig.java
package com.zetcode.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.zetcode"})
public class WebConfig implements WebMvcConfigurer {
@Autowired
private ApplicationContext applicationContext;
@Bean
public SpringResourceTemplateResolver templateResolver() {
var templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix("classpath:/templates/");
templateResolver.setSuffix(".html");
return templateResolver;
}
@Bean
public SpringTemplateEngine templateEngine() {
var templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
@Bean
public ViewResolver viewResolver() {
var resolver = new ThymeleafViewResolver();
var registry = new ViewResolverRegistry(null, applicationContext);
resolver.setTemplateEngine(templateEngine());
registry.viewResolver(resolver);
return resolver;
}
}
WebConfig
配置 Thymeleaf 模板引擎。 Thymeleaf 模板文件位于类路径的templates
子目录中。
com/zetcode/controller/MyController.java
package com.zetcode.controller;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.time.LocalDateTime;
@Controller
public class MyController {
@GetMapping(value = "/", produces = MediaType.TEXT_HTML_VALUE)
public String home(Model model) {
model.addAttribute("now", LocalDateTime.now());
return "index";
}
}
MyController
包含主页的一种路由。
com/zetcode/controller/ControllerAdvisor.java
package com.zetcode.controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.NoHandlerFoundException;
@ControllerAdvice
public class ControllerAdvisor {
@ExceptionHandler(NoHandlerFoundException.class)
public ModelAndView handle(Exception ex) {
var mv = new ModelAndView();
mv.addObject("message", ex.getMessage());
mv.setViewName("error/404");
return mv;
}
}
ControllerAdvisor
包含NoHandlerFoundException
的处理器。 它显示404.html
错误页面,位于resources/templates/error/404.html
中。
resources/templates/error/404.html
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Resource not found</title>
</head>
<body>
<h2>404 - resource not found</h2>
<p>
<span th:text="${message}" th:remove="tag"></span>
</p>
</body>
</html>
404.html
是我们的自定义 404 错误页面。
resources/templates/index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Home page</title>
</head>
<body>
<p>
This is home page.
</p>
<p>
Today is <span th:text="${now}"></span>
</p>
</body>
</html>
这是主页。
在本教程中,我们在 Spring 应用中创建了一个自定义 404 错误页面。
您可能也对这些相关教程感兴趣: Spring WebJars 教程, Spring @GetMapping
教程, Spring DefaultServlet
教程, Spring Web 应用简介和 Java 教程。
Spring WebApplicationInitializer
教程
Spring WebApplicationInitializer
教程展示了如何使用WebApplicationInitializer
以编程方式引导 Spring Web 应用。
Spring 是用于创建企业应用的流行 Java 应用框架。
WebApplicationInitializer
WebApplicationInitializer
用于引导 Spring Web 应用。 WebApplicationInitializer
注册一个 Spring DispatcherServlet
并创建一个 Spring Web 应用上下文。 通常,开发者使用AbstractAnnotationConfigDispatcherServletInitializer
(它是WebApplicationInitializer
的实现)来创建 Spring Web 应用。
传统上,基于 Servlet 的 Java Web 应用使用web.xml
文件来配置 Java Web 应用。 从 Servlet 3.0 开始,可以通过 Servlet 上下文监听器以编程方式创建 Web 应用。
Spring WebApplicationInitializer
示例
以下应用使用WebApplicationInitializer
创建 Spring Web 应用。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ ├───config
│ │ │ MyWebInitializer.java
│ │ │ WebConfig.java
│ │ └───controller
│ │ MyController.java
│ └───resources
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>mockmvcex</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有以下依存关系:logback-classic
javax.servlet-api
和spring-webmvc
。
com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
public class MyWebInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
var ctx = new AnnotationConfigWebApplicationContext();
ctx.register(WebConfig.class);
ctx.setServletContext(servletContext);
var servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
servlet.setLoadOnStartup(1);
servlet.addMapping("/");
}
}
MyWebInitializer
实现WebApplicationInitializer
接口。 引导代码在onStartup()
方法中。
var ctx = new AnnotationConfigWebApplicationContext();
ctx.register(WebConfig.class);
ctx.setServletContext(servletContext);
我们创建一个AnnotationConfigWebApplicationContext
并向register()
注册一个 Web 配置文件。 我们将应用上下文与 Servlet 上下文绑定。
var servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
servlet.setLoadOnStartup(1);
servlet.addMapping("/");
在这里,我们注册一个 Spring DispatcherServlet
,它是 Spring Web 应用的前端控制器。
com/zetcode/config/WebConfig.java
package com.zetcode.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.zetcode")
public class WebConfig {
}
WebConfig
通过@EnableWebMvc
启用 Spring MVC 注解,并为com.zetcode
包配置组件扫描。
com/zetcode/controller/MyController.java
package com.zetcode.controller;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@GetMapping(value = "/", produces = MediaType.TEXT_PLAIN_VALUE)
public String home() {
return "This is home page";
}
}
MyController
是一种 RESTful 控制器,具有一个映射。
$ curl localhost:8080
This is home page
我们使用curl
工具连接到主页。
在本教程中,我们使用WebApplicationInitializer
创建了一个简单的 Spring Web 应用。
您可能也对这些相关教程感兴趣: Spring @GetMapping
教程, Spring DefaultServlet
教程, Spring Web 应用简介和 Java 教程。
Spring BindingResult
教程
Spring BindingResult
教程展示了如何使用BindingResult
来获取验证结果。
Spring 是用于创建企业应用的流行 Java 应用框架。
BindingResult
BindingResult
保存验证和绑定的结果,并包含可能发生的错误。 BindingResult
必须紧随经过验证的模型对象之后,否则 Spring 无法验证该对象并引发异常。
Spring BindingResult
示例
以下应用验证用户表单,并使用BindingResult
存储验证结果。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ ├───config
│ │ │ MyWebInitializer.java
│ │ │ WebConfig.java
│ │ ├───controller
│ │ │ MyController.java
│ │ └───form
│ │ UserForm.java
│ └───resources
│ └───templates
│ form.html
│ showInfo.html
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>bindingresultex</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
<thymeleaf-version>3.0.11.RELEASE</thymeleaf-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.10.Final</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>${thymeleaf-version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>${thymeleaf-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.14.v20181114</version>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有项目依赖项。
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.10.Final</version>
</dependency>
我们使用hibernate-validator
进行验证。
com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.FrameworkServlet;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
@Configuration
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
MyWebInitializer
初始化 Spring Web 应用。 它包含一个配置类:WebConfig
。
com/zetcode/config/WebConfig.java
package com.zetcode.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.zetcode"})
public class WebConfig implements WebMvcConfigurer {
@Autowired
private ApplicationContext applicationContext;
@Bean
public SpringResourceTemplateResolver templateResolver() {
var templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix("classpath:/templates/");
templateResolver.setSuffix(".html");
return templateResolver;
}
@Bean
public SpringTemplateEngine templateEngine() {
var templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
@Bean
public ViewResolver viewResolver() {
var resolver = new ThymeleafViewResolver();
var registry = new ViewResolverRegistry(null, applicationContext);
resolver.setTemplateEngine(templateEngine());
registry.viewResolver(resolver);
return resolver;
}
}
WebConfig
配置 Thymeleaf 模板引擎。 Thymeleaf 模板文件位于类路径的templates
子目录中。
com/zetcode/form/UserForm.java
package com.zetcode.form;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
public class UserForm {
@NotBlank
@Size(min=2)
private String name;
@NotBlank
@Email
private String email;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
这是一个表单 bean。 它包含一些验证注解。
@NotBlank
@Size(min=2)
private String name;
name 属性不能为空,并且必须至少包含 2 个字符。
@NotBlank
@Email
private String email;
email 属性不能为空,并且必须是格式正确的电子邮件。
com/zetcode/controller/MyController.java
package com.zetcode.controller;
import com.zetcode.form.UserForm;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import javax.validation.Valid;
@Controller
public class MyController {
@GetMapping(value = "/")
public String form(UserForm userForm) {
return "form";
}
@PostMapping("/")
public String checkForm(@Valid UserForm userForm, BindingResult bindingResult,
RedirectAttributes atts) {
if (bindingResult.hasErrors()) {
return "form";
}
atts.addAttribute("name", userForm.getName());
atts.addAttribute("email", userForm.getEmail());
return "redirect:/showInfo";
}
@GetMapping("/showInfo")
public String showInfo(@ModelAttribute("name") String name,
@ModelAttribute("email") String email) {
return "showInfo";
}
}
MyController
包含请求路径到处理器方法的映射。
@GetMapping(value = "/")
public String form(UserForm userForm) {
return "form";
}
主页返回一个包含表单的视图。 UserForm
bean 正在支持表单。 它将使用来自表单的数据进行填充。
@PostMapping("/")
public String checkForm(@Valid UserForm userForm, BindingResult bindingResult,
RedirectAttributes atts) {
...
我们用@Valid
验证UserForm
bean。 验证结果存储在BindingResult
中。
if (bindingResult.hasErrors()) {
return "form";
}
如果绑定结果包含错误,我们将返回表格。
atts.addAttribute("name", userForm.getName());
atts.addAttribute("email", userForm.getEmail());
return "redirect:/showInfo";
遵循发布后重定向模式,成功验证后,我们将重定向到showInfo
视图。 为了不丢失输入,我们将它们存储在RedirectAttributes
中。
@GetMapping("/showInfo")
public String showInfo(@ModelAttribute("name") String name,
@ModelAttribute("email") String email) {
return "showInfo";
}
@ModelAttribute
将请求属性nad
放入模型对象,然后将其发送到showInfo
视图。
resources/templates/form.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>User form</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.3.1/semantic.min.css"
rel="stylesheet">
</head>
<body>
<section class="ui container">
<form action="#" class="ui form" th:action="@{/}" th:object="${userForm}" method="post">
<div class="field">
<label>Name:</label>
<input type="text" th:field="*{name}">
<span th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Name Error</span>
</div>
<div class="field">
<label>Email:</label>
<input type="text" th:field="*{email}">
<span th:if="${#fields.hasErrors('email')}" th:errors="*{email}">Email Error</span>
</div>
<button class="ui button" type="submit">Submit</button>
</form>
</section>
</body>
</html>
根页面包含表单。
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.3.1/semantic.min.css"
rel="stylesheet">
表单使用语义 UI 设置样式。
<form action="#" class="ui form" th:action="@{/}" th:object="${userForm}" method="post">
th:object
引用用户表单 bean。 这不是一个类名,而是一个 Spring bean 名称。 因此它是小写的。
<input type="text" th:field="*{name}">
输入被映射到userForm
的name
属性。
<span th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Name Error</span>
此行显示可能的验证错误。
resources/templates/showInfo.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Show info</title>
</head>
<body>
<p>
Successfully added user <span th:text="${name}" th:remove="tag"></span> with email
<span th:text="${email}" th:remove="tag"></span>
</p>
</body>
</html>
此视图显示输入的信息。
在本教程中,我们在验证表单时使用了BindingResult
。
您可能也对这些相关教程感兴趣: Spring @GetMapping
教程, Spring DefaultServlet
教程, Spring Web 应用简介和 Java 教程。
Spring FreeMarker 教程
Spring FreeMarker 教程展示了如何在 Spring 应用中使用 FreeMarker 模板引擎。
Spring 是用于创建企业应用的流行 Java 应用框架。
FreeMarker
FreeMarker 是适用于 Web 和独立环境的服务器端 Java 模板引擎。 模板使用 FreeMarker 模板语言(FTL)编写,这是一种简单的专用语言。 FreeMarker 的模板有.ftl
扩展。
Spring FreeMarker 示例
以下应用使用 FreeMarker 生成视图。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ ├───config
│ │ │ MyWebInitializer.java
│ │ │ WebConfig.java
│ │ ├───controller
│ │ │ MyController.java
│ │ └───service
│ │ WordService.java
│ └───resources
│ │ logback.xml
│ └───templates
│ index.ftl
│ showWords.ftl
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>springfreemarkerex</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.14.v20181114</version>
</plugin>
</plugins>
</build>
</project>
在pom.xml
中,我们具有必要的依赖项。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
@Configuration
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
MyWebInitializer
注册 Spring DispatcherServlet
,它是 Spring Web 应用的前端控制器。
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
getServletConfigClasses()
返回 Web 配置类。
com/zetcode/config/WebConfig.java
package com.zetcode.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.zetcode"})
public class WebConfig implements WebMvcConfigurer {
@Bean
public FreeMarkerViewResolver freemarkerViewResolver() {
var resolver = new FreeMarkerViewResolver();
resolver.setCache(true);
resolver.setSuffix(".ftl");
return resolver;
}
@Bean
public FreeMarkerConfigurer freemarkerConfig() {
var freeMarkerConfigurer = new FreeMarkerConfigurer();
freeMarkerConfigurer.setTemplateLoaderPath("classpath:/templates/");
return freeMarkerConfigurer;
}
}
WebConfig
配置 FreeMarker 模板引擎。 我们将模板文件的位置设置为classpath
上的templates
目录。 (resources
在类路径上。)
com/zetcode/service/WordService.java
package com.zetcode.service;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class WordService {
private final List<String> words = List.of("pen", "sky",
"rock", "forest", "falcon", "eagle");
public List<String> all() {
return words;
}
}
WordService
返回几个字。
com/zetcode/controller/MyController.java
package com.zetcode.controller;
import com.zetcode.service.WordService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MyController {
@GetMapping(value = "/")
public String home() {
return "index";
}
@GetMapping(value = "/words")
public String showWords(Model model, WordService wordService) {
var words = wordService.all();
model.addAttribute("words", words);
return "showWords";
}
}
MyController
提供请求路径和处理器方法之间的映射。 我们有两个映射:home
页面和showWords
页面。
var words = wordService.all();
model.addAttribute("words", words);
我们使用wordService
检索所有单词并将其放入模型中。 该模型将传递到 FreeMarker,后者将处理模板中的数据。
resources/templates/index.ftl
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Home page</title>
</head>
<body>
<p>
<a href="words">Show words</a>
</p>
</body>
</html>
主页包含显示所有单词的锚点。
resources/templates/showWords.ftl
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Show words</title>
</head>
<body>
<h2>List of words</h2>
<ul>
<#list words as word>
<li>${word}</li>
</#list>
</ul>
</body>
</html>
使用 FreeMarker 的list
指令,我们可以显示 HTML 列表中的所有单词。
$ mvn jetty:run
我们运行服务器并定位到localhost:8080
以获取具有锚点的主页。
在本教程中,我们使用了FreeMarker
模板引擎。
您可能也对这些相关教程感兴趣: Spring @Configuration
教程, Java 教程或列出所有 Spring 教程。
Spring Thymeleaf 教程
Spring Thymeleaf 教程展示了如何在 Spring 应用中使用 Thymeleaf 模板引擎。
Spring 是用于创建企业应用的流行 Java 应用框架。
Thymeleaf
Thymeleaf 是适用于 Web 和独立环境的服务器端 Java 模板引擎。 它提供了完整的 Spring Framework 集成。
Spring Thymeleaf 示例
以下应用使用 Thymeleaf 生成视图。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ ├───config
│ │ │ MyWebInitializer.java
│ │ │ WebConfig.java
│ │ ├───controller
│ │ │ MyController.java
│ │ └───service
│ │ WordService.java
│ └───resources
│ │ logback.xml
│ └───templates
│ index.html
│ showWords.html
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>springthymeleafex</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.14.v20181114</version>
</plugin>
</plugins>
</build>
</project>
在pom.xml
中,我们具有必要的依赖项。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
@Configuration
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
MyWebInitializer
注册 Spring DispatcherServlet
,它是 Spring Web 应用的前端控制器。
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
getServletConfigClasses()
返回 Web 配置类。
com/zetcode/config/WebConfig.java
package com.zetcode.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.zetcode"})
public class WebConfig implements WebMvcConfigurer {
@Autowired
private ApplicationContext applicationContext;
@Bean
public SpringResourceTemplateResolver templateResolver() {
var templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix("classpath:/templates/");
templateResolver.setSuffix(".html");
return templateResolver;
}
@Bean
public SpringTemplateEngine templateEngine() {
var templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
@Bean
public ViewResolver viewResolver() {
var resolver = new ThymeleafViewResolver();
var registry = new ViewResolverRegistry(null, applicationContext);
resolver.setTemplateEngine(templateEngine());
registry.viewResolver(resolver);
return resolver;
}
}
WebConfig
配置 Thymeleaf 模板引擎。 我们将模板文件的位置设置为classpath
上的templates
目录。 (resources
在类路径上。)
com/zetcode/service/WordService.java
package com.zetcode.service;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class WordService {
private final List<String> words = List.of("pen", "sky",
"rock", "forest", "falcon", "eagle");
public List<String> all() {
return words;
}
}
WordService
返回几个字。
com/zetcode/controller/MyController.java
package com.zetcode.controller;
import com.zetcode.service.WordService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MyController {
@GetMapping(value = "/")
public String home() {
return "index";
}
@GetMapping(value = "/words")
public String showWords(Model model, WordService wordService) {
var words = wordService.all();
model.addAttribute("words", words);
return "showWords";
}
}
MyController
提供请求路径和处理器方法之间的映射。 我们有两个映射:home
页面和showWords
页面。
var words = wordService.all();
model.addAttribute("words", words);
我们使用wordService
检索所有单词并将其放入模型中。 该模型将传递给 Thymeleaf,后者将处理模板中的数据。
resources/templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Home page</title>
</head>
<body>
<p>
<a href="words">Show words</a>
</p>
</body>
</html>
主页包含显示所有单词的锚点。
resources/templates/showWords.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Words</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<h2>List of words</h2>
<ul th:each="word : ${words}">
<li th:text="${word}">word</li>
</ul>
</body>
</html>
使用 Thymeleaf 的th:each
指令,我们可以显示 HTML 列表中的所有单词。
$ mvn jetty:run
我们运行服务器并定位到localhost:8080
以获取具有锚点的主页。
在本教程中,我们使用了Thymeleaf
模板引擎。
您可能对这些相关教程也感兴趣: Spring Freemarker 教程, Spring @Configuration
教程, Java 教程或列出所有 Spring 教程。
Spring @PostMapping
教程
Spring @PostMapping
教程显示了如何使用@PostMapping
注解将 HTTP POST 请求映射到特定的处理器方法。
Spring 是用于创建企业应用的流行 Java 应用框架。
@PostMapping
@PostMapping
注解将 HTTP POST 请求映射到特定的处理器方法。 它是一个组合的注解,用作@RequestMapping(method = RequestMethod.POST)
的快捷方式。
Spring @PostMapping
示例
以下应用使用@PostMapping
创建新资源。 在此示例中,我们使用注解来设置 Spring Web 应用。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ ├───config
│ │ │ MyWebInitializer.java
│ │ │ WebConfig.java
│ │ ├───controller
│ │ │ MyController.java
│ │ ├───model
│ │ │ Post.java
│ │ └───service
│ │ PostService.java
│ └───resources
│ logback.xml
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>postmappingex</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.14.v20181114</version>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有项目依赖项。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
@Configuration
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
MyWebInitializer
注册 Spring DispatcherServlet
,它是 Spring Web 应用的前端控制器。
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
getServletConfigClasses()
返回 Web 配置类。
com/zetcode/config/WebConfig.java
package com.zetcode.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.zetcode"})
public class WebConfig {
}
WebConfig
通过@EnableWebMvc
启用 Spring MVC 注解,并为com.zetcode
包配置组件扫描。
com/zetcode/controller/MyController.java
package com.zetcode.controller;
import com.zetcode.model.Post;
import com.zetcode.service.PostService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import javax.servlet.http.HttpServletRequest;
import java.util.Set;
import static org.springframework.http.ResponseEntity.ok;
@Controller
public class MyController {
@Autowired
private PostService postService;
@GetMapping(value="/posts")
public ResponseEntity<Set<Post>> all() {
return ok().body(postService.all());
}
@PostMapping(value = "/posts")
public ResponseEntity<Post> createPost(HttpServletRequest request,
UriComponentsBuilder uriComponentsBuilder) {
var content = request.getParameter("content");
var post = new Post();
post.setContent(content);
post = postService.save(post);
UriComponents uriComponents =
uriComponentsBuilder.path("/posts/{id}").buildAndExpand(post.getId());
var location = uriComponents.toUri();
return ResponseEntity.created(location).build();
}
}
MyController
提供请求路径和处理器方法之间的映射。
注意:这是一个很好的做法,在响应头返回新创建资源的位置。
@PostMapping(value = "/posts")
public ResponseEntity<Post> createPost(HttpServletRequest request,
UriComponentsBuilder uriComponentsBuilder) {
@PostMapping
将createPost()
方法映射到/posts
URL。
var content = request.getParameter("content");
我们获得 POST 请求的content
参数。
var post = new Post();
post.setContent(content);
post = postService.save(post);
创建一个新帖子,并将其保存在一个帖子服务中。
UriComponents uriComponents =
uriComponentsBuilder.path("/posts/{id}").buildAndExpand(post.getId());
var location = uriComponents.toUri();
使用UriComponentsBuilder
构建位置 URI。
return ResponseEntity.created(location).build();
返回带有位置 URI 的响应实体。
com/zetcode/model/Post.java
package com.zetcode.model;
import java.util.Objects;
public class Post {
private Long id;
private String content;
public Post() {
}
public Post(Long id, String content) {
this.id = id;
this.content = content;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Post post = (Post) o;
return Objects.equals(id, post.id) &&
Objects.equals(content, post.content);
}
@Override
public int hashCode() {
return Objects.hash(id, content);
}
}
这是一个简单的Post
bean。 它具有两个属性:id
和content
。
com/zetcode/service/PostService.java
package com.zetcode.service;
import com.zetcode.model.Post;
import org.springframework.stereotype.Service;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
@Service
public class PostService {
private final AtomicLong counter = new AtomicLong();
private final Set<Post> posts = new HashSet<>(Set.of(new Post(counter.incrementAndGet(), "Post one"),
new Post(counter.incrementAndGet(), "Post two"), new Post(counter.incrementAndGet(), "Post three"),
new Post(counter.incrementAndGet(), "Post four")));
public Post save(Post p) {
var post = new Post(counter.incrementAndGet(), p.getContent());
this.posts.add(post);
return post;
}
public Set<Post> all() {
return this.posts;
}
}
PostService
具有保存帖子并返回所有帖子的方法。 我们没有实现数据库层。 相反,我们使用一个简单的内存集合。
$ mvn jetty:run
我们运行 Jetty 服务器。
$ curl -i -d "content=Post five" -X POST http://localhost:8080/posts
HTTP/1.1 201 Created
Date: Tue, 30 Apr 2019 09:49:10 GMT
Location: http://localhost:8080/posts/5
Content-Length: 0
Server: Jetty(9.4.14.v20181114)
创建一个新帖子。 注意位置标头。
$ curl localhost:8080/posts
[{"id":3,"content":"Post three"},{"id":4,"content":"Post four"},
{"id":1,"content":"Post one"},{"id":5,"content":"Post five"},{"id":2,"content":"Post two"}]
我们得到所有帖子。
在本教程中,我们介绍了@PostMapping
注解。
您可能也对这些相关教程感兴趣: Spring @GetMapping
教程, Spring @RequestMapping
教程, Spring @MatrixVariable
教程, Java 教程,或列出所有 Spring 教程。
Spring ResourceHandlerRegistry
教程
Spring ResourceHandlerRegistry
教程展示了如何在 Spring Web 应用中提供静态资产,例如图像,CSS 或 JavaScript 文件。
Spring 是用于创建企业应用的流行 Java 应用框架。
ResourceHandlerRegistry
ResourceHandlerRegistry
存储用于通过 Spring MVC 服务静态资源(例如图像,css 文件等)的资源处理器的注册。 它允许设置为在 Web 浏览器中高效加载而优化的缓存头。 可以在 Web 应用根目录下,类路径等位置之外的位置提供资源。
Spring ResourceHandlerRegistry
示例
以下应用使用ResourceHandlerRegistry
在 Spring Web 应用中注册静态资产。 我们使用addResourceHandlers()
为 CSS 和 JavaScript 文件注册处理器和位置。
我们将 Thymeleaf 用作视图引擎。 我们使用 Thymeleaf 的@{}
语法指向静态资源。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ ├───config
│ │ │ MyWebInitializer.java
│ │ │ WebConfig.java
│ │ └───controller
│ │ MyController.java
│ ├───resources
│ │ │ logback.xml
│ │ └───static
│ │ ├───css
│ │ │ format.css
│ │ └───js
│ │ main.js
│ └───webapp
│ └───WEB-INF
│ └───templates
│ homePage.html
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>staticresources</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有以下依存关系:logback-classic
,javax.servlet-api
,spring-webmvc
,thymeleaf-spring5
和thymeleaf
。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
resources/css/format.css
p {
background-color: aquamarine;
}
这是format.css
文件。 它格式化p
元素。
resources/js/main.js
const el = document.getElementById("block");
el.style.border = '1px dashed gray';
这是main.js
文件。 它将边框添加到div
元素。 请注意,即使 JavaScript 在科学方面提供了动态功能,但从 Spring 的角度来看,它仍被视为静态资源。
com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
@Configuration
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/*"};
}
}
MyWebInitializer
注册 Spring DispatcherServlet
,它是 Spring Web 应用的前端控制器。
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
getServletConfigClasses()
返回 Web 配置类。
com/zetcode/config/WebConfig.java
package com.zetcode.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.zetcode"})
public class WebConfig implements WebMvcConfigurer {
@Autowired
private ApplicationContext applicationContext;
@Bean
public SpringResourceTemplateResolver templateResolver() {
var templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix("/WEB-INF/templates/");
templateResolver.setSuffix(".html");
return templateResolver;
}
@Bean
public SpringTemplateEngine templateEngine() {
var templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
@Bean
public ViewResolver viewResolver() {
var resolver = new ThymeleafViewResolver();
var registry = new ViewResolverRegistry(null, applicationContext);
resolver.setTemplateEngine(templateEngine());
registry.viewResolver(resolver);
return resolver;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/js/**").addResourceLocations("classpath:/static/js/");
registry.addResourceHandler("/css/**").addResourceLocations("classpath:/static/css/");
}
}
WebConfig
通过@EnableWebMvc
启用 Spring MVC 注解,并为com.zetcode
包配置组件扫描。 它设置 Thymeleaf 引擎并注册静态资源处理器。
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/js/**").addResourceLocations("classpath:/static/js/");
registry.addResourceHandler("/css/**").addResourceLocations("classpath:/static/css/");
}
我们重写addResourceHandlers()
来注册 JavaScript 和 CSS 文件的处理器和位置。
com/zetcode/controller/MyController.java
package com.zetcode.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MyController {
@GetMapping(value="/")
public String homePage() {
return "homePage";
}
}
MyController
提供主页的映射。 在应用中,我们仅使用一个视图。
WEB-INF/templates/homePage.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Home page</title>
<link rel="stylesheet" th:href="@{/css/format.css}">
</head>
<body>
<div id="block">
<p>
This is home page.
</p>
</div>
<script th:src="@{/js/main.js}"></script>
</body>
</html>
homePage.html
是主页的视图。 它使用静态资源; 一个 CSS 和一个 JavaScript 文件。
<link rel="stylesheet" th:href="@{/css/format.css}">
我们使用特定的 Thymeleaf 语法引用静态文件。
在本教程中,我们展示了如何向 Spring 的ResourceHandlerRegistry
注册静态资源。
您可能也对这些相关教程感兴趣: Spring BeanDefinitionBuilder
教程, Spring 资源教程, Spring @GetMapping
教程和 Java 教程。
SpringRunner
教程
SpringRunner
教程展示了如何使用SpringRunner
测试 Spring 应用。
Spring 是流行的 Java 应用框架。 在本教程中,我们使用 Spring 5 版本。
SpringRunner
SpringRunner
是SpringJUnit4ClassRunner
的别名,该别名将JUnit
测试库与 Spring TestContext Framework 结合在一起。 我们将其与@RunWith(SpringRunner.class)
一起使用。
使用SpringRunner
,我们可以实现基于 JUnit 4 的标准单元测试和集成测试。
Spring TestContext Framework 提供了通用的,注解驱动的单元和集成测试支持,这些支持与使用中的测试框架(JUnit,TestNG)无关。
SpringRunner
示例
在以下应用中,我们使用SprigRunner
测试一个简单的服务。 该应用是一个 Spring 独立控制台应用。
该应用包含两个属性文件:一个文件用于生产应用,另一个文件用于测试。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ │ Application.java
│ │ ├───config
│ │ │ AppConfig.java
│ │ └───service
│ │ HelloService.java
│ └───resources
│ application.properties
│ logback.xml
└───test
├───java
│ └───com
│ └───zetcode
│ └───service
│ HelloServiceTest.java
└───resources
appTest.properties
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>springrunnerex</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>com.zetcode.Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
这是 Maven 构建文件。 我们具有以下依赖项:logback-classic
用于记录日志,spring-context
和spring-core
是基本的 Spring 依赖项,spring-test
用于测试,hamcrest-all
包含 Hamcrest 匹配库的所有模块,而JUnit
是用于单元测试的库。
exec-maven-plugin
帮助执行系统和 Java 程序。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
resources/application.properties
app.message=Hello there!
application.properties
包含一个消息属性,由HelloMessage
服务显示。
com/zetcode/AppConfig.java
package com.zetcode.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@ComponentScan(basePackages = "com.zetcode")
@PropertySource("application.properties")
public class AppConfig {
}
AppConfig
配置组件扫描并从提供的文件中加载属性。
com/zetcode/servide/HelloService.java
package com.zetcode.service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@Service
public class HelloService {
@Value("${app.message}")
private String message;
public String sayHello() {
return message;
}
}
HelloService
返回从application.properties
文件检索到的消息。
com/zetcode/Application.java
package com.zetcode;
import com.zetcode.config.AppConfig;
import com.zetcode.service.HelloService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;
@Component
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
var ctx = new AnnotationConfigApplicationContext(AppConfig.class);
var app = ctx.getBean(Application.class);
app.run();
ctx.close();
}
@Autowired
private HelloService helloService;
private void run() {
logger.info("Calling hello service");
logger.info(helloService.sayHello());
}
}
应用使用HelloService
将消息打印到控制台。
$ mvn -q exec:java
17:50:54.118 INFO com.zetcode.Application - Calling hello service
17:50:54.118 INFO com.zetcode.Application - Hello there!
我们运行该应用。
resources/appTest.properties
app.message=Testing hello message
appTest.properties
专用于测试。
com/zetcode/service/HelloServiceTest.java
package com.zetcode.service;
import com.zetcode.config.AppConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes={HelloService.class})
@TestPropertySource("/appTest.properties")
public class HelloServiceTest {
@Value("${app.message}")
private String message;
@Autowired
private HelloService helloService;
@Test
public void testHelloMessage() {
var message = helloService.sayHello();
assertThat(message, equalTo(message));
}
}
HelloServiceTest
用于测试HelloService
类。
@RunWith(SpringRunner.class)
@ContextConfiguration(classes={HelloService.class})
@TestPropertySource("/appTest.properties")
public class HelloServiceTest {
测试类用@RunWith(SpringRunner.class)
注解。 @ContextConfiguration
定义了类级别的元数据,用于确定如何加载和配置用于集成测试的应用上下文。 此外,我们还提供了@TestPropertySource
自定义测试属性文件。
@Value("${app.message}")
private String message;
我们从appTest.properties
文件注入消息。
@Autowired
private HelloService helloService;
我们注入HelloMessage
服务类。 这是要测试的类。
@Test
public void testHelloMessage() {
var message = helloService.sayHello();
assertThat(message, equalTo(message));
}
我们测试来自service
方法的消息是否等于注入的字符串值。
$ mvn -q test
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running com.zetcode.service.HelloServiceTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.489 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
我们运行测试。
在本教程中,我们展示了如何使用SpringRunner
在 Spring 应用中创建测试。 Spring MockMvc 教程, Spring @PropertySource
教程, Java 教程。
Spring MockMvc 教程
Spring MockMvc 教程展示了如何使用 MockMvc 测试 Spring MVC 应用。
Spring 是用于创建企业应用的流行 Java 应用框架。
MockMvc
MockMvc
被定义为服务器端 Spring MVC 测试的主要入口点。 MockMvc
的测试介于单元测试和集成测试之间。
Spring MockMvc 示例
以下应用使用MockMvc
测试 Spring MVC 应用。 我们为模板和 RESTful 控制器方法创建测试。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ ├───config
│ │ │ MyWebInitializer.java
│ │ │ WebConfig.java
│ │ └───controller
│ │ MyController.java
│ ├───resources
│ └───webapp
│ └───WEB-INF
│ └───templates
│ index.html
└───test
└───java
└───com
└───zetcode
└───controller
MyControllerTest.java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>mockmvcex</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有以下依存关系:logback-classic
,javax.servlet-api
,junit
,spring-webmvc
,spring-test
,thymeleaf-spring5
和thymeleaf
。
com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
@Configuration
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
MyWebInitializer
注册 Spring DispatcherServlet
,它是 Spring Web 应用的前端控制器。
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
getServletConfigClasses()
返回 Web 配置类。
com/zetcode/config/WebConfig.java
package com.zetcode.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.zetcode"})
public class WebConfig {
@Autowired
private ApplicationContext applicationContext;
@Bean
public SpringResourceTemplateResolver templateResolver() {
var templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix("/WEB-INF/templates/");
templateResolver.setSuffix(".html");
return templateResolver;
}
@Bean
public SpringTemplateEngine templateEngine() {
var templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
@Bean
public ViewResolver viewResolver() {
var resolver = new ThymeleafViewResolver();
var registry = new ViewResolverRegistry(null, applicationContext);
resolver.setTemplateEngine(templateEngine());
registry.viewResolver(resolver);
return resolver;
}
}
WebConfig
通过@EnableWebMvc
启用 Spring MVC 注解,并为com.zetcode
包配置组件扫描。 它设置了 Thymeleaf 引擎。
com/zetcode/controller/MyController.java
package com.zetcode.controller;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.time.LocalDateTime;
@Controller
public class MyController {
@GetMapping(value = "/", produces = MediaType.TEXT_HTML_VALUE)
public String home(Model model) {
model.addAttribute("now", LocalDateTime.now());
return "index";
}
@GetMapping(value = "/message", produces = MediaType.TEXT_PLAIN_VALUE)
@ResponseBody
public String message() {
return "Hello there!";
}
}
MyController
提供了两种处理器方法。 home()
方法返回具有单个属性的视图,message()
方法返回纯文本消息。 在我们的测试中,我们测试这两种方法。
WEB-INF/templates/index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Home page</title>
</head>
<body>
<p>
Today is: <span th:text="${now}"></span>
</p>
</body>
</html>
这是index.html
视图。
com/zetcode/controller/MyControllerTest.java
package com.zetcode.controller;
import org.junit.Before;
import org.junit.Test;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
public class MyControllerTest {
private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.standaloneSetup(new MyController()).build();
}
@Test
public void testHomePage() throws Exception {
this.mockMvc.perform(get("/"))
.andExpect(status().isOk())
.andExpect(view().name("index"))
.andDo(MockMvcResultHandlers.print())
.andReturn();
}
@Test
public void testMessagePage() throws Exception {
this.mockMvc.perform(get("/message")).andExpect(status().isOk())
.andExpect(content().string("Hello there!"));
}
}
MyControllerTest
测试两个处理器。
private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.standaloneSetup(new MyController()).build();
}
我们设置了MockMvc
。 我们将MyController
添加到独立设置中。 MockMvcBuilders.standaloneSetup()
允许注册一个或多个控制器,而无需使用完整的WebApplicationContext
。
@Test
public void testHomePage() throws Exception {
this.mockMvc.perform(get("/"))
.andExpect(status().isOk())
.andExpect(view().name("index"))
.andDo(MockMvcResultHandlers.print());
}
我们测试主页。 我们验证状态和返回的视图名称。 我们还将打印结果。
@Test
public void testMessagePage() throws Exception {
this.mockMvc.perform(get("/message")).andExpect(status().isOk())
.andExpect(content().string("Hello there!"));
}
我们测试消息页面。 由于它是一种 RESTful 方法,因此我们将验证状态和返回的字符串。
$ mvn -q test
我们使用mvn -q test
运行测试。
在本教程中,我们使用MockMvc
为 Spring MVC 创建了测试。
您可能也对这些相关教程感兴趣: SpringRunner
教程和 Java 教程。
Spring @DeleteMapping
教程
Spring @DeleteMapping
教程展示了如何使用@DeleteMapping
注解将 HTTP DELETE 请求映射到特定的处理器方法。
Spring 是用于创建企业应用的流行 Java 应用框架。
@DeleteMapping
@DeleteMapping
注解将 HTTP DELETE 请求映射到特定的处理器方法。 它是一个组合的注解,用作@RequestMapping(method = RequestMethod.DELETE)
的快捷方式。
Spring @DeleteMapping
示例
以下应用使用@DeleteMapping
删除资源。 我们使用注解来设置 Spring Web 应用。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ ├───config
│ │ │ MyWebInitializer.java
│ │ │ WebConfig.java
│ │ ├───controller
│ │ │ MyController.java
│ │ ├───model
│ │ │ Post.java
│ │ └───service
│ │ PostService.java
│ └───resources
│ logback.xml
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>postmappingex</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.14.v20181114</version>
</plugin>
</plugins>
</build>
</project>
在pom.xml
文件中,我们具有项目依赖项。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
@Configuration
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
MyWebInitializer
注册 Spring DispatcherServlet
,它是 Spring Web 应用的前端控制器。
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
getServletConfigClasses()
返回 Web 配置类。
com/zetcode/config/WebConfig.java
package com.zetcode.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.zetcode"})
public class WebConfig {
}
WebConfig
通过@EnableWebMvc
启用 Spring MVC 注解,并为com.zetcode
包配置组件扫描。
com/zetcode/controller/MyController.java
package com.zetcode.controller;
import com.zetcode.model.Post;
import com.zetcode.service.IPostService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import java.util.Set;
import static org.springframework.http.ResponseEntity.ok;
@Controller
public class MyController {
@Autowired
private IPostService postService;
@GetMapping(value="/posts")
public ResponseEntity<Set<Post>> all() {
return ok().body(postService.all());
}
@DeleteMapping(value = "/posts/{id}")
public ResponseEntity<Long> deletePost(@PathVariable Long id) {
var isRemoved = postService.delete(id);
if (!isRemoved) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<>(id, HttpStatus.OK);
}
}
MyController
提供请求路径和处理器方法之间的映射。 我们有两种映射:一种用于 GET 请求,另一种用于 DELETE 请求。
@GetMapping(value="/posts")
public ResponseEntity<Set<Post>> all() {
return ok().body(postService.all());
}
用@GetMapping
注解的方法返回所有帖子。
@DeleteMapping(value = "/posts/{id}")
public ResponseEntity<Long> deletePost(@PathVariable Long id) {
var isRemoved = postService.delete(id);
if (!isRemoved) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<>(id, HttpStatus.OK);
}
deletePost()
带有@DeleteMapping
注解。 该方法的工作是尝试使用IPostService
删除帖子。 根据结果返回适当的ResponseEntity
。
com/zetcode/model/Post.java
package com.zetcode.model;
import java.util.Objects;
public class Post {
private Long id;
private String content;
public Post() {
}
public Post(Long id, String content) {
this.id = id;
this.content = content;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Post post = (Post) o;
return Objects.equals(id, post.id) &&
Objects.equals(content, post.content);
}
@Override
public int hashCode() {
return Objects.hash(id, content);
}
}
这是一个简单的Post
bean。 它具有两个属性:id
和content
。
com/zetcode/service/IPostService.java
package com.zetcode.service;
import com.zetcode.model.Post;
import java.util.Set;
public interface IPostService {
boolean delete(Long id);
Set<Post> all();
}
IPostService
包含两种签约方法:delete()
和all()
。
com/zetcode/service/PostService.java
package com.zetcode.service;
import com.zetcode.model.Post;
import org.springframework.stereotype.Service;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
@Service
public class PostService implements IPostService {
private final AtomicLong counter = new AtomicLong();
private final Set<Post> posts = new HashSet<>(Set.of(new Post(counter.incrementAndGet(), "Post one"),
new Post(counter.incrementAndGet(), "Post two"), new Post(counter.incrementAndGet(), "Post three"),
new Post(counter.incrementAndGet(), "Post four")));
public boolean delete(Long id) {
var isRemoved = this.posts.removeIf(post -> post.getId().equals(id));
return isRemoved;
}
public Set<Post> all() {
return this.posts;
}
}
PostService
具有删除帖子并返回所有帖子的方法。 我们没有实现数据库层。 相反,我们使用一个简单的内存集合。
注意:在实际应用中,我们还将实现存储库层。
$ mvn jetty:run
我们运行 Jetty 服务器。
$ curl localhost:8080/posts
[{"id":3,"content":"Post three"},{"id":4,"content":"Post four"},
{"id":1,"content":"Post one"},{"id":2,"content":"Post two"}]
使用curl
工具,我们可以检索所有帖子。
$ curl -i -X DELETE localhost:8080/posts/1/
HTTP/1.1 200 OK
Date: Wed, 01 May 2019 12:59:07 GMT
Content-Type: application/json;charset=utf-8
Transfer-Encoding: chunked
Server: Jetty(9.4.14.v20181114)
1
我们删除 ID 为 1 的信息。
$ curl localhost:8080/posts
[{"id":3,"content":"Post three"},{"id":4,"content":"Post four"},{"id":2,"content":"Post two"}]
我们又收到了所有帖子。 编号为 1 的帖子已删除。
在本教程中,我们介绍了@DeleteMapping
注解。
您可能也对这些相关教程感兴趣: Spring @GetMapping
教程, Spring @PostMapping
教程, Spring @RequestMapping
教程, Spring @MatrixVariable
教程 或 Java 教程或列出所有 Spring 教程。
Spring @RequestMapping
教程
Spring @RequestMapping
教程显示了如何在 Spring Web 应用中使用@RequestMapping
注解。 注解用于将 Web 请求映射到请求处理类中的处理器方法上。
Spring 是用于创建企业应用的流行 Java 应用框架。
@RequestMapping
@RequestMapping
用于将 Web 请求映射到请求处理类中的处理器方法上。 将 Web 请求映射到处理器方法的过程也称为路由。
@RequestMapping
具有以下特化:
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
注释可以在类和方法级别上使用。 如果在两个级别上都使用,则将请求路径合并。
Spring @RequestMapping
示例
在下面的示例中,我们演示@RequestMapping
注解的用法。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ ├───config
│ │ │ MyWebInitializer.java
│ │ │ WebConfig.java
│ │ └───controller
│ │ MyController.java
│ │ TestController.java
│ └───resources
│ index.html
│ logback.xml
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>RequestMappingEx</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.14.v20181114</version>
</plugin>
</plugins>
</build>
</project>
在pom.xml
中,我们具有项目依赖项。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
这是logback.xml
配置
resources/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Home page</title>
</head>
<body>
<p>
This is home page.
</p>
</body>
</html>
这是一个主页。
com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.FrameworkServlet;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
@Configuration
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
MyWebInitializer
初始化 Spring Web 应用。 它包含一个配置类:WebConfig
。
com/zetcode/config/WebConfig.java
package com.zetcode.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.zetcode"})
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
WebConfig
配置 Spring Web 应用。
com/zetcode/controller/MyController.java
package com.zetcode.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalTime;
@RestController
public class MyController {
@RequestMapping(value = "/")
public String home() {
return "This is Home page";
}
@RequestMapping(value = "/about", method = RequestMethod.POST)
public String about() {
return "This is About page; POST request";
}
@RequestMapping(value = "/fresh", method = {RequestMethod.POST, RequestMethod.GET})
public String fresh() {
return "This is Fresh page; GET/POST request";
}
@RequestMapping(value = "/todo", consumes = "text/plain")
public String todo() {
return "This is Todo page; text/plain content type";
}
@RequestMapping(value = "/time", params = { "info=time" })
public String showTime() {
var now = LocalTime.now();
return String.format("%s", now.toString());
}
}
MyController
具有@RequestMapping
的各种路由定义。
@RequestMapping(value = "/")
public String home() {
return "This is Home page";
}
使用value
选项,我们将/
请求路径映射到home()
处理器方法。 如果未明确指定,则默认请求方法为 GET。 value
是path
选项的别名。
@RequestMapping(value = "/about", method = RequestMethod.POST)
public String about() {
return "This is About page; POST request";
}
使用method
选项,我们可以将处理器映射范围缩小到具有/about
路径的 POST 请求。
@RequestMapping(value = "/fresh", method = {RequestMethod.POST, RequestMethod.GET})
public String fresh() {
return "This is Fresh page; GET/POST request";
}
此方法可以接受 GET 和 POST 请求。
@RequestMapping(value = "/todo", consumes = "text/plain")
public String todo() {
return "This is Todo page; text/plain content type";
}
使用consumes
选项,我们可以将映射范围缩小到具有定义的内容类型的请求。
@RequestMapping(value = "/time", params = { "info=time" })
public String showTime() {
var now = LocalTime.now();
return String.format("%s", now.toString());
}
使用params
选项,我们可以缩小到/time
路径和info=time
请求参数的 GET 请求的映射。
com/zetcode/controller/TestController.java
package com.zetcode.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value="/test")
public class TestController {
@RequestMapping(value = "/info")
public String info() {
return "This is info page";
}
@RequestMapping(path="*.do")
public String somePage() {
return "This is some page";
}
}
TestController
具有另外两个映射。
@RestController
@RequestMapping(value="/test")
public class TestController {
我们也可以将@RequestMapping
放在类上。 然后将路径与方法路径合并。
@RequestMapping(value = "/info")
public String info() {
return "This is info page";
}
该处理器映射到/test/info
路径。
@RequestMapping(path="*.do")
public String somePage() {
return "This is some page";
}
path
选项等效于value
。 它可以接受 Ant 样式的 URL 映射。
$ mvn jetty:run
我们运行 Jetty 服务器。
$ curl localhost:8080
This is Home page
我们使用curl
工具向主页生成 GET 请求。
$ curl -X POST localhost:8080/about
This is About page; POST request
这是对/about
路径的 POST 请求。
$ curl -X POST localhost:8080/fresh
This is Fresh page; GET/POST request
$ curl -X GET localhost:8080/fresh
This is Fresh page; GET/POST request
/fresh
页面接受 GET 和 POST 请求。
$ curl -d "info=time" localhost:8080/time
13:24:29.934670700
我们将带有参数的请求发送到/time
页面。
$ curl localhost:8080/test/info
This is info page
类级别和方法级别的注解被组合到/test/info
路径中。
$ curl localhost:8080/test/produce.do
This is some page
最后是蚂蚁风格的映射。
在本教程中,我们使用@RequestMapping
注解创建了各种路径。
您可能也对这些相关教程感兴趣: Spring WebJars 教程, Spring @GetMapping
教程, Spring DefaultServlet
教程, Spring Web 应用简介和 Java 教程。
Spring @PathVariable
教程
Spring @PathVariable
教程显示了如何读取带有@PathVariable
注解的 URL 模板变量。 我们创建一个 Spring RESTful 应用来演示注解。
Spring 是用于创建企业应用的流行 Java 应用框架。
@PathVariable
@PathVariable
是 Spring 注解,指示方法参数应绑定到 URI 模板变量。 如果方法参数为Map<String, String>
,则将使用所有路径变量名称和值填充映射。
它具有以下可选元素:
name
- 要绑定到的路径变量的名称required
- 指示路径变量是否为必需value
- 名称的别名
Spring @PathVariable
示例
以下示例创建一个使用@PathVariable
的 Spring Web 应用。 记录变量值。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ ├───config
│ │ │ MyWebInitializer.java
│ │ │ WebConfig.java
│ │ └───controller
│ │ MyController.java
│ └───resources
│ logback.xml
└───test
└───java
这是 Spring 应用的项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>pathvariableex</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.14.v20181114</version>
</plugin>
</plugins>
</build>
</project>
我们声明项目依赖项。 @PathVariable
来自spring-webmvc
封装。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
@Configuration
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
DispatcherServlet
是 Spring Web 应用的前端控制器,已注册在MyWebInitializer
中。
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
getServletConfigClasses()
返回 Web 配置类。
com/zetcode/config/WebConfig.java
package com.zetcode.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.zetcode"})
public class WebConfig {
}
WebConfig
通过@EnableWebMvc
启用 Spring MVC 注解,并为com.zetcode
包配置组件扫描。
com/zetcode/MyController.java
package com.zetcode.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
public class MyController {
private static final Logger logger = LoggerFactory.getLogger(MyController.class);
@ResponseStatus(value = HttpStatus.OK)
@GetMapping(value = "/user/{name}")
public void process(@PathVariable String name) {
logger.info("User name: {}", name);
}
@ResponseStatus(value = HttpStatus.OK)
@GetMapping(value = "/user/{name}/{email}")
public void process2(@PathVariable String name, @PathVariable String email) {
logger.info("User name: {} and email: {}", name, email);
}
@ResponseStatus(value = HttpStatus.OK)
@GetMapping(value = "/book/{author}/{title}")
public void process3(@PathVariable Map<String, String> vals) {
logger.info("{}: {}", vals.get("author"), vals.get("title"));
}
}
我们为 GET 请求提供了三个映射。
@ResponseStatus(value = HttpStatus.OK)
@GetMapping(value = "/user/{name}")
public void process(@PathVariable String name) {
logger.info("User name: {}", name);
}
在此代码中,URI 模板变量绑定到name
方法参数。
@ResponseStatus(value = HttpStatus.OK)
@GetMapping(value = "/user/{name}/{email}")
public void process2(@PathVariable String name, @PathVariable String email) {
logger.info("User name: {} and email: {}", name, email);
}
通过指定多个@PathVariable
注解,也可以绑定多个变量。
@ResponseStatus(value = HttpStatus.OK)
@GetMapping(value = "/book/{author}/{title}")
public void process3(@PathVariable Map<String, String> vals) {
logger.info("{}: {}", vals.get("author"), vals.get("title"));
}
也可以使用Map<String, String>
绑定多个变量。
$ mvn jetty:run
我们启动 Jetty 服务器。
$ curl localhost:8080/user/Peter/peter@gmail.com/
我们用curl
发出请求。
22:04:35.273 INFO com.zetcode.controller.MyController - User name: Peter and email: peter@gmail.com
应用记录此消息。
在本教程中,我们使用 Spring 框架创建了一个 RESTful Web 应用。 我们已经演示了@PathVariable
的用法。 您可能也对相关教程感兴趣: Spring @RequestMapping
教程, Spring @RequestHeader
教程, Java 教程或列出所有 Spring 教程。
Spring @RequestBody
教程
Spring @RequestBody
教程展示了如何使用@RequestBody
注解将方法参数绑定到请求主体。
Spring 是用于创建企业应用的流行 Java 应用框架。
Spring @RequestBody
@RequestBody
注解将请求主体绑定到方法参数。 序列化/反序列化的过程由HttpMessageConverter
执行。 另外,可以通过使用@Valid
注解自变量来应用自动验证。
Spring @RequestBody
示例
该应用将表单 POST 和 JSON post 请求的请求主体参数绑定到映射的方法参数。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ ├───bean
│ │ │ User.java
│ │ ├───config
│ │ │ MyWebInitializer.java
│ │ │ WebConfig.java
│ │ └───controller
│ │ MyController.java
│ └───resources
│ logback.xml
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.zetcode</groupId>
<artifactId>springrequestbodyex</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.14.v20181114</version>
</plugin>
</plugins>
</build>
</project>
我们声明必要的依赖关系。 在HttpMessageConverter
中进行序列化需要jackson-databind
。 该应用在嵌入式 Jetty 上运行; 因此,我们声明jetty-maven-plugin
。
resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zetcode" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} %blue(%-5level) %magenta(%logger{36}) - %msg %n
</Pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
</configuration>
logback.xml
是 Logback 日志库的配置文件。
com/zetcode/bean/User.java
package com.zetcode.bean;
public class User {
private String name;
private String occupation;
public User() {
}
public User(String name, String occupation) {
this.name = name;
this.occupation = occupation;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getOccupation() {
return occupation;
}
public void setOccupation(String occupation) {
this.occupation = occupation;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("User{");
sb.append("name='").append(name).append('\'');
sb.append(", occupation='").append(occupation).append('\'');
sb.append('}');
return sb.toString();
}
}
在示例中,我们具有User
bean,它具有name
和occupation
属性。
com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
@Configuration
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
MyWebInitializer
注册 Spring DispatcherServlet
,它是 Spring Web 应用的前端控制器。
com/zetcode/config/WebConfig.java
package com.zetcode.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.zetcode"})
public class WebConfig implements WebMvcConfigurer {
}
WebConfig
通过@EnableWebMvc
启用 Spring MVC 注解,并为com.zetcode
包配置组件扫描。
com/zetcode/controller/MyController.java
package com.zetcode.controller;
import com.zetcode.bean.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
private static final Logger logger = LoggerFactory.getLogger(MyController.class);
@ResponseStatus(value = HttpStatus.OK)
@PostMapping(value="/vals")
public void process(@RequestBody MultiValueMap<String, String> values) {
logger.info("Values:{}", values);
}
@ResponseStatus(value = HttpStatus.OK)
@PostMapping(value="/user", consumes = MediaType.APPLICATION_JSON_VALUE)
public void process2(@RequestBody User user) {
logger.info("User: {}", user);
}
}
在MyContoller
中,我们有两个 POST 映射。 我们使用@RequestBody
将请求参数绑定到MultiValueMap
和User
bean。 绑定值显示在日志中。
$ mvn jetty:run
我们启动服务器。
$ curl -i -d "par1=val1&par2=val2" -X POST http://localhost:8080/vals
使用curl
工具,我们可以创建第一个映射的请求。 这将创建一个表单 POST 数据请求(内容类型为application/x-www-form-urlencoded
)。
11:57:39.049 INFO com.zetcode.controller.MyController - Values:{par1=[val1], par2=[val2]}
我们得到这个日志。
$ curl -i -H "Content-Type: application/json" -d "{\"name\":\"John Doe\",\"occupation\":\"gardener\"}" -X POST "http://localhost:8080/user"
我们调用第二个映射。 在这里,我们使用 JSON 数据创建一个请求。 请注意,在 Windows 上,我们需要转义双引号。
12:02:33.817 INFO com.zetcode.controller.MyController - User: User{name='John Doe', occupation='gardener'}
这是日志中的输出。
在本教程中,我们使用@RequestBody
注解将请求属性绑定到方法参数。
您可能也对这些相关教程感兴趣: Spring @PostMapping
教程, Java 教程或列出所有 Spring 教程。