Spring Boot 总结

作者: happeace | 来源:发表于2016-11-16 11:56 被阅读1657次

    Spring Boot 其实是对Spring家族和一些常用组件的一个比较好的组合打包的方式,并将很多通用的配置都内置了,如果不需要太多个性化配置,采用很少的配置就可以跑起来, 使得使用起来很方便,比如:

    • 简化配置
    • 结合spring data jpa 数据库操作简便
    • RestController 返回结果自动转换 json
    • 直接运行jar的方式(内嵌tomcat等容器) 部署方便,和docker很容易结合
    • ……

    开始

    参考 quick start
    pom.xml里配置parent 和核心的几个依赖:

     <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.2.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    

    实际上spring-boot-starter-web只是一个pom文件, 里面预置好了关键的依赖, 如spring context、spring mvc、log等:

    spring-boot-starter-web包含的依赖

    配置

    官网资料 Properties & configuration

    属性获取

    默认的配置文件是application.propertiesapplication.yml

    @Value

    @Value("${sys1.url}") String url;

    Environment

     @Autowired private Environment env;    
     String url = env.getProperty("sys1.url")
    

    ConfigurationProperties

    @ConfigurationProperties(prefix = "sys1")
    class Config {
        private String url;
        // url 的 set get 方法 ...
    }
    

    ConfigurationProperties的prefix指定在application.properties中配置项名字的前缀如: sys1.url, Config类中的属性名url和配置文件中的后部分一致, 实现自动注入。
    除了prefix,ConfigurationProperties也可以有locations指定默认配置文件外的其他配置文件

    application.properties有些配置项会被spring boot读取,如:

    server.port = 8080
    server.session-timeout = 7200
    # log
    logging.file= application.log
    logging.level.org.springframework .security.cas = INFO
    logging.level.com.my.cloud.vodlivemgr.* = DEBUG
    
    # db
    spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mydb?useUnicode=true&characterEncoding=utf8&autoReconnect=true&autoReconnectForPools=true
    spring.datasource.username=test
    spring.datasource.password=test
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    

    多环境

    测试、开发和线上的配置分开,并可以在运行时指定配置, 采用profiles的方式。
    启动时可指定profile: java -jar -Dspring.profiles.active=production demo.jar

    properties文件配置

    使用properties配置的, 公共配置放application.properties, 环境配置放 application-env.properties,如application-dev.properties, application.properties可指定默认激活的环境:spring.profiles.active= dev, 使用application-dev.properties中的配置

    yaml文件配置

    可将所有环境配置放application.yml中, 通过 ---分隔每个profile。

    # 公共配置
    server:
      tomcat:
        uri-encoding: utf-8
        max-threads: 1024
        access_log_enabled: true
      session:
        timeout: 60
    cas:
      casServerLoginUrl: https://sso.mysit/login
      casServerUrlPrefix: https://sso.mysit/cas
    
    # 默认激活的环境配置
    spring:
      profiles.active: dev
    
    ---
    # 线上环境配置
    spring:
      profiles: online
    server:
      port: 80
    logging:
      path: /home/logs/sys1/
      level: info
    cas:
      serviceUrl: http://site.online/
    
    ---
    #测试环境配置
    spring:
      profiles: test
    server:
      port: 8080
    logging:
      file: sys1.log
      level: debug
    cas:
      serviceUrl: http://site.test/
    
    ---
    #开发环境配置
    spring:
      profiles: dev
    server:
      port: 8080
    logging:
      file: sys1.log
      level: debug
    cas:
      serviceUrl: http://site.dev/
    

    日志

    spring boot默认采用logback, 可在application.properties里配置。 启动时还可以指定日志级别 java -jar myapp.jar --debug

    静态页面

    静态资源如html js image等放到(或打包时发布到)这些目录:
    /resources 、 /META-INF/resources、 /public 、 /static
    如:习惯放在webapp下的,在pom.xml中配置发布到/public下

    <build>
        <resources>
            <resource>
                <directory>src/main/webapp</directory>
                <targetPath>/public</targetPath>
            </resource>
         </resources>
    </build>
    

    前端访问这些静态资源时 路径当作是在/下, 如/public/index.html,访问时用/index.html。
    stackoverflow:Spring Boot not serving static content

    数据库

    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
       <groupId>mysql</groupId>
       <artifactId>mysql-connector-java</artifactId>
       <version>5.1.15</version>
    </dependency>
    

    可在application.properties里配置:

    # db
    spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mydb?useUnicode=true&characterEncoding=utf8
    spring.datasource.username=test
    spring.datasource.password=test
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    spring.datasource.validation-query=select 1
    spring.datasource.test-while-idle=true
    spring.datasource.time-between-eviction-runs-millis= 3600000
    spring.datasource.max-active= 10
    spring.datasource.min-idle= 1
    spring.datasource.max-idle= 5
    spring.jpa.properties.hibernate.hbm2ddl.auto=update
    spring.datasource.jdbc-interceptors=ConnectionState;SlowQueryReport(threshold=1000)
    

    pom引用了spring-boot-starter-data-jpa,则会自动使用tomcat-jdbc连接池
    Tomcat 的 JDBC 连接池
    最后一句配置SlowQueryReport可在数据库查询超过1000毫秒时打印慢查日志。

    spring.datasource.test-while-idle=true spring.datasource.time-between-eviction-runs-millis= 3600000 在空闲时 每个1小时 访问一下数据库,避免连接池中的连接因超时而失效, 见 stackoverflow:Spring Boot JPA - configuring auto reconnect

    Spring Data JPA

    spring data jpa 是基于Hibernate的, 通过Entity可自动创建数据表,甚至关联表(如User 和 Role的关联表user_role)

    @Entity
    public class User {
        @Id
        @GeneratedValue
        private int id;
        @Column(unique = true, nullable = false)
        private String loginName;
    
        @ManyToMany(fetch = FetchType.EAGER)
        @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"),
                inverseJoinColumns = @JoinColumn(name = "role_id"))
        private Set<Role> roles = new HashSet<Role>();
        // get set 方法省略
    }
    

    Dao层只要继承JpaRepository 就已经有了基本的增删查改功能, 需要定制SQL的可以通过@Query注解完成,见 Using @Query

    public interface UserDao extends JpaRepository <User, Integer>{
        User findByLoginName(String loginName);
        void deleteByLoginName(String loginname);
    }
    
    public interface RoleDao extends JpaRepository<Role, Integer> {
        Role findByName(String loginName);
        @Query("SELECT r FROM Role r WHERE r.id IN (?1)")
        List<Role> findRolesByIds(List<Integer> ids);
    }
    

    并可在其他类中直接自动注入,如@Autowired private UserDao userDao;, 接口是不能实例化的, 这里应该是框架会根据接口定义自动创建一个代理类, 注入的其实是代理类。

    Spring MVC

    在以往后端返回数据时, 需要自己采用json库,将pojo转换为json字符串输出到前端, spring boot 默认给做了这个事情:

    @RestController
    @RequestMapping("admin")
    public class AdminController {
        Logger log = LoggerFactory.getLogger(AdminController.class);
        @Autowired private UserDao userDao;
        
        @RequestMapping(value = "users", method = RequestMethod.GET)
        public List<User> getUsers() {
            return new userDao.findAll();
        }
    }
    

    访问 /admin/users 直接返回:

    [
        {
            "id": 19,
            "loginName": "123456@qq.com",
            "roles": [ 
                { "id": 3, "name": "ADMIN" },
                { "id": 2, "name": "OPS" }
            ]
        }
    ]
    

    测试

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

    spring-boot-starter-test 里引入了junit等。
    测试类上增加注解:

    @RunWith(SpringJUnit4ClassRunner.class)
    @WebAppConfiguration
    @SpringApplicationConfiguration(classes = App.class)
    

    然后就可以使用junit的 @Before @After 和 @Test 等注解来写测试方法了。

    热部署

    在开发时,修改代码,IDE触发自动编译后, 应该是Spring boot的buildspring-boot-maven-plugin自动触发了自动reload类。
    目前可能是我IDE设置的问题, 每次修改后还得右键Recompile一下。

    也有说使用spring-boot-devtools等依赖来完成的。
    官网资料 using-boot-hot-swapping

    Spring Security 和 CAS 集成

    示例 github: demo-spring-security-cas

    官网说明:spring io: CAS Authentication, 说明中是基于xml配置的, 要转换为Spring boot的注解配置。

    相关文章

      网友评论

        本文标题:Spring Boot 总结

        本文链接:https://www.haomeiwen.com/subject/mlcrpttx.html