ramostear.comramostear.com 谭朝红的技术分享博客

格言 编程是一门技术,也是一门艺术 !

Spring Boot Admin Server的应用

Spring Boot Admin Server的应用

Spring Boot(十七)— Admin Server

在上一章节中,我们学习了如何使用Spring Boot Actuator来管理应用程序。但是,当我们有多个应用程序需要管理时,使用Actuator来管理这些应用将变得很吃力。因为,当你有N个应用程序需要管理时,每个应用程序都有自己独立的端点信息,维护这些独立的端点信息将是一件可怕的事情。

面对这样的窘境,Spring Boot为我们提供了另外一个神器——Spring Boot Admin Server。它可以统一的在一个地方来管理所有的端点信息,与此同时,CodeCentric团队还提供了一套基于VUE的管理界面,方便我们对各个应用程序进行管理。

在本章节中,我们将使用Spring Boot快熟的构建起一个Admin Server应用程序,在下一个章节中,我们将讲解Admin Client如何与Admin Server一起工作。

构建Spring Boot Admin Server

为了能够构建Admin Server应用程序,我们需要在Maven build文件中引入以下的两个依赖项:

<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-server</artifactId>
</dependency>
<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-server-ui</artifactId>
</dependency>

其中,spring-boot-admin-server-ui为我们提供了一套漂亮的应用管理界面。

开启对Admin Server的支持

使用@EnableAdminServer注解对应用程序的主类进行注释。@EnableAdminServer注解可以让你的应用程序具备管理其他应用程序端点信息的能力。

package com.ramostear.application;

import de.codecentric.boot.admin.server.config.EnableAdminServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableAdminServer
public class AdminServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(AdminServerApplication.class, args);
    }

}

配置应用程序

现在,在application.properties文件中定义如下的几个配置:

server.port=9091
spring.application.name= Admin-Server
spring.application.admin.enabled=true

第一个参数时设置应用程序的启动端口号为9091,第二个参数时设置应用的名称为“Admin-Server”,最后一个参数时开启Admin Server服务。

Maven build 文件清单

<?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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.ramostear</groupId>
    <artifactId>admin-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>admin-server</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-boot-admin.version>2.1.3</spring-boot-admin.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-starter-server</artifactId>
        </dependency>
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-server-ui</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>de.codecentric</groupId>
                <artifactId>spring-boot-admin-dependencies</artifactId>
                <version>${spring-boot-admin.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

接下来,使用下面的Maven命令对项目进行打包:

mvn clean install

打包成功后,使用下面的命令运行JAR文件:

java -jar JARFILE

现在,应用程序已经在Tomcat上启动成功,端口号为:9091 。

2019-03-12 01:44:55.289  INFO 18044 --- [           main] o.s.b.a.e.web.EndpointLinksResolver      : 
Exposing 2 endpoint(s) beneath base path '/actuator'
2019-03-12 01:44:55.803  INFO 18044 --- [           main] o.s.b.web.embedded.netty.NettyWebServer  : 
Netty started on port(s): 9091
2019-03-12 01:44:55.806  INFO 18044 --- [           main] c.r.application.AdminServerApplication   : 
Started AdminServerApplication in 2.81 seconds (JVM running for 3.933)

访问Admin Server

现在,打开Web浏览器,输入URL:http://localhost:9091/ ,然后查看服务管理的界面。

Spring Boot Admin Server UI

在下一章节中,我们将学习Admin Client的相关知识。

Spring Boot Actuator的使用

Spring Boot Actuator的使用

Spring Boot(十六)— Actuator

Spring Boot Actuator提供了一个安全的、用于监控和管理Spring Boot应用程序的端点。在默认情况下,所有的Actuator端点都被安全保护机制所保护起来的。在本章节中,我们将学习有关Spring Boot Actuator的基础知识。

启动Spring Boot Actuator

为了在Spring Boot应用程序中启用Actuator功能,我们需要在Maven build文件中添加Spring Boot Actuator Starter依赖。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

配置Actuator

在application.properties文件中,我们需要进行如下的配置:

management.endpoint.env.enabled=true
management.endpoints.web.exposure.include=*
management.server.port=9000

说明:第一行配置是开启端点管理功能,第二行配置是禁用端点的安全检查,最后是为Actuator配置了一个独立的运行端口

如果采用的是YAML文件格式作为Spring Boot应用程序的配置文件,可以使用下面的方式进行配置:

management:
  endpoint:
      env:
        enable:true
  endpoints:
    web:
      exposure:
        include:*
  server:
    port:9000

注意:在Spring Boot 2.0的版本中,原来的management.security.enabled和management.port两个属性配置已经被废弃

启动应用程序

使用maven命令mvn clean install对项目进行打包,当控制台窗口提示“BUILD SUCCESS”信息后,你可以在当前工程目录下找到相应的JAR文件。

现在,你可以使用下面的命令来运行JAR文件:

java -jar JARFILE

下面是应用程序启动成功后控制台窗口的日志信息:

2019-03-12 00:34:58.880  INFO 14084 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2019-03-12 00:34:58.901  INFO 14084 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]

....

2019-03-12 00:34:59.710  INFO 14084 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 9000 (http)
2019-03-12 00:34:59.711  INFO 14084 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]

...

2019-03-12 00:34:59.757  INFO 14084 --- [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 15 endpoint(s) beneath base path '/actuator'
2019-03-12 00:34:59.928  INFO 14084 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 9000 (http) with context path ''
2019-03-12 00:34:59.959  INFO 14084 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''

通过日志信息可知,应用程序已经在Tomcat 8080端口上启动,Actuator以9000端口启动。

测试

打开Postman测试工具,在地址栏输入:http://localhost:9000/actuator 并发送请求:

可以看到,Spring Boot Actuator列举了所有的管理端点信息,接下来,将通过一个表格对Actuator中几个重要的端点加以说明:

EndPoint 说明
/metrics 查看应用程序指标,如内存使用率,线程信息、类以及系统运行时间等信息
/env 查看应用程序的环境变量
/beans 查看应用程序中的Bean及其类型、生命周期和依赖关系
/health 查看应用程序的健康状况
/info 查看有关Spring Boot应用程序的基本信息
/trace 查看Rest端点的Traces列表信息
Spring Boot应用中进行任务调度

Spring Boot应用中进行任务调度

Spring Boot(十五)— 任务调度

任务调度(也可以称为定时任务)是指在特定的时间段去执行一个规定的任务过程。Spring Boot为开发者提供了一个更优雅的方式创建任务调度程序。在本章节中,我们将学习使用Spring Boot来创建任务调度程序。

任务调度分为两种类型,一种是间隔时间执行的任务,如每隔3秒执行一次任务程序;另外一种时指定具体时间的任务,如在每天的凌晨整点备份数据库。

Cron表达式

在开始讲解定时任务之前,先来看一下定时任务中的Cron表达式的相关内容。Cron表达式用于配置CronTrigger实例,它是org.quartz.Trigger的子类。Cron表达式被放置在@Scheduled 注释标签中,下面的代码给出了一个cron表达式的样例:

@Scheduled(cron = "0/5 * 22 * * ?")
public void cronJobSchedule(){
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    Date now = new Date();
    logger.info("Java cron job expression scheduler::"+sdf.format(now));
}

在cron表达式中,一共有七位表达式参数,我们将使用一张表格来了解各个参数的用途:

位数 说明 范围
第一位 表示秒 取值范围:0-59
第二位 表示分钟 取值范围:0-59
第三位 表示小时 取值范围:0-23
第四位 表示日期 取值范围:1-31
第五位 表示月份 取值范围:1-12
第六位 表示星期 取值范围:1-7
第七位 表示年份,通常置空 取值范围:1970-2099

说明,在第六位星期参数中,1表示的是星期日,除使用数字表示外,还可以使用表示星期的英文缩写来设置

了解了cron表达式的语法规则后,我们再来了解一下表达式中各种占位符的含义。cron表达式中一共可以使用的占位符有5个,如下表所示:

占位符 说明 示例
(星号)* 可以理解为一个周期 每秒、没分、每小时等
(问好)? 只能出现在日期和星期两个位置中 表示时间不确定
(横线)- 表示一个时间范围 如在小时中10-11,表示从上午10点到上午11点
(逗号), 表示一个列表值 如在星期中使用:1,3,5 表示星期一、星期三和星期五
(斜杠)/ 表示一个开始时间和间隔时间周期 在分钟中使用:0/15 表示从0分开始,每15分钟运行一次

下面将列举一些示例来说明cron表达式和占位符:

表达式 说明
0 0 0 每天00:00:00执行任务
0 30 10 每天上午10:30:00执行任务
0 30 10 ? 每天上午10:30:00执行任务
0 0/15 10 ? 每天上午10:00:00、10:15:00、10:30:00和10:45:00这四个时间点执行任务
0 0 0 ? * 1 每个星期天的凌晨整点执行任务
0 0 0 ? * 1#3 每个月的第三个星期天的凌晨整点执行任务

开启定时任务

在Spring Boot应用程序中,需要使用@EnableScheduling注解来开启对定时任务的支持,并且该注解应该用于应用程序主类上,下面的代码演示了在Spring Boot中开启定时任务支持。

package com.ramostear.application;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
public class ScheduleApplication {

    public static void main(String[] args) {
        SpringApplication.run(ScheduleApplication.class, args);
    }

}

固定时间任务

下面我们将使用cron表达式创建一个固定时间的调度任务来实现每天的22点到23点每隔15秒钟执行一次任务。

package com.ramostear.application.schedule;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author ramostear
 * @create-time 2019/3/11 0011-21:49
 * @modify by :
 * @since:
 */
@Component
public class DemoScheduler {

    private static final Logger logger = LoggerFactory.getLogger(DemoScheduler.class);

    @Scheduled(cron = "0/15 * 22-23 * * ?")
    public void cronJobSchedule(){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        Date now = new Date();
        logger.info("Java cron job expression scheduler::"+sdf.format(now));
    }
}

下面的文本是应用程序在23:09分启动后,控制台窗口输出的日志信息:

[2019-03-11T23:09:00.000z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][26][INFO ] 
Java cron job expression scheduler::2019-03-11 23:09:00.001
[2019-03-11T23:09:15.015z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][26][INFO ] 
Java cron job expression scheduler::2019-03-11 23:09:15.002
[2019-03-11T23:09:30.030z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][26][INFO ] 
Java cron job expression scheduler::2019-03-11 23:09:30.001
[2019-03-11T23:09:45.045z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][26][INFO ] 
Java cron job expression scheduler::2019-03-11 23:09:45.002
[2019-03-11T23:10:00.000z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][26][INFO ] 
Java cron job expression scheduler::2019-03-11 23:10:00.002

固定周期任务

固定时间周期调度任务是指从应用程序启动开始,在固定的时间周期执行一次任务,如每1000毫秒执行一次、每1分钟执行一次。下面的代码给出了创建固定周期调度任务的示例:

@Scheduled(fixedRate = 1000)
public void fiexdRateSchedule(){
    //TODO ...
}

通过配置fixedRate参数的值,实现从应用程序启动后,每隔5秒钟执行一次任务。

package com.ramostear.application.schedule;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author ramostear
 * @create-time 2019/3/11 0011-21:49
 * @modify by :
 * @since:
 */
@Component
public class DemoScheduler {

    private static final Logger logger = LoggerFactory.getLogger(DemoScheduler.class);

    @Scheduled(fixedRate=5000)
    public void fixedRateSchedule(){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        Date now = new Date();
        logger.info("Java fixedRate scheduler::"+sdf.format(now));
    }
}

下面的文本是在23:18分启动应用程序后,控制台窗口输出的日志信息。

[2019-03-11T23:18:22.022z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][33][INFO ] 
Java fixedRate scheduler::2019-03-11 23:18:22.062
[2019-03-11T23:18:27.027z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][33][INFO ] 
Java fixedRate scheduler::2019-03-11 23:18:27.062
[2019-03-11T23:18:32.032z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][33][INFO ] 
Java fixedRate scheduler::2019-03-11 23:18:32.062
[2019-03-11T23:18:37.037z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][33][INFO ] 
Java fixedRate scheduler::2019-03-11 23:18:37.063
[2019-03-11T23:18:42.042z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][33][INFO ] 
Java fixedRate scheduler::2019-03-11 23:18:42.062

时延调度

所谓的时延调度,是通过设置initialDelayfixedDelay属性的值来控制当应用程序启动成功后,推迟一定时间再执行调度任务,其使用的语法如下:

@Scheduled(fixedDelay=1000,initialDelay=1000)
public fixedDelaySchedule(){

}

现在,我们将实现一个特定的定时任务需求:在应用程序启动成功后延迟10秒钟,再以每5秒钟的频率执行任务:

package com.ramostear.application.schedule;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author ramostear
 * @create-time 2019/3/11 0011-21:49
 * @modify by :
 * @since:
 */
@Component
public class DemoScheduler {

    private static final Logger logger = LoggerFactory.getLogger(DemoScheduler.class);

    @Scheduled(fixedDelay = 5000,initialDelay = 10000)
    public void fixedRateAndInitialDelaySchedule(){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        Date now = new Date();
        logger.info("Java fixedRate and initialDelay scheduler::"+sdf.format(now));
    }
}

下面的文本显示了在23:30:59启动应用程序,控制台窗口输出的日志信息:

[2019-03-11T23:31:01.001z][org.springframework.boot.StartupInfoLogger][main][59][INFO ] Started ScheduleApplication in 2.193 seconds (JVM running for 2.904)
[2019-03-11T23:31:11.011z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][40][INFO ] Java fixedRate and initialDelay scheduler::2019-03-11 23:31:11.639
[2019-03-11T23:31:16.016z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][40][INFO ] Java fixedRate and initialDelay scheduler::2019-03-11 23:31:16.640
[2019-03-11T23:31:21.021z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][40][INFO ] Java fixedRate and initialDelay scheduler::2019-03-11 23:31:21.641
[2019-03-11T23:31:26.026z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][40][INFO ] Java fixedRate and initialDelay scheduler::2019-03-11 23:31:26.643
[2019-03-11T23:31:31.031z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][40][INFO ] Java fixedRate and initialDelay scheduler::2019-03-11 23:31:31.644

从日志信息中可以看到,应用程序在23:31:01启动成功。等待十秒后,在23:31:11输出了第一条日志信息,往后每隔5秒输出一条日志信息。

注意:上面所设置的参数都是以毫秒为单位

本章节的课程源码已经上传至Github代码仓库,你可以访问下面的链接获取课程源码:https://github.com/ramostear/spring-boot-schedule-tutorial

在Spring Boot中提供国际化支持

在Spring Boot中提供国际化支持

Spring Boot(十四)— 国际化支持

国际化是一个可以让应用程序适应不同语言和区域显示而无需修改工程代码的一种软件本地化自适应能力。在本章节中,将使用Spring Boot与Thymeleaf来演示国际化的支持,系统会自动根据当前的语言环境或者Session中的语言来读取对应的语言模板。

依赖

需要将Spring Boot Web Starter和Spring Boot Thymeleaf Starter依赖加入到工程中。下面是Maven的build文件内容:

<?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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.ramostear</groupId>
    <artifactId>i18n</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>i18n</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

配置LocaleResolver

需要为应用程序配置一个默认的本地化语言环境的解析器。在Spring Boot应用程序中,可以通过下面的方式配置一个默认的 LocaleResolver:

@Bean
    public LocaleResolver localeResolver(){
        SessionLocaleResolver resolver = new SessionLocaleResolver();
        resolver.setDefaultLocale(Locale.US);
        return resolver;
    }

配置拦截器

需要使用LocaleChangeInterceptor拦截语言参数的变化,并设置语言参数的名称。

@Bean
    public LocaleChangeInterceptor localeChangeInterceptor(){
        LocaleChangeInterceptor interceptor = new LocaleChangeInterceptor();
        interceptor.setParamName("lang");
        return interceptor;
    }

注册拦截器

为了让LocaleChangeInterceptor生效,需要将拦截器注册到Spring Boot的拦截器注册表中。

@Override
    public void addInterceptors(InterceptorRegistry registry){
        registry.addInterceptor(localeChangeInterceptor());
    }

国际化消息资源

在默认的情况下,Spring Boot 应用程序从类路径src/main/resources目录中获取国际化消息资源。缺省语言资源文件名为message.properties,其他不同语言的资源文件命名模式为:message_xx.properties.xx代表区域代码。

我们提供两种语言的显示,一种时默认的英语消息,一种是中文消息。英语的资源文件配置在index.properties中进行设置。

index.msg = welcome to spring boot i18n tutorial.

中文资源在index_zh_CN.properties中进行设置。

index.msg = 欢迎阅读Spring Boot 国际化教程.

视图模板

在模板页面中,使用语法#{key}的方式获取国际化资源文件设置的值

<h1 th:text="#{index.msg}"></h1>

控制器

这里我们创建一个简单的控制器,返回视图路径即可:

package com.ramostear.application.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * @author ramostear
 * @create-time 2019/3/11 0011-18:12
 * @modify by :
 * @since:
 */
@Controller
public class I18NController {

    @GetMapping("/index.html")
    public String index(){
        return "index";
    }
}

运行测试

启动应用程序,打开浏览器并在地址栏输入:http://localhost:8080/index

此时,没有给任何的语言参数,Spring Boot应用程序默认使用US资源文件。

接下来,修改请求地址为:http://localhost:8080/index?lang=zh_CN :

现在,已经成功将界面从英文状态切换到中文状态进行显示。

代码清单

本次教程的源代码已经上传到github仓库,点击下面的链接可以获得所有的源码:https://github.com/ramostear/spring-boot-i18n-tutorial

如何在Spring Boot中解决跨域问题?

如何在Spring Boot中解决跨域问题?

Spring Boot(十三)— CORS跨域支持

CORS,全称Cross-Origin Resource Sharing,是一种允许当前域(domain)的资源(比如html/js/web service)被其他域(domain)的脚本请求访问的机制,通常由于同域安全策略(the same-origin security policy)浏览器会禁止这种跨域请求。它会在你进行如下的请求时被触发:

在本章节的内容中,我将以一个简单的案例来讲解在Spring Boot中如何处理跨域请求资源。

1. 局部跨域

在Spring Boot应用程序中,你可以使用@CrossOrign注解来开启单个控制器支持跨域请求操作。需要注意@CrossOrign的作用范围只在被注释的Rest API(局部支持跨域)。下面的代码给出了一个简单的演示:

@GetMapping("/users")
@CrossOrign(origins="http://localhost:8080")
public ResponseEntity<Object> users(){
    return null;
}

2. 全局跨域

Spring Boot提供了显示Bean装配的方式配置允许全局跨域操作。你可以参照下面给出的代码配置允许全局跨域请求:

@Bean
    public WebMvcConfigurationSupport crossConfig(){
        return new WebMvcConfigurationSupport(){
            @Override
            public void addCorsMappings(CorsRegistry registry){
                registry.addMapping("/users").allowedOrigins("http://localhost:8080");
            }
        };
    }

3. 跨域调用

现在,创建一个控制调用第六章—RESTful Web服务,获取用户的信息。在这里,我们使用RestTemplate调用User Restful Web服务,如何使用RestTemplate,请阅读第十章 — RestTemplate相关内容。下面的代码显示了使用RestTemplate进行跨域调用Restful Web服务。

package com.ramostear.application.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;

/**
 * @author ramostear
 * @create-time 2019/3/11 0011-7:14
 * @modify by :
 * @since:
 */
@RestController
public class UserController {
    private static final String ROOT_URI = "http://localhost:8080/users";

    @Autowired
    RestTemplate restTemplate;

    @GetMapping("/users")
    public String getUsers(){
        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
        HttpEntity<String> entity = new HttpEntity<>(headers);
        return restTemplate.exchange(ROOT_URI, HttpMethod.GET,entity,String.class).getBody();
    }

}

除此之外,需要修改application.propertiesserver.port属性的值为8090(或者其他与User Restful Web服务不冲突的端口号):

server.port= 8090

现在,分别启动两个应用程序,并测试跨域调用是否成功。启动Postman测试应用程序,在地址栏输入:http://localhost:8090/users, 发送请求,并观察页面变化:

在Spring Boot中定义服务组件

在Spring Boot中定义服务组件

Spring Boot(十二)— 服务组件

所谓的服务组件(Service Component)— 就是用于处理系统业务逻辑的类,如果按照系统分层设计理论来划分,服务组件是位于业务层当中的类。在Spring Boot中,服务组件是一个被@Service注解进行注释的类,这些类用于编写系统的业务代码。在本章节中,将讲解如何创建并使用服务组件。

在开始正文之前,先来看两段示例代码。使用服务组件之前,我们需要定义服务组件接口类,用于索引服务组件提供的服务,代码如下所示:

public interface UserService{
    // TODO ...
}

然后,需要使用@Service注解对服务组件接口实现类进行注释,演示代码如下:

@Service(value="userService")
public class UserServiceImpl implements UserService{
    //TODO ...
}

最后,使用@Autowired注解来自动引用服务组件,代码如下:

@Controller
public class DemoController{
    @Autowired
    UserService userService;
    //TODO ...
}

在本次讲解中,我们依然以对用户的增、删、改、查为案例,将控制器中的业务方法迁移到服务组件中。

1. 创建服务接口

创建一个包含添加用户、更新用户、删除用户和查询用户的服务接口类 — 用户服务组件接口类。详细代码如下:

package com.ramostear.application.service;

import com.ramostear.application.model.User;

import java.util.Collection;

/**
 * Created by ramostear on 2019/3/11 0011.
 */
public interface UserService {

    /**
     * create user
     * @param user
     */
    void create(User user);

    /**
     * update user info by ID
     * @param id
     * @param user
     */
    void update(long id,User user);

    /**
     * delete user by ID
     * @param id
     */
    void delete(long id);

    /**
     * query all user
     * @return
     */
    Collection<User> findAll();
}

2. 实现服务接口

创建一个接口实现类,用于实现其中的增、删、改、查四个业务方法,并用@Service注解进行标注,具体代码如下:

package com.ramostear.application.service.impl;

import com.ramostear.application.model.User;
import com.ramostear.application.service.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * @author ramostear
 * @create-time 2019/3/11 0011-4:29
 * @modify by :
 * @since:
 */
@Service(value="userService")
public class UserServiceImpl implements UserService {

    private static Map<Long,User> userRepo = new HashMap<>();

    @PostConstruct
    public void initUserRepo(){
        User admin = new User();
        admin.setId(1).setName("admin");
        userRepo.put(admin.getId(),admin);

        User editor = new User();
        editor.setId(2).setName("editor");
        userRepo.put(editor.getId(),editor);
    }
    @Override
    public void create(User user) {
        userRepo.put(user.getId(),user);
    }

    @Override
    public void update(long id, User user) {
        userRepo.remove(id);
        user.setId(id);
        userRepo.put(id,user);
    }

    @Override
    public void delete(long id) {
        userRepo.remove(id);
    }

    @Override
    public Collection<User> findAll() {
        return userRepo.values();
    }
}

3. 使用服务组件

接下来,定义一个用户控制器,使用@Autowired注解来应用用户服务组件,实现对用户的增、删、改、查功能:

package com.ramostear.application.controller;

import com.ramostear.application.model.User;
import com.ramostear.application.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

/**
 * @author ramostear
 * @create-time 2019/3/11 0011-4:42
 * @modify by :
 * @since:
 */
@RestController
public class UserController {

    @Autowired
    UserService userService;


    @GetMapping("/users")
    public ResponseEntity<Object> users(){
        return new ResponseEntity<>(userService.findAll(), HttpStatus.OK);
    }

    @PostMapping("/users")
    public ResponseEntity<Object> create(@RequestBody User user){
       userService.create(user);
       return new ResponseEntity<>("User is created successfully.",HttpStatus.CREATED);
    }

    @PutMapping("/users/{id}")
    public ResponseEntity<Object> update(@PathVariable(name="id") long id,@RequestBody User user){
        userService.update(id,user);
        return new ResponseEntity<>("User is updated successfully.",HttpStatus.OK);
    }

    @DeleteMapping("/users/{id}")
    public ResponseEntity<Object> delete(@PathVariable(name = "id")long id){
        userService.delete(id);
        return new ResponseEntity<>("User is deleted successfully.",HttpStatus.OK);
    }
}

4. 数据模型

用户对象的代码沿用以往章节的User.java代码:

package com.ramostear.application.model;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

/**
 * @author ramostear
 * @create-time 2019/3/6 0006-3:12
 * @modify by :
 * @since:
 */
@Getter
@Setter
@NoArgsConstructor
public class User {
    private long id;
    private String name;

    public User setId(long id){
        this.id = id;
        return this;
    }

    public User setName(String name){
        this.name = name;
        return this;
    }
}

注:应用程序主类和Maven build文件与之前章节的代码形同,不再列举。

5. 运行测试

启动Spring Boot应用程序,然后打开Postman测试应用程序,分别进行如下的测试。

GET 请求:获取所有的用户信息。

URL地址:http://localhost:8080/users

获取用户信息

POST 请求:新增一位用户信息

URL地址:http://localhost:8080/users

请求参数:{“id”:3,”name”:”reader”}

新增用户

PUT请求:修改用户信息

URL地址:http://localhost:8080/users/3

请求参数:{“id”:3,”name”:”ramostear”}

修改用户

DELETE请求:删除用户信息

URL地址:http://localhost:8080/users/3

删除用户

6. 附件

本章节用于演示的项目源码已经上传到Github代码仓库,你可以通过下面的地址链接免费获取本章节的全部源码信息:https://github.com/ramostear/Spring-Boot-Service-Component

Spring Boot 2.0 概述

Spring Boot 2.0 概述

Spring Boot 2.0 概述

Spring Boot 是由Pivotal团队基于Java开发的一个开源框架,可用于构建独立的、可部署的生产环境下的Spring应用。

1 . 什么是微服务?

在介绍Spring Boot之前,我们先聊一聊微服务的概念。Micro Service是一种允许开发人员独立开发和部署服务的一种体系架构。每个服务实例都独立部署和运行,它们具有自身的操作流程。简单来说,微服务就是将传统的庞大的业务应用程序按照某种业务规则(轻量级模型)进行拆分,拆分后,每个服务都有自己的服务上线文边界,以达到服务区域内的自治,同时又可以通过消息总线与其他服务模块进行通信,协同完成某一个业务操作流程。

1.2. 微服务的好处

微服务为开发人员带来了以下的一些优势:

  • 易于部署
  • 简单的可扩展性
  • 与容器兼容
  • 最低限度的硬件配置
  • 开发时间短

2. 什么是Spring Boot?

Spring Boot 为Java开发人员提供了一个优秀的统一平台,开发人员可以利用Spring Boot 开发出一个生产级别的可独立运行的Spring应用程序。通过Spring Boot,开发人员可以使用最少的配置,完成复杂的Spring应用程序设置。

2.1. Spring Boot 的优势

使用Spring Boot进行开发,将具备如下的一些优势:

  • 使得Spring应用程序易于理解和开发
  • 提高开发效率
  • 缩短了软件交付的时间

2.2. Spring Boot 的设计目标

Spring Boot的出现,其追求的目标如下:

  • 弱化使用XML配置文件的方式对Spring应用程序进行设置
  • 以更简单易懂的方式开发生产级别的Spring应用程序
  • 以更短的时间交付可独立运行的Spring应用程序
  • 降低Spring 框架的学习门槛

3. 为什么选择Spring Boot?

要不要选择一门技术入手,需要分析它的用户群体数量、性能指标、普适性和学习成本。就Spring Boot本身而言,其自身具备如下的几个优点:

  • 提供了一种更为优雅和易懂的方式来配置Java Bean、XML和数据库事务
  • 提供了强大的批处理和REST Endpoint管理能力
  • 提供了强大的自动装配能力,减少人工干预的次数
  • 采用注解的方式开发应用程序
  • 极大的简化了依赖管理工作
  • 提供了嵌入式的Servlet容器,如Tomcat 、Jetty等

4. Spring Boot的工作方式

Spring Boot 通过 @EnableAutoConfiguration 注解将存在于项目类路径上的依赖项自动装配到应用程序中,无需其他的人工干预。使用@SpringBootApplication 注解标注一个包含main方法的类,此类就成为Spring Boot应用程序的主入口。@ComponentScan 注解将会触发Spring Boot自动扫描项目中包含的所有组件。

5 . Spring Boot Starter

对于一个大型的项目而言、最让开发人员头疼的事情是如何管理整个项目中的依赖关系和与之对应的版本问题。Spring Boot提供了一组特定的依赖项来帮助开发人员解决此问题。例如,如果要在Spring Boot项目中使用JPA来访问数据库,则只需要在项目中引入spring-boot-starter-data-jpa 依赖项即可。

几乎所有的Spring Boot Starter都遵循相同的命名模式:“spring-boot-starter-*” ,其中的“*”表示一种应用程序的类型名称

下面我们列举几个常用的Spring Boot Starter加以说明:

  • spring-boot-starter-web : 用于依赖Spring web
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
  • spring-boot-starter-thymeleaf : 用于依赖Thymeleaf模板引擎

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    
  • spring-boot-starter-test : 用于依赖单元测试

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
    

6 . 自动装配

Spring Boot Auto Configuration会自动将添加到项目中的依赖JAR包完成相应的配置。例如,如果你在pom.xml中引入了MySQL的依赖包,在不添加任何配置的情况下,Spring Boot会自动配置内置数据库。如果需要开启自动装配功能,需要在项目主类上添加@EnableAutoConfiguration注解或者@SpringBootApplication注解:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;

@EnableAutoConfiguration
public class Application{
    public static void main(String[] args){
        SpringApplication.run(Application.class);
    }
}

7. Spring Boot 主应用程序

一个Spring Boot的主应用程序需包含两个部分:

  • @SpringBootApplication 注解:用于标注一个类为Spring Boot应用的启动类
  • main 方法:Spring Boot应用程序的主入口

@SpringBootApplication是一个组合注解,它包含了自动装配、组件扫描和Spring Boot配置。我们也可以单独使用@EnableAutoConfiguration@ComponentScan@SpringBootConfiguration 注解来标注主类。

使用@SpringBootApplication进行标注:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application{
    public static void main(Stirng[] args){
        SpringApplication.run(Application.class);
    }   
}

使用@EnableAutoConfiguration@ComponentScan@SpringBootConfiguration 进行标注:

@EnableAutoConfiguration
@ComponentScan
@SpringBootConfiguration
public class Application{
    public static void main(String[] args){
        SpringApplication.run(Application.class);
    }
}

8. 组件扫描

Spring Boot应用程序在程序初始化阶段完成组件扫描的工作。使用@ComponentScan对主类进行标注,将开组件扫描功能:

@ComponentScan
public class Application{
    public static void main(String[] args){
        SpringApplication.run(Application.class);
    }
}
如何在Tomcat中部署Spring Boot程序?

如何在Tomcat中部署Spring Boot程序?

Spring Boot(三)—Tomcat中部署

Spring Boot应用程序除了生成JAR文件直接运行外,也可以创建成一个WAR文件部署到Web服务器中。在本章节中,我将为你展示如何使用Spring Boot创建WAR文件并在Tomcat Web容器中进行部署。

1. Spring Boot Servlet初始化程序

如果想要在Tomcat Web服务器中部署Spring Boot应用程序,需要让被@SpringBootApplication注解注释的的主类继承SpringBootServletInitializer类,并覆盖configure方法。

下面的代码片段是使用JAR文件运行Spring Boot应用程序的主文件代码:

package com.ramostear.spring.boot.deploytomcat;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author ramostear
 */
@SpringBootApplication
public class DeployTomcatApplication {

    public static void main(String[] args) {
        SpringApplication.run(DeployTomcatApplication.class, args);
    }

}

现在,我们需要扩展SpringBootServletInlitializer类以支持WAR文件部署。扩展后的主类代码如下:

package com.ramostear.spring.boot.tutorial2;

@SpringBootApplication
public class Application extends SpringBootServletInitializer{
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder){
        return builder.sources(Application.class,args);
    }
    public static void main(String[]args){
        SpringBootApplication.run(Application.class,args);
    }
}

2. 设置主类

对于Spring Boot应用程序,你需要明确的指出在maven构建项目是主类的位置。你需要在pom.xml文件加入如下的代码:

<start-class>com.ramostear.spring.boot.tutorial2.Application</start-class>

3. 更新打包方式

想要将Spring Boot应用程序从jar包更换为war包,还需要修改pom.xml中的packaging配置:

<packaging>war</packaging>

现在,我们可以编写一个简单的REST Endpoint来返回字符串“Hey Spring Boot,I am from tomcat server.”。为了演示此功能,我们还需要将Spring Boot Web Starter添加到pom.xml文件中:

<dependencies>
    ...
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    ...
</dependencies>

接下来,我们将在主类中编写一个简单的REST Endpoint:

package com.ramostear.spring.boot.deploytomcat;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author ramostear
 */
@SpringBootApplication
@RestController
public class DeployTomcatApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(DeployTomcatApplication.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(DeployTomcatApplication.class);
    }

    @GetMapping("/")
    public String sayHello(){
        return "Hey Spring Boot,I am from tomcat server.";
    }
}

4. 打包Spring Boot应用程序

我们将使用Maven打包命令创建一个可以在Tomcat服务器中运行的WAR文件。使用Maven命令:mvn:package打包应用程序。你可以在当前工程下的target目录中找到war文件:

C:\~projectdir> mvn package

控制台输出:

[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building deploy-tomcat 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:3.1.0:resources (default-resources) @ deploy-tomcat ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] Copying 0 resource

.....


[INFO] 
[INFO] --- spring-boot-maven-plugin:2.1.3.RELEASE:repackage (repackage) @ deploy-tomcat ---
[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 10.273 s
[INFO] Finished at: 2019-03-04T23:34:12+08:00
[INFO] Final Memory: 38M/288M
[INFO] ------------------------------------------------------------------------

Process finished with exit code 0

5 . 部署到Tomcat

现在,运行Tomcat服务器,并在webapps目录下部署准备好的war文件。你也可以登录Tomcat的管理界面上传war文件并部署:

成功部署war文件后,代开浏览器,并在浏览器地址栏输入:http://localhost:8080/deploy-tomcat-0.0.1-SNAPSHOT/ ,观察页面输出结果:

6 . 主要代码

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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.ramostear</groupId>
    <artifactId>deploy-tomcat</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>deploy-tomcat</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</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-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    <packaging>war</packaging>
</project>

DeployTomcatApplication.java文件:

package com.ramostear.spring.boot.deploytomcat;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author ramostear
 */
@SpringBootApplication
@RestController
public class DeployTomcatApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(DeployTomcatApplication.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(DeployTomcatApplication.class);
    }

    @GetMapping("/")
    public String sayHello(){
        return "Hey Spring Boot,I am from tomcat server.";
    }
}
Spring Boot 2.0 快速构建应用

Spring Boot 2.0 快速构建应用

Spring Boot系列教程(二)快速构建

在本章节中,将想你展示如何利用Spring Initializer快速构建一个Spring Boot应用程序。

1. Spring Initializer

快速构建起一个Spring Boot应用程序的方法之一是使用Spring Initializer.首先,我们需要访问Spring Initializer的官网https://start.spring.io ,接下来,我们需要选择相应的构建方式、语言以及Spring Boot的版本。默认的构建方式是Maven Project,使用Java语言,Spring Boot的版本默认最新版本。

接下来,我们需要提供一个项目的GroupId和ArtifactId,最后是检索并选择我们需要引入的依赖包。以上选择设置完成后,点击“Generate Project”按钮生成并下载Spring Initializer生成的项目包。本次案例中,我们将添加spring-boot-starter-web依赖项,用于编写一个REST风格的端点示例:

Spring Initializer

2.Maven

现在,解压下载后的项目压缩包,并导入到对应的IDE中(本次案例使用的是Spring Tools Suite),打开根目录下的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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.ramostear</groupId>
    <artifactId>quick-build</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>quick-build</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</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-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

3. 依赖包

Spring Boot为开发者提供了很多starters用于快速添加依赖包。本次案例中我们添加了一个Spring Web依赖的Starter:

...
<dependencies>
    ...
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    ...
</dependencies>
...

4. 主类和方法

一个Spring Boot应用程序需要提供应用主类和方法,并且该主类需要(通常)使用@SpringBootApplication注解进行标注。你可以在src/java/main目录下找到主类文件。

此示例中,主类文件位于src/java/main目录中,且位于com.ramostear.quickbuild包中:

package com.ramostear.quickbuild;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
 * @author:  ramostear
 * @date:   2019年3月3日下午9:49:28
 */
@SpringBootApplication
public class QuickBuildApplication {

    public static void main(String[] args) {
        SpringApplication.run(QuickBuildApplication.class, args);
    }

}

5. REST EndPoint

接下来,我们将在主类中编写一个返回“Hello Spring Boot”信息的Rest Endpoint。我们需要在主类上新增一个@ResController注解,然后使用@GetMapping注解注释我们的请求方法:

package com.ramostear.quickbuild;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * @author:  ramostear
 * @date:   2019年3月3日下午9:49:28
 */
@SpringBootApplication
@RestController
public class QuickBuildApplication {

    public static void main(String[] args) {
        SpringApplication.run(QuickBuildApplication.class, args);
    }


    @GetMapping("/")
    public String sayHello() {
        return "Hello Spring Boot.";
    }


}

6. 创建可执行的JAR文件

现在,我们可用通过Maven命令行来创建一个可执行的JAR文件。在命令行工具中使用Maven命令:mvn clean install

mvn clean install

执行上述命令后,你可以在控制台看到BUILD SUCCESS消息:

BUILD SUCCESS

7. 运行JAR 文件

上述步骤完成后,可以在target目录中找到创建的JAR文件:

target dir

现在,可以使用命令java -jar 运行JAR文件。本案例中创建的JAR文件名为quick-build-0.0.1-SNAPSHOT.jar

C:\Users\Administrator\Desktop\quick-build\target> java -jar quick-build-0.0.1-SNAPSHOT.jar

JAR文件成功运行后,你可以在控制台下看到如下的信息输出:

console start infomatioin

控制台信息显示Tomcat容器的服务端口为8080,打开浏览器并在地址栏输入http://localhost:8080/,你可以看到如下的输出:

browser info

配置Spring Boot 应用程序参数

配置Spring Boot 应用程序参数

Spring Boot(四)—应用程序属性

Spring Boot应用程序属性支持我们开发的应用工作在不同的环境中。在本章节中,我将展示如何配置和指定Spring Boot 应用程序的属性。

1. 命令行属性

Spring Boot应用程序可以将命令行属性转换为Spring Boot Environment属性。在Spring Boot中,命令行属性的优先级高于其他资源属性。在默认情况下,Spring Boot使用8080端口作为Tomcat的启动端口。下面让我们使用命令行属性来更改端口号:

  • 1.创建可执行的JAR文件,然后使用命令 java -jar 运行jar文件。

  • 2.使用命令行更改Spring Boot应用程序的默认端口号

    D:\work\2019\domain-driver-design\deploy-tomcat\target> java -jar deploy-tomcat-0.0.1-SNAPSHOT.war --server.port = 8888
    

    :你可以使用分隔符“-”来分割多个属性

2. 属性文件

属性文件的作用是可以在单个文件中设置多个属性的值。在Spring Boot 应用程序中,属性保存在类路径下的application.properties文件中。通常情况下,application.properties文件存放在src/main/resource目录中,其属性设置格式如下:

server.port = 8888
server.tomcate.max-http-post-size = -1
spring.application.name = spring-boot-tutorial
spring.datasource.username = admin
spring.datasource.password = springboottutorial
...

3 . YAML文件

Spring Boot应用程序支持基于YAML格式的属性配置文件为Spring Boot提供属性设置。YAML文件时Spring Boot比较推荐的属性配置文件,相较于application.properties文件,YAML配置文件册层次更为清晰。同样的,YAML文件也存放于类路径下(“src/main/resource”),其文件内容格式为:

server:
  port: 8888
  tomcate:
    max-http-post-size: -1
spring: 
  application:
    name: spring-boot-tutorial
  datasource:
    username: admin
    password: springboottutorial
  mvc:
    favicon:
      enabled: false

注:YAML文件中,每个属性的上下层级之间相差两个空格

4. 外部属性文件

Spring Boot支持我们将属性配置文件放在外部空间中,而不仅仅局限于将配置文件放置在类路径下。在运行JAR文件的时候,我们可以指定外部配置文件的存放路径。

D:\work\2019\domain-driver-design\deploy-tomcat\target> java -jar -Dspring.config.location = D:\work\configs\application.properties deploy-tomcat-0.0.1-SNAPSHOT.war

5. @Value 注解

在Spring Boot应用程序中,可以使用@Value注解读取应用中的属性值,其读取相关属性值得语法如下:

@Value("${property_key_name}")
Object param;

接下来,我们将演示使用@Value注解来读取application.properties配置文件中spring.application.name属性的值:

@Value("${spring.application.name}")
private String appName;

完整的示例代码:

package com.ramostear.spring.boot.properties;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class SpringBootPropertiesApplication {

    @Value("${spring.application.name}")
    private String appName;

    public static void main(String[] args) {
        SpringApplication.run(SpringBootPropertiesApplication.class, args);
    }

    @GetMapping("/")
    public String say(){
        return appName;
    }
}

application.properties文件内容:

spring.application.name= Spring Boot Properties Demo

下面,我们启动程序,并在浏览器地址栏中输入:http://localhost:8080/ ,观察浏览器页面结果:

注:如果在程序运行时没有在配置文件中提供该属性,则Spring Boot将抛出IllegalArgumentException异常信息:

Could not resolve placeholder 'spring.application.name' in value "${spring.application.name}"

因为Spring Boot无法解析表达式“${spring.application.name}”中的占位符“spring.application.name”。

要解决上面演示的问题,只需要在表达式后面增加一个默认的属性值即可。

  • 语法:

    @Value("${property_key_name:default_value}")
    
  • 代码示例:

    package com.ramostear.spring.boot.properties;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @SpringBootApplication
    @RestController
    public class SpringBootPropertiesApplication {
    
        @Value("${spring.application.name:Spring Boot Application}")
        private String appName;
    
        public static void main(String[] args) {
            SpringApplication.run(SpringBootPropertiesApplication.class, args);
        }
    
        @GetMapping("/")
        public String say(){
            return appName;
        }
    }
    

再次运行应用程序,观察浏览器页面变化:

6. active配置模式

Spring Boot支持基于Spring active模式来设置不同环境下的应用属性。例如,我们可以创建两份配置文件application_dev.properties和application_prod.properties,application_dev.properties用于开发环境中设置属性,application_prod.properties则用于生产环境中配置应用属性。

首先,我们来看一下默认的application.properties文件中的配置:

server.port = 8888
spring.application.name = Default Spring Boot Application Name

启动应用程序,观察控制台输出信息:

2019-03-05 01:29:19.590  INFO 7828 --- [main] .r.s.b.p.SpringBootPropertiesApplication : 
No active profile set, falling back to default profiles: default

2019-03-05 01:29:20.869  INFO 7828 --- [main] o.s.b.w.embedded.tomcat.TomcatWebServer  : 
Tomcat initialized with port(s): 8888 (http)

现在,Tomcat服务器已经使用8888端口启动成功,且提示没有设置任何的active profile。

接下来,我们创建两个active配置文件application_dev.properties和application_prod.properties,其配置内容如下。

application_dev.properties配置文件:

server.port = 8081
spring.application.name = Development Spring Boot Application Name

application_prod.properties配置文件:

server.port = 8082
spring.application.name = Product Spring Boot Application Name

两个独立的配置文件准备好后,我们需要调整application.properties文件的配置内容,以模拟使用active配置文件来切换不同环境下使用不同的属性配置:

  • 1.将默认的属性配置切换到dev模式上,切换到开发环境上的配置命令如下:

    D:\work\2019\domain-driver-design\spring-boot-properties\target> java -jar spring-boot-properties-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev
    

    你可以在控制台中观察到如下的输出:

    2019-03-05 02:02:00.013  INFO 7700 ---[main] .r.s.b.p.SpringBootPropertiesApplication : The following profiles are active: dev
    2019-03-05 02:02:01.697  INFO 7700 --- [main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8081 (http)
    2019-03-05 02:02:01.732  INFO 7700 --- [main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
    

    现在,Tomcat服务器已经使用端口8081(http)

  • 2.接下来,我们再将应用从dev切换到prod环境上,执行如下命令:

    D:\work\2019\domain-driver-design\spring-boot-properties\target>java -jar spring-boot-properties-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod
    

    你可以在控制台中观察到如下的输出:

    2019-03-05 02:09:33.983  INFO 5944 --- [main] .r.s.b.p.SpringBootPropertiesApplication : The following profiles are active: prod
    
    2019-03-05 02:09:35.643  INFO 5944 --- [main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8082 (http)
    
    2019-03-05 02:09:35.678  INFO 5944 --- [main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
    

    现在,Tomcat服务器已经使用端口8082(http)

如果应用使用的是YAML文件来配置应用属性,我们可以将不同环境的配置信息放在一个配置文件中,而不用像使用properties文件那样创建多个独立的配置文件。

下面我们将演示使用YAML文件来配置并切换不同环境下的属性配置,在YAML文件中,使用分隔符“—-”来分割不同active下的属性配置:

application.yml配置文件

spring:
   application:
      name: Default Spring Application Name
server:
   port: 8080

---
spring:
   profiles: dev
   application:
      name: Development Spring Application Name
server:
   port: 8081

---
spring:
   profiles: prod
   application:
      name: Product Spring Application Name
server:
   port: 8082

说明:使用YAML作为配置文件时,切换active的命令与使用Properties配置文件时一致。