SpringBoot 笔记

栏目: Java · 发布时间: 7年前

内容简介:SpringBoot 笔记

SpringBoot 笔记

营销测试 工具 工程实现, 基于 SpringBoot , 码了一段时间, 整理一下笔记, 真的 特别好用!!! 最直观的感受有下面三方面:

  • 无 xml 配置!!!
  • 内嵌 tomcat
  • 组件选配

1. 创建工程

1.1 使用 IDEA 创建

个人推荐使用 IDEA 来创建, 省事. 不需要下载, 解压, 顺带还指定安装目录.

SpringBoot 笔记 SpringBoot 笔记 SpringBoot 笔记

1.2 官网创建工程

打开官网 http://start.spring.io/ , 填入 Group Artifact 等, 勾选依赖的组件, 点击 Generate Project , 下载 ZIP. 然后导入IDEA.

创建后的目录结构如下:

├── mvnw
├── mvnw.cmd
├── pom.xml
├── promoboot.iml
├── src
│   ├── main
│   │   ├── java
│   │   └── resources
│   └── test
│       └── java
└── target
    ├── classes
    │   ├── application.properties
    │   └── com
    ├── generated-sources
    │   └── annotations
    ├── generated-test-sources
    │   └── test-annotations
    └── test-classes
        └── com

2. 启动工程

在启动文件中, 添加个 Controller 并启动测试一下, 默认的 server.port=8080

@Controller
@SpringBootApplication
public class PromobootApplication {

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

    @RequestMapping("/")
    @ResponseBody
    String home() {
        return "Hello World!";
    }
}

SpringBoot 笔记

启动工程的方式有如下几个:

2.1 SpringBoot启动 — IDEA 启动

直接启动 main 函数

2.2 SpringBoot启动 — mvn 命令启动

执行下面命令, 直接启动:

mvn spring-boot:run

2.3 SpringBoot启动 — 打包部署启动

打包并部署放到生产环境

首先创建 Jar 包

mvn package

然后使用 java -jar 命令启动

java -jar target/promoboot-0.0.1-SNAPSHOT.jar

SpringBoot 笔记

2.4 SpringBoot 热部署

改完代码, 每次启动工程挺费时的, SpringBoot 支持热部署需要添加 spring-boot-devtools 依赖, 可以手动添加, 也可以在创建 SpringBoot 时勾选 DevTools, 如下图:

SpringBoot 笔记

下面说一下手工添加的方式:

  • 手动添加 devtools 依赖, 设置 optional = true
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional> 
</dependency>
  • 使用 mvn spring-boot:run 启动
mvn spring-boot:run

可以看到多了一条监听 class 变更的日志

18:26:43.631 [main] DEBUG org.springframework.boot.devtools.restart.ChangeableUrls - Matching URLs for reloading : [file:/Users/fish/AliDrive/git/springbootdemo/target/classes/]

此时修改代码, 就可以无脑看执行结果了!

另外, IDEA 设置一下字段编译, 如下图

SpringBoot 笔记

2.5 开启本地 Debug 端口

参考文档 Debug the application , 开启本地 Debug 端口使用如下方法:

mvn spring-boot:run -Drun.jvmArguments="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"

3. 配置文件读取与环境隔离

初始化的工程, 自带了 application.properties 配置文件.

3.1 使用 yaml 替换 properties

其实框架默认支持 Ruby on Rails 惯用的 yaml 格式配置文件, 非常建议大家使用 yaml 来替换掉 properties , 配置文件看起来短多了, 对比如下:

  • 使用 properties
server.port = 8080
server.context-path = '/boot'
  • 使用 yaml
server:
  port: 8080
  context-path: '/boot'

此外, yaml 语法还支持变量定义等, 详细用法可以查看文档 YAML Syntax

3.2 开发/测试/生产 环境配置隔离

对于程序员, 手动改配置是一项不能忍的工作, 好在 spingboot 完美的支持配置文件隔离. 操作如下:

新增 开发/测试/生产 配置文件:

SpringBoot 笔记

配置 application.properties 中的内容, 比如启用 dev 环境, 设置 active = dev, 就启用了 application-dev.yaml :

spring:
  profiles:
    active: dev

本地开发时, 使用 mvn spring-boot:run 启动的工程, 可以自动生效.

3.2 线上部署, 配置环境隔离

上面提到过 Jar 包的部署方式, 同一套代码部署到不同环境时, 不需要修改配置文件, 使用下面的命令来部署:

  • 将服务部署到生产环境(prod)
mvn install && java -jar target/promoboot-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod

3.4 读取配置文件中的值

类似 sofa 框架的 @AppConfig 注解, SpringBoot 在读取配置文件时, 关键词是

// 获取单个配置值
@Value("${xx.oo}")

// 自定义对象注入
@Component
@ConfigurationProperties

3.4.1 读取单个配置的值

application.yaml 配置如下:

params:
  env: stable

代码中使用如下方式获取:

@Value("${params.env}")
private String env;

3.4.2 自定义个对象进行注入

如果某一个类型的参数实在多, 使用上面的方式非常繁琐, SpringBoot 支持直接映射到对象中.

apple:
  size: 20
  color: red
  weight: 300

然后定义个 Apple 的类, 添加上 ComponentConfigurationProperties 注解.

@Component
@ConfigurationProperties(prefix = "apple")
public class Apple {

    private String name;

    private int size;

    private String color;

    private int weight;

    public String getName() {
        return name;
    }
    ......

最后, 引用方式如下:

@Autowired
private Apple apple;

这样 Apple 的配置就映射进来了, 当然你也可以在他的属性上添加 @NotEmpty 等注解. 比如在 color 属性上添加 @NotEmpty, 配置文件中置空, 系统自动编译会直接报错的:

***************************
APPLICATION FAILED TO START
***************************

Description:

Binding to target Apple{name='lol', size=20, cllor='', weight=300} failed:

    Property: apple.color
    Value:
    Reason: may not be empty

4. Controller

  • SpringMVC

SpringBoot 笔记

  • SpringBoot

SpringBoot 笔记

从上面两个图可见, 两个框架提供的功能是一样的, SpringBoot 更简单, 还挺好用:

@RestController = @Controller + @ResponseBody

@GetMapping(value="xx") = @RequestMapping(value = "xx", method = RequestMethod.GET)
@PostMapping(value="xx") = @RequestMapping(value = "xx", method = RequestMethod.POST)

5. 数据库操作 JPA

操作数据库, 常见的 JDBC, MyBatis等, 不再赘述. 项目中使用的是 JPA , 非常简洁.

5.1 什么是 JPA

JPA(Java Persistence API)是Sun官方提出的 Java 持久化规范, 它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系数据, 目的是整合现有的 ORM 技术.

5.2 工程配置

5.2.1 添加依赖

比如使用 mysql 数据库, 那么在 pom.xml 中添加 jpa mysql 依赖

<!--使用spring-jpa-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <!--mysql 依赖添加-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

5.2.2 数据库配置

编辑 application-dev.yaml 文件

spring:
# 数据库配置
  datasource:
    username: oooo
    password: xxxx
    url: jdbc:mysql://dev.lab.alipay.net:3306/promotion
    driver-class-name: com.mysql.jdbc.Driver
    # 配置 hibernate 属性
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

ddl-auto 是 hibernate 的配置属性, 对应的作用是:

create: 删表, 重新创建表(慎用)
update: 常用配置, ,第一次加载Hibernate时创建数据表, 以后加载HIbernate时只会根据model更新
validate: 验证数据库表结构

5.2.3 创建实体

比如创建一个 Robot 实体, 自定义一些属性:

@Entity
@Table(name = "robot")
public class RobotDO {

    @Id
    @GeneratedValue
    private long id;

    @Column(nullable = false)
    private String robotName;

    private String size;

    @Column(name = "robot_type")
    private String type;

    private Date gmtCreate;

    private Date gmtModified;

注解解释:

@Id:            主键
@GeneratedValue: 数据库表 primary key, 自增长

@Column(name=""): hibernate 自动根据属性名称创建数据库列名, 也可以手动定义列名

@Column(nullable = false): create table robot (robot_name varchar(255) not null,) .....

@Table: 数据库表名默认和类名一直, 使用该注解自定义

@CreationTimestamp: 自动填入 gmtCreate 时间

@UpdateTimestamp: 自动填入更新时间

5.2.4 重启工程, 生成数据表

启动 springboot 工程, 可以看到数据库中新增了表 robot

SpringBoot 笔记

5.2.5 测试代码

定义个接口, 继承自 JpaRepository :

public interface RobotDAO extends JpaRepository<RobotDO, Integer> {

}

查看父类源码, 自带了 CRUD, 直接写个 Controller 来测试一下 (测试代码比较偷懒, 没有写 Service, 直接注入 DAO, 不推荐):

@SpringBootApplication
@RestController
public class TestController {

    Logger logger = Logger.getLogger(this.getClass());

    @Autowired
    private Apple apple;

    @Autowired
    private RobotDAO robotDAO;

    @GetMapping(value = "/test")
    public Object testController() {
        logger.info("=====================Visiting  test controller======================");

        logger.info("测试插入:");
        RobotDO robotDO = new RobotDO();
        robotDO.setRobotName("Wall-E");
        robotDO.setSize("Huge");
        robotDO.setType("AI");
        robotDAO.save(robotDO);

        logger.info("测试查找:");
        logger.info(robotDAO.findAll());

        return apple;
    }

日志输出如下, 设置 show-sql: true 可以方便看出执行的具体 SQL:

2017-05-30 15:39:41.570  INFO 16254 --- [nio-9999-exec-1] troller$$EnhancerBySpringCGLIB$$efd51a80 : =====================Visiting  test controller======================
2017-05-30 15:39:41.570  INFO 16254 --- [nio-9999-exec-1] troller$$EnhancerBySpringCGLIB$$efd51a80 : 测试插入:
Hibernate: insert into robot (gmt_create, gmt_modified, robot_name, size, robot_type) values (?, ?, ?, ?, ?)
2017-05-30 15:39:41.585  INFO 16254 --- [nio-9999-exec-1] troller$$EnhancerBySpringCGLIB$$efd51a80 : 测试查找:
2017-05-30 15:39:41.588  INFO 16254 --- [nio-9999-exec-1] o.h.h.i.QueryTranslatorFactoryInitiator  : HHH000397: Using ASTQueryTranslatorFactory
Hibernate: select robotdo0_.id as id1_0_, robotdo0_.gmt_create as gmt_crea2_0_, robotdo0_.gmt_modified as gmt_modi3_0_, robotdo0_.robot_name as robot_na4_0_, robotdo0_.size as size5_0_, robotdo0_.robot_type as robot_ty6_0_ from robot robotdo0_
2017-05-30 15:39:41.598  INFO 16254 --- [nio-9999-exec-1] troller$$EnhancerBySpringCGLIB$$efd51a80 : [
RobotDO{id=1, robotName='Wall-E', size='Huge', type='AI', gmtCreate=2017-05-30 15:38:24.0, gmtModified=2017-05-30 15:38:24.0}, 
RobotDO{id=2, robotName='Wall-E', size='Huge', type='AI', gmtCreate=2017-05-30 15:38:55.0, gmtModified=2017-05-30 15:38:55.0}, 
RobotDO{id=3, robotName='Wall-E', size='Huge', type='AI', gmtCreate=Tue May 30 15:39:41 CST 2017, gmtModified=Tue May 30 15:39:41 CST 2017}
]

看一下数据库:

SpringBoot 笔记

5.2.5 事务操作

多表操作, 需要放在一个事务里, 在方法上面添加 @Transactional 即可.

6. AOP

面向切面编程, 是 spring 的一大特性, 举个 controller 切面例子, 看一下 springboot 的 aop 使用.

参考的是这个文档 Spring AOP Example Tutorial

6.1 AOP 依赖引入

<!--AOP依赖添加-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

6.2 AOP 实现

@Aspect
@Component
@Order(1)
public class ControllerAspect {
    private Logger logger = Logger.getLogger(this.getClass());

    @Pointcut("execution(public * com.alipay.liuqi.controller.TestController.testController())")
    public void webController() {

    }

    @Before(value = "webController()")
    public void beforeWebController() {
        logger.info("===BeforeWebController: start visiting===");
    }

    @After(value = "webController()")
    public void afterWebController() {
        logger.info("====AfterWebController: end visiting===");
    }

    @AfterThrowing(value = "webController()")
    public void afterThrowWebController() {
        logger.info("====AfterThrowWebController: throw exception ===");
    }

    @AfterReturning(value = "webController()")
    public void afterReturnWebControlelr() {
        logger.info("====AfterReturnWebControlelr: return normal ===");
    }

    @Around(value = "webController()")
    public void aroundWebController(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        logger.info("====AroundWebController: start around ===");
        proceedingJoinPoint.proceed();
        logger.info("====AroundWebController: end around ===");
    }
}

执行一下, 日志打印出来:

2017-05-30 17:12:21.183  INFO 16254 --- [nio-9999-exec-2] c.alipay.liuqi.aspect.ControllerAspect   : ====AroundWebController: start around ===
2017-05-30 17:12:21.184  INFO 16254 --- [nio-9999-exec-2] c.alipay.liuqi.aspect.ControllerAspect   : ===BeforeWebController: start visiting===
2017-05-30 17:12:21.189  INFO 16254 --- [nio-9999-exec-2] troller$$EnhancerBySpringCGLIB$$efd51a80 : I am controller
2017-05-30 17:12:21.194  INFO 16254 --- [nio-9999-exec-2] c.alipay.liuqi.aspect.ControllerAspect   : ====AroundWebController: end around ===
2017-05-30 17:12:21.194  INFO 16254 --- [nio-9999-exec-2] c.alipay.liuqi.aspect.ControllerAspect   : ====AfterWebController: end visiting===
2017-05-30 17:12:21.194  INFO 16254 --- [nio-9999-exec-2] c.alipay.liuqi.aspect.ControllerAspect   : ====AfterReturnWebControlelr: return normal ===

6.3 AOP 小结

其他说明

  1. Pointcut 支持正则表达式
  2. 除了 @Before 和 @After, 还有其他的注解, 说明如下:
@AfterReturning: 切面点正常执行后, 才执行 AfterReturning 注解下面代码

@AfterThrowing: 切面点抛出异常后, 执行 AfterThrowing 注解对应的代码

@Around: 可以同时在所拦截方法的前后, 执行一段逻辑, 比如可以统计一下方法执行的时间

切面小结:

  1. 定义切面点
  2. 实现切面点前后要做的事情
  3. 排好优先级

7. 其他

7.1 使用 LiveReload 热刷新

热部署提到了修改完代码, 不需要重启工程, 但是有时候前端页面还是需要刷新的, 查看热部署文档时, 看到了 LiveReload , 热刷新简直好用极了!!!

7.1.1 添加 devtools 依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional> <!-- 这个需要为 true 热部署才有效 -->
        </dependency>

7.1.2 设置 livereload 属性为 true

修改 application-dev.profiles :

# 配置热部署, 热刷新
spring:
  devtools:
    livereload:
      enabled: true

7.1.3 浏览器安装 livereload 插件

插件地址

启动工程后, 日志会显示 livereload 占用的端口:

2017-05-30 17:12:09.505  INFO 16254 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729

7.2 未提到的

健康性检查是工程非常重要的指标, 因为没怎么用到, 暂未提及.

  • 接口测试
  • 健康性检查(Spring Boot Actuator)

参考文档

  1. SpringBoot 官方文档

  2. SpringBoot进阶之Web进阶–视频教程

  3. Spring Boot中使用Spring-data-jpa让数据访问更简单、更优雅

  4. [stackoverflow–JPA 时间设置]((https://stackoverflow.com/questions/221611/creation-timestamp-and-last-update-timestamp-with-hibernate-and-mysql)

  5. https://github.com/spring-projects/spring-boot


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

智能革命

智能革命

李彦宏 等 / 中信出版集团 / 2017-5-1 / 68.00元

人类历史上的历次技术革命,都带来了人类感知和认知能力的不断提升,从而使人类知道更多,做到更多,体验更多。以此为标准,李彦宏在本书中将人工智能定义为堪比任何一次技术革命的伟大变革,并且明确提出,在技术与人的关系上,智能革命不同于前几次技术革命,不是人去适应机器,而是机器主动来学习和适应人类,并同人类一起学习和创新这个世界。“人工智能”正式写入2017年政府工作报告,折射出未来人工智能产业在我国经济发......一起来看看 《智能革命》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

html转js在线工具
html转js在线工具

html转js在线工具