目录 start

目录 end |2018-07-21| 码云 | CSDN | OSChina


SpringBoot

一个简化Spring开发的框架,微服务SpringCloud的基础

思考

  • SpringBoot优缺点

    • 大大降低编程门槛, 但是, 将大量细节隐藏在默认配置中, 需要详细阅读文档和源码才能更好的玩转SpringBoot, 不然到处是坑
  • SpringBoot启动流程解析原理才是王道

  • Spring 是单例模式, 全部使用IOC容器进行管理, 那么怎么处理并发呢,

    • 答案是 ? 多线程 然后 ThreadLocal 分别存储了各自的数据, 所以才说, 不能在Controller层 放置属性, 使其具有状态, 从而导致并发问题
    • 那么WebSocket服务器, 处理并发会不会有并发问题?
  • 为什么说 Java 程序员到了必须掌握 Spring Boot 的时候?

Guide

参考教程

系列

开始使用

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

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

    ├── 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
  • 官方下载地址 所有版本

测试模块

  • [ ] 了解这些测试注解 的作用和使用场景
    // 依赖于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页面,模拟浏览器的动作,查看系统运行状态

配置文件

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

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

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

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

多种配置文件并切换

yml方式

  • 单文件配置文件 application.yml
      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中指明
      spring:
        profiles:
          active: dev或者是prod
    

    应用配置文件

    依赖于 org.springframework.boot:spring-boot-configuration-processor 配置对应的实体类

    @Data
    @Component
    @ConfigurationProperties(prefix = "graduate.main")
    public class MainConfig {
      private String delimiter;
    }
    

    应用配置类

    @Configuration
    @EnableConfigurationProperties(MainConfig.class)
    public class AutoCustomConfig {
    }
    

    application.yml

    graduate:
    main:
      delimiter: ,
    

Web模块

Lisener

ServletContextListener

    @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上传文件
  • 上传文件有大小限制,使用如下方法进行配置 参考博客
    @Bean
    public MultipartConfigElement multipartConfigElement() {
      MultipartConfigFactory factory = new MultipartConfigFactory();
      //单个文件最大
      factory.setMaxFileSize("80MB"); //KB,MB
      // 设置总上传数据总大小
      factory.setMaxRequestSize("102400KB");
      return factory.createMultipartConfig();
    }
    

    错误页面跳转配置

    @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);
          });
      }
    }
    

    跨域

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

@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的配置

参考博客

  • 签发证书:
    keytool -genkey -alias tomcat -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 3650
    
    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注解类里添加 ```java @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; }


- 另一种方式 [参考博客](http://www.cnblogs.com/xinzhao/p/4950689.html)
`方式不一样,没有成功`
```sh
    ############ 证书颁发机构
    # 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实现的线程池可以返回一个异常信息对象

项目部署

生成指定文件

war

  • 部署为war必须的类,一般在创建项目时选war就会自动生成,选jar就要手动添加
      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镜像

方便监控应用状态,cpu 内存 流量, 官方文档

手动方式

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

gradle结合docker

results matching ""

    No results matching ""