内容简介:SpringBoot 笔记
营销测试 工具 工程实现, 基于 SpringBoot
, 码了一段时间, 整理一下笔记, 真的 特别好用!!!
最直观的感受有下面三方面:
- 无 xml 配置!!!
- 内嵌 tomcat
- 组件选配
1. 创建工程
1.1 使用 IDEA 创建
个人推荐使用 IDEA 来创建, 省事. 不需要下载, 解压, 顺带还指定安装目录.
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!"; } }
启动工程的方式有如下几个:
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
2.4 SpringBoot 热部署
改完代码, 每次启动工程挺费时的, SpringBoot 支持热部署需要添加 spring-boot-devtools
依赖, 可以手动添加, 也可以在创建 SpringBoot 时勾选 DevTools, 如下图:
下面说一下手工添加的方式:
- 手动添加 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 设置一下字段编译, 如下图
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 完美的支持配置文件隔离. 操作如下:
新增 开发/测试/生产 配置文件:
配置 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 的类, 添加上 Component
和 ConfigurationProperties
注解.
@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 更简单, 还挺好用:
@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
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} ]
看一下数据库:
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 小结
其他说明
- Pointcut 支持正则表达式
- 除了 @Before 和 @After, 还有其他的注解, 说明如下:
@AfterReturning: 切面点正常执行后, 才执行 AfterReturning 注解下面代码 @AfterThrowing: 切面点抛出异常后, 执行 AfterThrowing 注解对应的代码 @Around: 可以同时在所拦截方法的前后, 执行一段逻辑, 比如可以统计一下方法执行的时间
切面小结:
- 定义切面点
- 实现切面点前后要做的事情
- 排好优先级
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)
参考文档
-
[stackoverflow–JPA 时间设置]((https://stackoverflow.com/questions/221611/creation-timestamp-and-last-update-timestamp-with-hibernate-and-mysql)
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 【每日笔记】【Go学习笔记】2019-01-04 Codis笔记
- 【每日笔记】【Go学习笔记】2019-01-02 Codis笔记
- 【每日笔记】【Go学习笔记】2019-01-07 Codis笔记
- vue笔记3,计算笔记
- Mysql Java 驱动代码阅读笔记及 JDBC 规范笔记
- 【每日笔记】【Go学习笔记】2019-01-16 go网络编程
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
图片转BASE64编码
在线图片转Base64编码工具
html转js在线工具
html转js在线工具