目录 start

  1. SpringBoot
    1. 思考
    2. 参考教程
      1. 系列
    3. 简易使用
    4. 使用SpringBootCLI
    5. 测试模块
    6. Profils
      1. 多种配置文件并切换
        1. yml方式
        2. yml和properties结合
      2. 应用配置文件
    7. Events
    8. Logging
    9. Web模块
      1. Lisener
        1. ServletContextListener
      2. 上传下载文件
      3. 错误页面跳转配置
      4. 跨域
    10. 全局异常处理
    11. HTTPS的配置
    12. 线程池
    13. 项目部署
      1. 编译打包jar/war
        1. war
        2. jar
      2. 构建docker镜像
        1. 手动方式
        2. gradle结合docker
      3. 热部署

目录 end|2019-10-19 17:04|


SpringBoot

首页

一个简化Spring开发的框架,微服务SpringCloud的基础
1.5.14 官方文档

思考

参考教程

Guide
小马哥书籍《Spring Boot 编程思想》示例工程

系列


简易使用

使用Idea的话就可以直接创建项目 使用别的可以下载zip进行导入 | 官方初始项目构建 下载地址

目录结构最好如下 *Application类要处于所有用了Springboot注解的类的顶级目录, 这样默认才能扫描到

1
2
3
4
5
6
7
8
├── config/
├── controller/
├── dao/
├── domain/
├── GraduateApplication.java
├── service/
├── ServletInitializer.java
└── util/

使用SpringBootCLI

  • 使用 SDKMAN 进行安装
    • 使用git bash运行 curl -s get.sdkman.io | bash
    • source "/Users/{yourname}/.sdkman/bin/sdkman-init.sh"根据实际目录去运行
    • spring –version
  • 官方下载地址 所有版本

测试模块

  • 了解这些测试注解 的作用和使用场景
1
2
3
4
5
6
7
8
// 依赖于Springboot环境的测试类的必备注解
@RunWith(SpringRunner.class)
@SpringBootTest

// 使用内存数据库测试
@ComponentScan("com.github.kuagncp") // 如果有类没注入需要手动设置扫面
@RunWith(SpringJUnit4ClassRunner.class)
@DataJpaTest
  • 可以使用MockMvc来测试Controller层的代码
  • 可以使用MockMvc的SpringSecurity支持来测试安全模块
  • 使用 WebIntegraionTest 测试运行中的Web容器
    • 启动嵌入式的Servlet容器来进行测试,下断言
  • 使用随机端口启动服务器 配置local.server.port=0
  • 使用Selenium来测试HTML页面,模拟浏览器的动作,查看系统运行状态

Profils

Spring Profiles

配置文件(application.properties或者yml) 加载顺序 | 官方文档说明

  1. 当前Jar/War目录下的/config目录 ./config/
  2. 当前目录 ./
  3. classpath 里的/config目录 classpath:/config/
  4. classpath 根目录 classpath:/

自定义配置文件名就要运行时加参数

  1. java -jar myproject.jar --spring.config.name=myproject
  2. java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties

参考博客: Spring Boot(五) - 外化配置

多种配置文件并切换

yml方式

  • 单文件配置文件 application.yml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    spring:
    profiles:
    active: development # 选用开发模式
    ---
    spring:
    profiles: development
    //一系列配置
    ---
    spring:
    profiles: production
    // 一系列配置
  • 或者 多文件放 application-{profile}.yml

yml和properties结合

  • 格式:application-{profile}.properties
  • 将上面的开发部分,发行部分的配置创建两个配置文件 application-dev.propertiesapplication-prod.properties
  • 在主配置文件application.yml中指明
    1
    2
    3
    spring:
    profiles:
    active: dev或者是prod

应用配置文件

依赖于 org.springframework.boot:spring-boot-configuration-processor

配置对应的实体类

1
2
3
4
5
6
@Data
@Component
@ConfigurationProperties(prefix = "graduate.main")
public class MainConfig {
private String delimiter;
}

应用配置类

1
2
3
4
@Configuration
@EnableConfigurationProperties(MainConfig.class)
public class AutoCustomConfig {
}

application.yml

1
2
3
graduate:
main:
delimiter: ,


Events

Note: Spring Events

配置成异步并使用线程池

1
2
3
4
5
6
7
8
9
10
11
@Configuration
public class AsynchronousSpringEventsConfig {
@Bean(name = "applicationEventMulticaster")
public ApplicationEventMulticaster simpleApplicationEventMulticaster() {
SimpleApplicationEventMulticaster eventMulticaster = new SimpleApplicationEventMulticaster();

SimpleAsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();
eventMulticaster.setTaskExecutor(taskExecutor);
return eventMulticaster;
}
}


Logging

默认可以通过 application.properties 配置框架的日志,以及应用具体到包和类的日志等级,日志文件等等

参考博客: Spring boot——logback 基础使用篇(一)
参考博客: springboot use logback能根据Profile配置,还能写if
spring boot logging

使用 logback 则需要配置 logback.xml 或者 logback-spring.xml 建议使用后者

  • 思考: 能否不同的包使用不同的pattern pattern

配置 pattern 并引用 MDC logging.pattern.level=%X{mdcData}%5p


Web模块

Lisener

ServletContextListener

1
2
3
4
5
6
7
8
9
10
11
12
@WebListener
public class ApplicationContext implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent event) {
System.out.println("Servlet容器初始化");
}

@Override
public void contextDestroyed(ServletContextEvent event) {
System.out.println("Servlet容器销毁");
}
}

上传下载文件

第一种直接上传到应用的webroot或者resources目录下,第二种上传到数据库中,第三种使用ftp。

  • Springboot上传文件
  • 上传文件有大小限制,使用如下方法进行配置 参考博客
    1
    2
    3
    4
    5
    6
    7
    8
    9
    @Bean
    public MultipartConfigElement multipartConfigElement() {
    MultipartConfigFactory factory = new MultipartConfigFactory();
    //单个文件最大
    factory.setMaxFileSize("80MB"); //KB,MB
    // 设置总上传数据总大小
    factory.setMaxRequestSize("102400KB");
    return factory.createMultipartConfig();
    }

错误页面跳转配置

1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
@Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {
return (container -> {
ErrorPage error401Page = new ErrorPage(HttpStatus.FORBIDDEN, "/403.html");
ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/404.html");
ErrorPage error500Page = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/500.html");
container.addErrorPages(error401Page, error404Page, error500Page);
});
}
}

跨域

不同的域名(主机)端口都会导致跨域问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Configuration
public class CorsConfig {
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*"); // 允许任何域名使用
corsConfiguration.addAllowedHeader("*"); // 允许任何头
corsConfiguration.addAllowedMethod("*"); // 允许任何方法(post、get等)
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig()); // 4
return new CorsFilter(source);
}
}

全局异常处理

  1. 新建类, 加上注解 ControllerAdvice
  2. 方法上使用注解 ExceptionHandler(Exception.class) 处理所有异常
  3. 然后返回值的写法和普通Controller一样, 返回JSON就ResponseBody

HTTPS的配置

参考博客

  • 签发证书:
    1
    keytool -genkey -alias tomcat -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 3650
1
2
3
4
5
6
7
8
9
10
server:
context-path: /myth
ssl:
key-store: classpath:keystore.p12
key-store-password: demo1429336
key-store-type: PKCS12
key-alias: tomcat
port: 8888
session:
timeout: 3000

任意的一个@Configuration注解类里添加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Bean
public TomcatEmbeddedServletContainerFactory servletContainerFactory() {
TomcatEmbeddedServletContainerFactory factory =
new TomcatEmbeddedServletContainerFactory() {
@Override
protected void postProcessContext(Context context) {
//SecurityConstraint必须存在,可以通过其为不同的URL设置不同的重定向策略。
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint("CONFIDENTIAL");
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/*");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
factory.addAdditionalTomcatConnectors(createHttpConnector());
return factory;
}

private Connector createHttpConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("http");
connector.setSecure(false);
connector.setPort(8887);//http端口(这是要新增加的一个端口)
connector.setRedirectPort(8888);// https 端口配置文件中tomcat启动的默认端口
return connector;
}

  • 另一种方式 参考博客
    方式不一样,没有成功
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    ############ 证书颁发机构
    # CA机构私钥
    openssl genrsa -out ca.key 2048
    # CA证书
    openssl req -x509 -new -key ca.key -out ca.crt
    ############ 服务端
    # 生成服务端私钥
    openssl genrsa -out server.key 2048
    # 生成服务端证书请求文件
    openssl req -new -key server.key -out server.csr
    # 使用CA证书生成服务端证书 关于sha256,默认使用的是sha1,在新版本的chrome中会被认为是不安全的,因为使用了过时的加密算法。
    openssl x509 -req -sha256 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 -out server.crt
    # 打包服务端的资料为pkcs12格式(非必要,只是换一种格式存储上一步生成的证书) 生成过程中,需要创建访问密码,请记录下来。
    openssl pkcs12 -export -in server.crt -inkey server.key -out server.pkcs12
    # 生成服务端的keystore(.jks文件, 非必要,Java程序通常使用该格式的证书) 生成过程中,需要创建访问密码,请记录下来。
    keytool -importkeystore -srckeystore server.pkcs12 -destkeystore server.jks -srcstoretype pkcs12
    # 把ca证书放到keystore中(非必要)
    keytool -importcert -keystore server.jks -file ca.crt

线程池

  • 参考博客
  • 多线程以及异常处理 参考博客
    • 因为多线程的特性,所以异常只能在子线程中处理不能抛出到主线程里,但是 Spring实现的线程池可以返回一个异常信息对象

项目部署

编译打包jar/war

war

  • 部署为war必须的类,一般在创建项目时选war就会自动生成,选jar就要手动添加

    1
    2
    3
    4
    5
    6
    public class ServletInitializer extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
    return application.sources(DemoApplication.class);
    }
    }
  • maven: mvn war 即可 mvn package -DskipTests

  • gradle: gradle war 然后 gradle bootRepackage 即可

jar

  • 没有特殊的配置,打包即用
    • maven: mvn package 即可生成可执行的jar
    • gradle:gradle jar 然后 gradle bootRepackage 也生成可执行jar

构建docker镜像

Official Doc: spring boot docker

手动方式

  • 先构建得到war或jar,然后根据dockerfile构建一个镜像
    1
    2
    3
    FROM frolvlad/alpine-oraclejdk8:slim
    ADD weixin-1.0.0.war app.war
    ENTRYPOINT ["java","-jar","/app.war"]

gradle结合docker

热部署

参考博客: SpringBoot热部署