内容简介: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网络编程
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web Caching
Duane Wessels / O'Reilly Media, Inc. / 2001-6 / 39.95美元
On the World Wide Web, speed and efficiency are vital. Users have little patience for slow web pages, while network administrators want to make the most of their available bandwidth. A properly design......一起来看看 《Web Caching》 这本书的介绍吧!