文章目录
本页将介绍Spring Boot Redis
缓存实例。RedisCacheManager
是由Redis
支持的CacheManager
。如果Redis
在我们的Spring Boot
应用程序中可用并已配置,RedisCacheManager
将被自动配置。Redis
连接从Lettuce
或Jedis
Java Redis
客户端获得。Redis
的依赖性由spring-boot-starter-data-redis
启动器解决。在Spring Boot 2.0
中,Lettuce
被默认解决,而不是Jedis
。要使用Jedis
,我们需要在构建文件中包含jedis
依赖。
Spring
@EnableCaching
在我们的应用程序中启用Spring
缓存管理能力。它被@SpringBootApplication
注解所注解。@Cacheable
表示调用方法的结果可以被缓存,一旦结果被缓存,下一次调用方法的执行将被跳过,只有缓存的结果被提供。@CachePut
添加或更新缓存,但不跳过方法的执行。@CacheEvict
清空缓存但不跳过方法的执行。@Caching
被用来分组多个缓存注释。
演示工具版本
- Java 9
- Spring 5.0.8.RELEASE
- Spring Data 2.0.9.RELEASE
- Spring Boot 2.0.4.RELEASE
- Maven 3.5.2
- MySQL 5.5
- Eclipse Oxygen
Maven 依赖
Spring
提供了spring-boot-starter-data-redis
来解决Redis
的依赖关系。
它为Lettuce
和Jedis
客户端库提供基本的自动配置。
默认情况下,Spring Boot 2.0
使用Lettuce
。为了获得池化连接工厂,我们需要提供commons-pool2
依赖。
找到Maven
文件。
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.concretepage</groupId>
<artifactId>spring-boot-app</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-boot-app</name>
<description>Spring Boot Application</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/>
</parent>
<properties>
<java.version>9</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.5</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties
找到我们的演示程序中使用的应用程序属性文件。
application.properties
#Redis specific configurations
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=
spring.redis.lettuce.pool.max-active=7
spring.redis.lettuce.pool.max-idle=7
spring.redis.lettuce.pool.min-idle=2
spring.redis.lettuce.pool.max-wait=-1ms
spring.redis.lettuce.shutdown-timeout=200ms
spring.cache.redis.cache-null-values=false
spring.cache.redis.time-to-live=600000
spring.cache.redis.use-key-prefix=true
spring.cache.type=redis
#spring.cache.cache-names=articleCache,allArticlesCache
#Database specific configurations
spring.datasource.url=jdbc:mysql://localhost:3306/concretepage
spring.datasource.username=root
spring.datasource.password=cp
spring.datasource.hikari.connection-timeout=20000
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=12
spring.datasource.hikari.idle-timeout=300000
spring.datasource.hikari.max-lifetime=1200000
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
spring.jpa.properties.hibernate.id.new_generator_mappings=false
spring.jpa.properties.hibernate.format_sql=true
使用 Lettuce 配置
Spring Boot 2.0
启动器spring-boot-starter-data-redis
默认解决了Lettuce
。Spring
提供LettuceConnectionFactory
来获取连接。要获得池化连接工厂,我们需要在类路径上提供commons-pool2
。要使用Lettuce
,我们需要以下Maven
依赖项。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
为了配置Lettuce
池,我们需要使用spring.redis.*
前缀与Lettuce
池连接属性。找到Lettuce
池的样本配置。
application.properties
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=
spring.redis.lettuce.pool.max-active=7
spring.redis.lettuce.pool.max-idle=7
spring.redis.lettuce.pool.min-idle=2
spring.redis.lettuce.pool.max-wait=-1ms
spring.redis.lettuce.shutdown-timeout=200ms
我们可以覆盖默认的Redis
主机、端口和密码配置。如果我们想无限期地阻塞,请使用max-wait
这个负值。
使用 Jedis 配置
默认情况下,Spring Boot 2.0
启动器spring-boot-starter-data-redis
使用Lettuce
。要使用Jedis
,我们需要排除Lettuce
的依赖,并包含Jedis
。找到使用Jedis
的Maven
依赖项。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
jedis
的依赖将自动解决类路径上的commons-pool2
。
为了配置Jedis
池,我们需要使用spring.redis.*
前缀与Jedis
池连接属性。找到Jedis
池的样本配置。
application.properties
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=
spring.redis.jedis.pool.max-active=7
spring.redis.jedis.pool.max-idle=7
spring.redis.jedis.pool.min-idle=2
spring.redis.jedis.pool.max-wait=-1ms
RedisCacheManager
在Spring Boot
中,RedisCacheManager
是自动配置的。这里我们将讨论如何配置Spring Boot Redis
缓存属性以改变自动配置的RedisCacheManager
的默认值,然后我们将创建一个自己的RedisCacheManager
示例,以获得对配置的完全控制。
1. 自动配置的 RedisCacheManager
如果Redis
在我们的Spring Boot
应用程序中可用并已配置,RedisCacheManager
将被自动配置。我们可以使用spring.cache.*
属性来控制Spring
缓存的配置。
spring.cache.type: 定义了缓存类型。如果我们不配置这个属性,它将被自动检测到环境。对于Redis
缓存,其值为redis
。
spring.cache.cache-names: 在启动时创建额外的缓冲区。
Redis
缓存的默认值可以通过spring.cache.redis.*
进行配置。
spring.cache.redis.cache-null-values: 它接受布尔值。当该值为true
时,它将允许缓存空值,否则不允许。
spring.cache.redis.time-to-live: 缓存过期时间。
spring.cache.redis.use-key-prefix: 它接受布尔值。如果是true
,那么在写到Redis
时将会使用键的前缀。默认值是true
。
spring.cache.redis.key-prefix: 定义键前缀。默认情况下,当两个独立的缓存使用同一个键时,会添加一个键前缀以避免键重叠。
找到Redis
缓存配置的示例。
application.properties
spring.cache.redis.cache-null-values=false
spring.cache.redis.time-to-live=600000
spring.cache.redis.use-key-prefix=true
spring.cache.type=redis
spring.cache.cache-names=articleCache,allArticlesCache
缓存articleCache
和allArticleCache
将存活10分钟。
2. 自定义的 RedisCacheManager
我们可以创建自己的RedisCacheManager
来获得对Redis
配置的完全控制。我们需要创建LettuceConnectionFactory
Bean
、RedisCacheConfiguration
Bean
和RedisCacheManager
,如下所示。
RedisConfig.java
package com.concretepage;
import java.time.Duration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.EnableCaching;
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.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
@Configuration
@EnableCaching
@PropertySource("classpath:application.properties")
public class RedisConfig {
@Autowired
private Environment env;
@Bean
public LettuceConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration redisConf = new RedisStandaloneConfiguration();
redisConf.setHostName(env.getProperty("spring.redis.host"));
redisConf.setPort(Integer.parseInt(env.getProperty("spring.redis.port")));
redisConf.setPassword(RedisPassword.of(env.getProperty("spring.redis.password")));
return new LettuceConnectionFactory(redisConf);
}
@Bean
public RedisCacheConfiguration cacheConfiguration() {
RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(600))
.disableCachingNullValues();
return cacheConfig;
}
@Bean
public RedisCacheManager cacheManager() {
RedisCacheManager rcm = RedisCacheManager.builder(redisConnectionFactory())
.cacheDefaults(cacheConfiguration())
.transactionAware()
.build();
return rcm;
}
}
RedisCacheConfiguration
是一个不可变的类,它有助于自定义Redis
的缓存行为,如缓存过期时间,禁止缓存空值等。它也有助于自定义序列化策略。
使用 @EnableCaching 启用缓存
为了在我们的应用程序中启用缓存,Spring
提供了@EnableCaching
注解。@EnableCaching
启用注释驱动的缓存管理能力。
它负责注册所需的Spring
组件以启用注释驱动的缓存管理。@EnableCaching
是用@Configuration
或@SpringBootApplication
注解来注释的。
SpringBootAppStarter.java
@SpringBootApplication
@EnableCaching
public class SpringBootAppStarter {
public static void main(String[] args) {
SpringApplication.run(SpringBootAppStarter.class, args);
}
}
使用 @Cacheable
@Cacheable
表示调用方法的结果可以被缓存,一旦结果被缓存,下一次调用方法的执行将被跳过,并且只提供缓存的结果。找出其中的一些元素。
cacheNames: 储存方法结果的缓存名称。
value: cacheNames
的别名。
condition: Spring
SpEL
表达式可以进行有条件缓存。
key: SpEL动态地计算key
。
keyGenerator: 自定义KeyGenerator
的Bean
名称。
unless: SpEL来否决方法缓存。
sync: 当多个线程试图为同一个key
加载一个值时,它被用来同步方法的调用。
为了计算key
, condition
或unless
,我们可以在SpEL
中使用以下元数据。
#result: 引用方法的结果。
#root.method: 引用方法。
#root.target: 对目标对象的引用。
#root.caches: 引用受影响的缓存。
#root.methodName:方法名称的快捷方式。
#root.targetClass:目标类的快捷方式。
#root.args[1], #p1 or #a1: 它们给出了方法的第二个参数。改变数值,我们可以得到其他参数。我们也可以通过他们的名字来访问参数。
现在找到使用@Cacheable
注解的示例代码片段。
@Cacheable(value= "articleCache", key= "#articleId")
public Article getArticleById(long articleId) {
------
}
在上面的代码中,方法的结果将用articleCache
的缓存名称来缓存,使用的键是传递的文章ID
。这意味着对于不同的文章ID
,结果将以不同的键被缓存,但有相同的缓存名称。一旦方法的结果被缓存为一个键,那么对于相同的键,方法将不会执行,缓存的结果将被提供。
@Cacheable(value= "allArticlesCache", unless= "#result.size() == 0")
public List<Article> getAllArticles(){
------
}
在上面的代码中,如果结果的大小为0
,方法的结果将不会被缓存。 如果我们不提供键,默认情况下,它将是(""
)或方法参数被用来计算键(如果有的话)。
使用 @CachePut
@CachePut
触发了一个缓存投放操作。它不会跳过方法的执行,每次执行的结果都会缓存在相关的缓存中。@CachePut
拥有与@Cacheable
相同的元素,如cacheNames
, value
, condition
, key
, unless
, keyGenerator
等。找到使用@CachePut
的示例代码片段。
@CachePut(value= "articleCache", key= "#article.articleId")
public Article addArticle(Article article){
------
}
上述方法将在每次调用时执行,方法结果将被添加或更新到与给定的缓存名称的键相对应的缓存中。
使用 @CacheEvict
@CacheEvict
触发了一个缓存清空操作。它不会跳过方法的执行,并且每次执行都会清空缓存。它的元素包括cacheNames
, value
, condition
, key
, keyGenerator
, allEntries
等。如果allEntries= true
,缓存中的所有条目都被移除。找到使用@CacheEvict
的代码片段。
@CacheEvict(value= "allArticlesCache", allEntries= true)
public void deleteArticle(long articleId) {
------
}
上述方法将执行每一次调用,所有缓存的条目将被删除。
使用 @Caching
@Caching
是多个缓存注解的组注解。它有cacheable
、put
和evict
元素。
找到使用@CachePut
和@CacheEvict
的代码片段,在组中使用@Caching
。
@Caching(
put= { @CachePut(value= "articleCache", key= "#article.articleId") },
evict= { @CacheEvict(value= "allArticlesCache", allEntries= true) }
)
public Article updateArticle(Article article) {
------
}
在@Caching
组中使用多个@CacheEvict
的代码段。
@Caching(
evict= {
@CacheEvict(value= "articleCache", key= "#articleId"),
@CacheEvict(value= "allArticlesCache", allEntries= true)
}
)
public void deleteArticle(long articleId) {
------
}
Spring Boot Cache + Redis + MySQL CRUD 完整示例
这里我们将提供一个Spring Boot Cache + Redis + MySQL
CRUD
操作的完整例子。在Eclipse
中查找项目结构。
现在找到完整的代码。
articles
表
CREATE TABLE IF NOT EXISTS `articles` (
`article_id` int(5) NOT NULL AUTO_INCREMENT,
`title` varchar(200) NOT NULL,
`category` varchar(100) NOT NULL,
PRIMARY KEY (`article_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
INSERT INTO `articles` (`article_id`, `title`, `category`) VALUES
(1, 'Spring REST Security', 'Spring'),
(2, 'Java Concurrency', 'Java');
ArticleService.java
package com.concretepage.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import com.concretepage.entity.Article;
import com.concretepage.repository.ArticleRepository;
@Service
public class ArticleService implements IArticleService {
@Autowired
private ArticleRepository articleRepository;
@Override
@Cacheable(value= "articleCache", key= "#articleId")
public Article getArticleById(long articleId) {
System.out.println("--- Inside getArticleById() ---");
return articleRepository.findById(articleId).get();
}
@Override
@Cacheable(value= "allArticlesCache", unless= "#result.size() == 0")
public List<Article> getAllArticles(){
System.out.println("--- Inside getAllArticles() ---");
List<Article> list = new ArrayList<>();
articleRepository.findAll().forEach(e -> list.add(e));
return list;
}
@Override
@Caching(
put= { @CachePut(value= "articleCache", key= "#article.articleId") },
evict= { @CacheEvict(value= "allArticlesCache", allEntries= true) }
)
public Article addArticle(Article article){
System.out.println("--- Inside addArticle() ---");
return articleRepository.save(article);
}
@Override
@Caching(
put= { @CachePut(value= "articleCache", key= "#article.articleId") },
evict= { @CacheEvict(value= "allArticlesCache", allEntries= true) }
)
public Article updateArticle(Article article) {
System.out.println("--- Inside updateArticle() ---");
return articleRepository.save(article);
}
@Override
@Caching(
evict= {
@CacheEvict(value= "articleCache", key= "#articleId"),
@CacheEvict(value= "allArticlesCache", allEntries= true)
}
)
public void deleteArticle(long articleId) {
System.out.println("--- Inside deleteArticle() ---");
articleRepository.delete(articleRepository.findById(articleId).get());
}
}
IArticleService.java
package com.concretepage.service;
import java.util.List;
import com.concretepage.entity.Article;
public interface IArticleService {
List<Article> getAllArticles();
Article getArticleById(long articleId);
Article addArticle(Article article);
Article updateArticle(Article article);
void deleteArticle(long articleId);
}
Article.java
package com.concretepage.entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="articles")
public class Article implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="article_id")
private long articleId;
@Column(name="title")
private String title;
@Column(name="category")
private String category;
public long getArticleId() {
return articleId;
}
public void setArticleId(long articleId) {
this.articleId = articleId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
}
ArticleRepository.java
package com.concretepage.repository;
import org.springframework.data.repository.CrudRepository;
import com.concretepage.entity.Article;
public interface ArticleRepository extends CrudRepository<Article, Long> {
}
ArticleController.java
package com.concretepage.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
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 org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.util.UriComponentsBuilder;
import com.concretepage.entity.Article;
import com.concretepage.service.IArticleService;
@Controller
@RequestMapping("user")
public class ArticleController {
@Autowired
private IArticleService articleService;
@GetMapping("article/{id}")
public ResponseEntity<Article> getArticleById(@PathVariable("id") Long id) {
Article article = articleService.getArticleById(id);
return new ResponseEntity<Article>(article, HttpStatus.OK);
}
@GetMapping("articles")
public ResponseEntity<List<Article>> getAllArticles() {
List<Article> list = articleService.getAllArticles();
return new ResponseEntity<List<Article>>(list, HttpStatus.OK);
}
@PostMapping("article")
public ResponseEntity<Void> addArticle(@RequestBody Article article, UriComponentsBuilder builder) {
Article savedArticle = articleService.addArticle(article);
HttpHeaders headers = new HttpHeaders();
headers.setLocation(builder.path("/article/{id}").buildAndExpand(savedArticle.getArticleId()).toUri());
return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
}
@PutMapping("article")
public ResponseEntity<Article> updateArticle(@RequestBody Article article) {
articleService.updateArticle(article);
return new ResponseEntity<Article>(article, HttpStatus.OK);
}
@DeleteMapping("article/{id}")
public ResponseEntity<Void> deleteArticle(@PathVariable("id") Long id) {
articleService.deleteArticle(id);
return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
}
}
SpringBootAppStarter.java
package com.concretepage;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching
public class SpringBootAppStarter {
public static void main(String[] args) {
SpringApplication.run(SpringBootAppStarter.class, args);
}
}
RestClientUtil.java
package com.concretepage;
import java.net.URI;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import com.concretepage.entity.Article;
public class RestClientUtil {
public void getArticleByIdDemo(long id) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
RestTemplate restTemplate = new RestTemplate();
String url = "http://localhost:8080/user/article/{id}";
HttpEntity<String> requestEntity = new HttpEntity<String>(headers);
ResponseEntity<Article> responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, Article.class, id);
Article article = responseEntity.getBody();
System.out.println("Id:"+article.getArticleId()+", Title:"+article.getTitle()
+", Category:"+article.getCategory());
}
public void getAllArticlesDemo() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
RestTemplate restTemplate = new RestTemplate();
String url = "http://localhost:8080/user/articles";
HttpEntity<String> requestEntity = new HttpEntity<String>(headers);
ResponseEntity<Article[]> responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, Article[].class);
Article[] articles = responseEntity.getBody();
for(Article article : articles) {
System.out.println("Id:"+article.getArticleId()+", Title:"+article.getTitle()
+", Category: "+article.getCategory());
}
}
public void addArticleDemo(Article objArticle) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
RestTemplate restTemplate = new RestTemplate();
String url = "http://localhost:8080/user/article";
HttpEntity<Article> requestEntity = new HttpEntity<Article>(objArticle, headers);
URI uri = restTemplate.postForLocation(url, requestEntity);
System.out.println(uri.getPath());
}
public void updateArticleDemo(Article objArticle) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
RestTemplate restTemplate = new RestTemplate();
String url = "http://localhost:8080/user/article";
HttpEntity<Article> requestEntity = new HttpEntity<Article>(objArticle, headers);
restTemplate.put(url, requestEntity);
}
public void deleteArticleDemo(long id) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
RestTemplate restTemplate = new RestTemplate();
String url = "http://localhost:8080/user/article/{id}";
HttpEntity<Article> requestEntity = new HttpEntity<Article>(headers);
restTemplate.exchange(url, HttpMethod.DELETE, requestEntity, Void.class, id);
}
public static void main(String args[]) {
RestClientUtil util = new RestClientUtil();
//Add article
Article objArticle = new Article();
objArticle.setTitle("Spring REST Security");
objArticle.setCategory("Spring");
//util.addArticleDemo(objArticle);
//Update article
objArticle.setArticleId(1);
objArticle.setTitle("Java Concurrency");
objArticle.setCategory("Java");
//util.updateArticleDemo(objArticle);
//util.deleteArticleDemo(2);
util.getArticleByIdDemo(1);
System.out.println("---- All articles ----");
util.getAllArticlesDemo();
}
}
测试应用程序
要测试我们的演示应用程序,请找到下面的步骤。
1. 使用链接安装并启动Redis
。
2. 如果你使用的是Windows
操作系统,你可以先安装Cygwin
,然后在其中安装Redis
。
3. Redis
将在6379
端口的localhost
上启动。
4. 在上面的文章中给出的表导入MySQL
数据库中。
5. 我们可以通过以下方式运行我们的Spring Boot
应用程序。
a. 使用Eclipse
使用页面末尾的下载链接下载项目的源代码。
将该项目导入eclipse
。
使用命令提示符,进入项目的根文件夹并运行。
mvn clean eclipse:eclipse
然后在eclipse
中刷新该项目。点击Run as
-> Java Application
来运行主类MyApplication
。
Tomcat
服务器将被启动。
b. 使用Maven命令
下载项目的源代码。使用命令提示符进入项目的根文件夹并运行命令。
mvn spring-boot:run
Tomcat
服务器将被启动。
c. 使用可执行的JAR
使用命令提示符,转到项目的根文件夹并运行该命令。
mvn clean package
我们将在目标文件夹中得到可执行的spring-boot-app-0.0.1-SNAPSHOT.jar
。以下列方式运行这个JAR
。
java -jar target/spring-boot-app-0.0.1-SNAPSHOT.jar
Tomcat
服务器将被启动。
6. 现在我们已经准备好测试这个应用程序了。要运行客户端,在eclipse
中进入RestClientUtil
类,点击Run as
-> Java Application
。
参考文献
【1】Spring Boot Reference Guide
【2】Spring Data Redis
【3】Spring Boot Redis
【4】Spring Data Redis Cache
【5】Spring Boot Redis Cache
源码下载
提取码:mao4