假设我们在某人的阅读列表里不止想要展示图书标题,还要提供该书的Amazon链接。我们不仅想提供该书的链接,还要标记该书,以便利用Amazon的Associate Program。
1.修改Thymeleaf模板
<a th:href="'http://www.amazon.com/gp/product/'
+ ${book.isbn}
+ '/tag=habuma-20'"
th:text="${book.title}">Title</a>
此外,ReadingListController需要在模型里包含amazonID这个键,其中的内容是Amazon Associate ID。应该引用一个实例变量。这个变量的值应该来自属性配置。
2.在一个Bean里加载配置属性(在一个类里收集属性)
@Component
@ConfigurationProperties("amazon") //注入带amazon前缀的属性
public class AmazonProperties {
private String associateId;
public String getAssociateId() {
return associateId;
}
public void setAssociateId(String associateId) {
this.associateId = associateId;
}
}
3.注入了AmazonProperties的ReadingListController
@Controller
@RequestMapping("/")
public class ReadingListController {
private ReadingListRepository readingListRepository;
private AmazonProperties amazonProperties;
@Autowired
public ReadingListController(
ReadingListRepository readingListRepository,
AmazonProperties amazonProperties){ //注入AmazonProperties
this.readingListRepository = readingListRepository;
this.amazonProperties = amazonProperties;
}
@RequestMapping(value = "/{reader}", method = RequestMethod.GET)
public String readersBooks(
@PathVariable("reader") String reader,
Model model){
List<Book> readingList = readingListRepository.findByReader(reader);
if(readingList != null) {
model.addAttribute("books",readingList);
model.addAttribute("reader",reader);
//向模型中添加Asscciate ID
model.addAttribute("amazon",amazonProperties.getAssociateId());
}
return "readingList";
}
@RequestMapping(value = "/{reader}",method = RequestMethod.POST)
public String addToReadingList(@PathVariable("reader") String reader,Book book){
book.setReader(reader);
readingListRepository.save(book);
return "redirect:/{reader}";
}
如你所见,ReadingListController现在有了一个associateId属性,还有对应的setAssociateId()方法,用它可以设置该属性。readersBooks()现在能通过amazonID这个键把associateId的值放入模型。
ReadingListController上加了@ConfigurationProperties注解,这说明该Bean的属性应该是(通过setter方法)从配置属性值注入的。说得更具体一点,prefix属性说明ReadingListController应该注入带amazon前缀的属性。综合起来,我们指定ReadingListController的属性应该从带amazon前缀的配置属性中进行注入。ReadingListController只有一个setter方法,就是设置associateId属性用的setter方法。因此,设置Amazon Associate ID唯一要做的就是添加amazon.associateId属性,把它加入支持的任一属性源位置里即可。
4.以在application.properties里设置该属性:
amazon.associateId=habuma-20
使用Profile配置
当应用程序需要部署到不同的运行环境时,一些配置细节通常会有所不同。比如,数据库连接的细节在开发环境下和测试环境下就会不一样,在生产环境下又不一样。Spring Framework从Spring 3.1开始支持基于Profile的配置。Profile是一种条件化配置,基于运行时激活的Profile,会使用或者忽略不同的Bean或配置类。
举例来说,假设我们里创建的安全配置是针对生产环境的,而自动配置的安全配置用在开发环境刚刚好。在这个例子中,我们就能为SecurityConfig加上@Profile注解:
@Profile("production")
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
}
这里用的@Profile注解要求运行时激活production Profile,这样才能应用该配置。如果production Profile没有激活,就会忽略该配置,而此时缺少其他用于覆盖的安全配置,于是应用自动配置的安全配置。
设置spring.profiles.active属性就能激活Profile,任意设置配置属性的方式都能用于设置这个值。例如,在命令行里运行应用程序时,可以这样激活production Profile:
$ java -jar readinglist-0.0.1-SNAPSHOT.jar --
spring.profiles.active=production
也可以向application.yml里添加spring.profiles.active属性:
spring:
profiles:
active: production
还可以设置环境变量,将其放入application.properties,或者使用3.2节开头提到的各种方法。但由于Spring Boot的自动配置替你做了太多的事情,要找到一个能放置@Profile的地方还真不怎么方便。幸运的是,Spring Boot支持为application.properties和application.yml里的属性配置Profile。
假设你希望针对生产环境和开发环境能有不同的日志配置。在生产环境中,你只关心WARN或更高级别的日志项,想把日志写到日志文件里。在开发环境中,你只想把日志输出到控制台,记录DEBUG或更高级别.
而你所要做的就是为每个环境分别创建配置。
那要怎么做呢?这取决于你用的是属性文件配置还是YAML配置。
1. 使用特定于Profile的属性文件
如果你正在使用application.properties,可以创建额外的属性文件,遵循application-{profile}. properties这种命名格式,这样就能提供特定于Profile的属性了。
在日志这个例子里,开发环境的配置可以放在名为application-development.properties的文件里,配置包含日志级别和输出到控制台:
logging.level.root=DEBUG
对于生产环境,application-production.properties会将日志级别设置为WARN或更高级别,并将日志写入日志文件:
logging.path=/var/logs/
logging.file=BookWorm.log
logging.level.root=WARN
与此同时,那些并不特定于哪个Profile或者保持默认值(以防万一有哪个特定于Profile的配
置不指定这个值)的属性,可以继续放在application.properties里:
amazon.associateId=habuma-20
logging.level.root=INFO
2. 使用多Profile YAML文件进行配置
如果使用YAML来配置属性,则可以遵循与配置文件相同的命名规范,即创建application-
{profile}.yml这样的YAML文件,并将与Profile无关的属性继续放在application.yml里。
但既然用了YAML,你就可以把所有Profile的配置属性都放在一个application.yml文件里。举
例来说,我们可以像下面这样声明日志配置:
logging:
level:
root: INFO
---
spring:
profiles: development
logging:
level:
root: DEBUG
---
spring:
profiles: production
logging:
path: /tmp/
file: BookWorm.log
level:
root: WARN
如你所见,这个application.yml文件分为三个部分,使用一组三个连字符(---)作为分隔符。
第二段和第三段分别为spring.profiles指定了一个值,这个值表示该部分配置应该应用在哪个 Profile 里。第二段中定义的属性应用于开发环境,因为 spring.profiles 设置为development。与之类似,最后一段的spring.profile设置为production,在productionProfile被激活时生效。
另一方面,第一段并未指定spring.profiles,因此这里的属性对全部Profile都生效,或者对那些未设置该属性的激活Profile生效。