SpringBoot导读
SpringBoot
一、导读
1、开发工具及技术栈
- JDK:jdk1.8.0_191
- 开发工具:IntelliJIDEA 2020.3.2
- SpringBoot:
- 简化Spring的开发
- 需要一定的java基础
- 有Spring、SpringMVC、Mybatis框架知识
- Maven
- Magic-Api
- JWT
二、SpringBoot
1、概述
SpringBoot 提供了一种快速使用Spring的方式,基于约定优于配置的思想,可以让开发人员不必在配置和逻辑业务之间进行思维的切换,全身心投入到逻辑业务的代码编写中,从而大打提高开发的效率。一定程度上缩短了开发周期。
2、功能
自动配置
SpringBoot是一个运行时的过程,就是程序启动的时候,考虑众多因素,才会决定Spring配置应该用哪个,不该用哪个,该过程时自动的。
起步依赖
是一个Maven模型,根据POM定义了其他库的依赖传递,简单说就是把具备某些功能的坐标打包到一起,并提供一些默认的功能。
辅助功能
比如嵌入式服务器、安全、指标、健康监测、外部配置等。
- SpringBoot提供了一种快速开发Spring项目的方式,而不是Spring功能上的增强。
3、快速入门
3.1、pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.tjhis</groupId>
<artifactId>hisApi</artifactId>
<version>1.0.2</version>
<name>hisApi</name>
<description>hisApi</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- 引入magic-api-spring-boot-starter依赖。-->
<dependency>
<groupId>org.ssssssss</groupId>
<artifactId>magic-api-spring-boot-starter</artifactId>
<version>2.0.2</version>
</dependency>
<!-- 定时任务 -->
<dependency>
<groupId>org.ssssssss</groupId>
<artifactId>magic-api-plugin-task</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Oracle驱动 -->
<!-- <dependency>-->
<!-- <groupId>com.oracle.database.jdbc</groupId>-->
<!-- <artifactId>ojdbc8</artifactId>-->
<!-- <scope>runtime</scope>-->
<!-- </dependency>-->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.4</version>
</dependency>
<dependency>
<groupId>com.oracle.database.nls</groupId>
<artifactId>orai18n</artifactId>
<version>19.7.0.0</version>
</dependency>
<!-- 日志监控,Druid 用 -->
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- Druid https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- properti.yml的配置文件处理器,写yml文件时会有提示 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok项目是一个java库,它可以自动插入到编辑器和构建工具中,增强java的性能。
不需要再写getter、setter或equals方法,只要有一个注解,你的类就有一个功能齐全的构建器、自动记录变量等等。 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- JWT -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
<!-- hutool -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.10</version>
</dependency>
<!-- bouncycastle SM2 加密 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
<version>1.69</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
-
增加启动引导类
package cn.tjhis.api; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class ApiApplication { public static void main(String[] args) { SpringApplication.run(ApiApplication.class, args); } }
3.2、配置文件
## 生产环境
server:
port: 9908
# 配置静态资源启用 gzip 压缩
compression:
enabled: true
min-response-size: 128
# 配置主数据源
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
datasource:
driver-class-name: oracle.jdbc.OracleDriver #oracle.jdbc.driver.OracleDriver
username: system
password: manager
#url: jdbc:oracle:thin:@192.168.11.10:1521/orcl
url: jdbc:wrap-jdbc:filters=encoding:jdbc:oracle:thin:@//localhost:1521/orcl
type: com.alibaba.druid.pool.DruidDataSource
#Spring Boot 默认是不注入这些属性值的,需要自己绑定
#druid 数据源专有配置 ,必须导入 druid-spring : 1.1.10 才能配置以下参数
druid:
# 处理Oracle的英文字符集乱码的问题,中文字符集屏蔽该行
#connection-properties: serverEncoding=ISO-8859-1;clientEncoding=GBK
initialSize: 5
minIdle: 5
maxActive: 20
# 配置获取连接等待超时的时间
maxWait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
# 打开PSCache,并且指定每个连接上PSCache的大小
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall,log4j2
# StatViewServlet配置 sql监控
stat-view-servlet:
enabled: true
url-pattern: "/druid/*"
reset-enable: false
login-username: admin
login-password: Admin@123
#允许那些ip
allow: 127.0.0.1,192.168.120.93
#禁止那些ip
deny: 192.168.120.93
# WebStatFilter配置 web-jdbc关联监控
web-stat-filter:
enabled: true
url-pattern: "/*"
exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
filter:
stat:
enabled: true
merge-sql: true
# data:
# 配置mongo数据源
# mongodb:
# host: localhost
# port: 27017
# database: magicapi
# username: magicapi
# password: 123456
# 配置redis数据源
# redis:
# host: localhost
# port: 6379
# database: 4
# timeout: 5000
magic-api:
web: /magic/web
security:
username: admin # 登录用户名
password: Admin@123 # 登录密码
resource:
# type: database # 配置接口存储方式,这里选择存在数据库中
# table-name: magic_api_file # 数据库表名
prefix: /api # key前缀
location: d:/magic-api
# 配置打印SQL
show-sql: true
date-pattern: yyyy-MM-dd HH:mm:ss
page:
size: size # 页大小的参数名称
page: page # 页码的参数名称
default-page: 1 # 未传页码时的默认首页
default-size: 10 # 未传页大小时的默认页大小
prefix: api # 接口前缀,可以不配置
sql-column-case: camel # 启用驼峰命名转换
backup: #备份相关配置
enable: false #是否启用
max-history: -1 #备份保留天数,-1为永久保留
datasource: magic #指定数据源(单数据源时无需配置,多数据源时默认使用主数据源,如果存在其他数据源中需要指定。)
table-name: magic_api_backup #使用数据库存储备份时的表名
response-code:
success: 200 #执行成功的code值
invalid: 400 #参数验证未通过的code值
exception: 500 #执行出现异常的code值
response: |- # 配置JSON格式,格式为magic-script中的表达式
{
code: code,
message: message,
data,
timestamp,
requestTime,
executeTime,
}
throw-exception: true
task:
thread-name-prefix: magic-task- #线程池名字前缀
pool:
size: 8 #线程池大小,默认值为CPU核心数
shutdown:
awaitTermination: false #关闭时是否等待任务执行完毕,默认为false
awaitTerminationPeriod: 10s # 关闭时最多等待任务执行完毕的时间
# 更多配置 https://ssssssss.org/magic-api/config/
person:
name: 张三
address:
- 北京
- 丰台
- 富丰桥
age: 16
-
创建Controller
-
小结
- 在创建项目时,默认使用jar打包方式,因为用main函数启动的。
- 启动引导类是项目的入口。
4、Magic-api
4.1、简介
magic-api 是一个基于Java的接口快速开发框架,编写接口将通过magic-api提供的UI界面完成,自动映射为HTTP接口,无需定义Controller、Service、Dao、Mapper、XML、VO等Java对象即可完成常见的HTTP API接口开发。
之前我们开发一个接口,至少需要Controller,Service,Dao,Mapper文件,还需要各种配置,搭建启动springboot项目,发布完成,接口才能访问,接口才算完成。
而magic要做的就是通过UI界面动态的配置一下接口路径,出入参,点击保存,接口发布完成,即可访问,不需要编写代码,只需要简单配置,还支持事物,分页,http请求等数据库操作,有点类似于现在的低代码平台特性
支持MySQL、MariaDB、Oracle、DB2、PostgreSQL、SQLServer 等支持jdbc规范的数据库
支持非关系型数据库Redis、Mongodb
支持集群部署、接口自动同步。
支持分页查询以及自定义分页查询
支持多数据源配置,支持在线配置数据源
支持SQL缓存,以及自定义SQL缓存
支持自定义JSON结果、自定义分页结果
支持对接口权限配置、拦截器等功能
支持运行时动态修改数据源
支持Swagger接口文档生成
基于magic-script脚本引擎,动态编译,无需重启,实时发布
支持Linq式查询,关联、转换更简单
支持数据库事务、SQL支持拼接,占位符,判断等语法
支持文件上传、下载、输出图片
支持脚本历史版本对比与恢复
支持脚本代码自动提示、参数提示、悬浮提示、错误提示
支持导入Spring中的Bean、Java中的类
支持在线调试
支持自定义工具类、自定义模块包、自定义类型扩展、自定义方言、自定义列名转换等自定义操作
4.2、Magic-api 增删改查
- Oracle的表名必须用双引号,才能好使
// 新增
return db.table('test_data').insert({ id : 4, name : 'admin'})
return db.table('test_data').primary('id').save({ id : 4, name : 'admin'})
return db.table(\'user\').insert(body);
// oracle只有这种方法好使,成功之后返回rowid
var sql = """ insert into SCOTT.DEPT (DEPTNO,DNAME,LOC) values (#{DEPTNO},#{DNAME},#{LOC})"""
return db.insert(sql,body)
// 表名必须用双引号,才能好使,实际上不是,在这种状态不能开启驼峰sql-column-case ,如果需要驼峰,可以用db.camel()
return db.table("SCOTT.DEPT").insert(body)
// 更新
return db.table('test_data').primary('id').update({ id: 4, name : '张三峰'})
return db.update(\'update user set userName=\‘李四\’ where id=#{id}\')
// 删除
return db.table('test_data').primary('id').where().eq('id',4).delete()
return db.update(\'delete from user where id=#{id}\')
// 查询单条:路径变量从path对象中获取
return db.table(\'user\')
.where()
.eq(\'id\',path.id)
.selectOne();
return db.selectValue('select username from user where id = #{id}') return db.camel().selectOne('select * from user where id = #{id} ')
return db.selectInt('select count(*) from user')
// 查询所有
var sql = """
select dept_code,dept_name from dept_dict
"""
return db.camel().select(sql)
return db.camel().select('select * from user')
return db.camel().table("dept_dict").select()
// 分页 ,由于已经在application.yml中配置好了分页参数,可直接使用,下面第7项中有更详细的分页
return db.camel().table(\'user\').page();
return db.camel().page(sql);
// 从第11行开始取10行
return db.camel().table("dept_dict").page(10,11)
// 动态拼接
return db.camel().select("select * from sys_user ?{id,where id = #{id}}"); // 当id有值时,生成SQL:select * from sys_user where id = ?`,
// 当id无值时,生成SQL:select * from sys_user
return db.select("select * from sys_user ?{id!=null&&id.length() > 3,where id = #{id}}");
// 当id!=null&&id.length() > 3判断为true时,生成SQL:`select * from sys_user where id = ?
// 当判断为false时,生成SQL:select * from sys_user
// 模糊查询
return db
.camel()
.table("dept_dict")
.columns('dept_code','dept_name')
.where()
.like('dept_code','01%')
.like('dept_name','%疗区')
.page()
4.3、参数获取
-
### 这样的`URL`参数`magic-api` 会自动将`name`和`age`映射为同名变量。 GET http://localhost:9999/xxx/xxx?name=abc&age=49
-
Post也会映射为同名参数
-
POST请求:使用body对象可以直接获取请求body中的参数,例如
{ "name": "magic-api", "version": "9.9.9" } ## 如要获取name属性 则可通过 body.name 来获取
-
Path参数获取:路径变量从path对象中获取,GET请求,请求路径为/detail/
-
如要获取heade中的
token
可以通过header.token
来获取
4.4、校验
- assert在 2.0 已经被弃用
//import assert; //导入断言模块
// 验证不通过时,会终止运行
//assert.notEmpty(body.name,400,'名称不能为空!');
//assert.notEmpty(body.firstLetter,400,'首字母不能为空!');
//return db.table('pms_brand').insert(body);
if (pageSize==null || pageSize==0){
pageSize=10
}
if (pageIndex==null || pageIndex==0){
exit 400, '页码不能为空!';
}
// 类型转换
pageSize= pageSize::int
pageIndex= pageIndex::int
var sql = """
select dept_code,dept_name from dept_dict
"""
return db.page(sql,pageSize,pageSize * (pageIndex - 1))
4.7、切换数据源
// 从数据源key定义为slave的库中查询
return db.slave.select("""
select * from sys_user
""")
4.8、事物
// 自动事务
var val = db.transaction(()=>{
var v1 = db.update('...');
var v2 = db.update('....');
return v2;
});
return val;
// 手动事务
var tx = db.transaction(); //开启事务
try{
var value = db.update('...');
tx.commit(); // 提交事务
return value;
}catch(e){
tx.rollback(); // 回滚事务
}
4.9、结果转换
var list = db.table('comm.dept_dict').select();
return list.map((item)=>{
code : item.deptCode,
name : item.deptName,
showStatus : item.clinicAttr==0? '临床' : '其它'
});
4.10、java访问magic
-
配置文件中的magic的配置不要加prefix,否则在java无总是报
找不到路径
-
建议方法用
execute
,不要用call
execute
内部调用接口不包含code以及message信息,同时也不走拦截器。call
内部调用接口包含code以及message信息,同时也不走拦截器。
-
代码
@RestController public class LoginController { private final MagicAPIService service; private static final Logger logger = LoggerFactory.getLogger(CustomRequestInterceptor.class); public LoginController(MagicAPIService service) { this.service = service; } @GetMapping("/login") public Object login(String userName, String password) { Map<String, Object> params = new HashMap<>(); // 注入变量信息 params.put("userName", userName); // 内部调用接口不包含code以及message信息,同时也不走拦截器。 Object value = service.call("GET", "/comm/getUserByUserName", params); logger.info(value.toString()); return null; } }
4.11、magic访问java
import cn.tjhis.hisapi.config.JwtConfig;
var jwt = JwtConfig.parse(header.token)
return jwt.payloads.id;
5、properties.yml
-
优先级:properties.properties > properties.yml > properties.yaml
-
获取值
-
@Value
@RestController public class TestController { @Value("${spring.jackson.date-format}") private String dataFormat; @GetMapping("/test") public String getTest(){ return "Hello,王红晓," + dataFormat; } }
-
-
Environment
@RestController public class TestController { // 不建议使用Autowired注解,而是用构造的方法注入 private final Environment env; public TestController(Environment env) { this.env = env; } @GetMapping("/test") public String getTest() { return "Hello,王红晓," + env.getProperty("spring.jackson.date-format"); } }
-
@ConfigurationProperties
person: name: 张三 age: 18 address: - 北京 - 丰台 - 富丰桥
// 定义映射的实体类
package cn.tjhis.hisapi.entity;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "person")
@Data
public class Person {
private String name;
private int age;
private String[] address;
}
// 使用
import cn.tjhis.hisapi.entity.Person;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
private final Environment env;
private final Person person;
public TestController(Environment env, Person person) {
this.env = env;
this.person = person;
}
@GetMapping("/test")
public String getTest() {
return "Hello,王红晓," + person;
}
}
6、profile
-
激活
spring: profiles: active: test
-
active对应的配置文件为:application-XXX.yml,其中XXX即可为active的值
-
文件名
- application-test.yml:测试环境
- application-dev.yml:开发环境
- application-pro.yml:生产环境
-
虚拟机启动方式:
- 启动配置里面VM加:
-Dspring.profiles.active=pro
- 启动配置里面VM加:
-
jar包启动方式
- 在jar包的cmd命令行输入
java -jar ./hisApi-1.0.1.jar --spring.profiles.active=test
- 直接拷贝个文件和jar包平级
application.yml
,会优先启用该配置文件,其他配置也会被加载,但是会被当前的文件覆盖,如果放到config文件中,优先级会更高。运行命令:java -jar ./hisApi-1.0.1.jar
- 在jar包的cmd命令行输入
7、druid
- 访问:http://localhost:9908/druid/login.html
- 不能用ip访问的时候,可以修改配置
8、idea快捷键
一、常用快捷键
Ctrl + F12
弹出当前文件结构层(类的方法属性等),可以在弹出的层上直接输入,进行筛选
Ctrl + 左键单击 在打开的文件标题上,弹出该文件路径
Ctrl + N
根据输入的 类名 查找类文件
Ctrl + D 复制光标所在行 或 复制选择内容,并把复制内容插入光标位置下面
Ctrl + P
方法参数提示显示
Ctrl + Alt + O 优化导入的类,可以对当前文件和整个包目录使用
Alt + Insert 代码自动生成,如生成对象的 set / get 方法,构造函数,toString() 等
Shift + F6 对文件 / 文件夹 重命名
Ctrl + Shift + Enter 自动结束代码,行末自动添加分号
Ctrl + B 找变量、方法、类等的来源或者使用过的地方
Ctrl + Alt + B 在某个调用的方法名上使用会跳到具体的实现处,可以跳过接口
Ctrl + Q 光标所在的变量 / 类名 / 方法名等上面(也可以在提示补充的时候按),显示文档内容
Ctrl + Alt + T
对选中的代码弹出环绕选项弹出层(try,if等语句包裹)
Ctrl + Alt + L
格式化代码,可以对当前文件和整个包目录使用
Ctrl + Alt + 左方向键 退回到上一个操作的地方
Ctrl + Alt + 右方向键 前进到上一个操作的地方
Ctrl + Shift + J 自动将下一行合并到当前行末尾
Alt + F8 在 Debug 的状态下,选中对象,弹出可输入计算表达式调试框,查看该输入内容的调试结果
连按两次Shift 弹出 Search Everywhere 弹出层Alt + F7 查找光标所在的方法 / 变量 / 类被调用的地方
Ctrl + Alt + F7 显示使用的地方。寻找被该类或是变量被调用的地方,用弹出框的方式找出来
Ctrl + F
在当前文件进行文本查找
Ctrl + Shift + F
根据输入内容查找整个项目 或 指定目录内文件Ctrl + R 在当前文件进行文本替换
Ctrl + Shift + R 根据输入内容替换对应内容,范围为整个项目 或 指定目录内文件Ctrl + H 显示当前类的层次结构
Ctrl + Alt + H 调用层次
Ctrl + Shift + H 显示方法层次结构Ctrl + W 递进式选择代码块。可选中光标所在的单词或段落,连续按会在原有选中的基础上再扩展选中范围
Ctrl + Shift + W 递进式取消选择代码块。可选中光标所在的单词或段落,连续按会在原有选中的基础上再扩展取消选中范围Ctrl + [ 移动光标到当前所在代码的花括号开始位置
Ctrl + ] 移动光标到当前所在代码的花括号结束位置
Ctrl + Shift + [ 选中从光标所在位置到它的顶部中括号位置
Ctrl + Shift + ] 选中从光标所在位置到它的底部中括号位置Ctrl + O 选择可重写的方法
Ctrl + I 选择可实现的方法
Ctrl + Y 删除光标所在行 或 删除选中的行
Ctrl + X 剪切光标所在行 或 剪切选择内容
Ctrl + G 在当前文件跳转到指定行处
Ctrl + Q 光标所在的变量 / 类名 / 方法名等上面(也可以在提示补充的时候按),显示文档内容
Ctrl + U 前往当前光标所在的方法的父类的方法 / 接口定义
Ctrl + End 跳到文件尾
Ctrl + Home 跳到文件头Alt + ` 显示版本控制常用操作菜单弹出层
Alt + Enter 根据光标所在问题,提供快速修复选择,光标放在的位置不同提示的结果也不同Shift + ESC 隐藏当前 或 最后一个激活的工具窗口
Shift + End 选中光标到当前行尾位置
Shift + Home 选中光标到当前行头位置
Shift + Enter 开始新一行。光标所在行下空出一行,光标定位到新行位置
Shift + 左键单击 在打开的文件名上按此快捷键,可以关闭当前打开文件Ctrl + Alt + I 光标所在行 或 选中部分进行自动代码缩进,有点类似格式化
Ctrl + Alt + Space 类名自动完成Ctrl + Shift + N 通过文件名定位 / 打开文件 / 目录,打开目录需要在输入的内容后面多加一个正斜杠
Ctrl + Shift + U 对选中的代码进行大 / 小写轮流转换
Ctrl + Shift + / 代码块注释
Ctrl + Shift + Backspace 退回到上次修改的地方
Ctrl + Shift + F12 编辑器最大化
Ctrl + Shift + 左键单击 把光标放在某个类变量上,按此快捷键可以直接定位到该类中二、Ctrl相关
Ctrl + F
在当前文件进行文本查找 (必备)
Ctrl + R 在当前文件进行文本替换 (必备)
Ctrl + Z 撤销 (必备)
Ctrl + Y 删除光标所在行 或 删除选中的行 (必备)
Ctrl + X 剪切光标所在行 或 剪切选择内容
Ctrl + C 复制光标所在行 或 复制选择内容
Ctrl + D 复制光标所在行 或 复制选择内容,并把复制内容插入光标位置下面 (必备)
Ctrl + W 递进式选择代码块。可选中光标所在的单词或段落,连续按会在原有选中的基础上再扩展选中范围 (必备)
Ctrl + E 显示最近打开的文件记录列表
Ctrl + N
根据输入的 类名 查找类文件
Ctrl + G 在当前文件跳转到指定行处
Ctrl + J 插入自定义动态代码模板
Ctrl + P 方法参数提示显示
Ctrl + Q 光标所在的变量 / 类名 / 方法名等上面(也可以在提示补充的时候按),显示文档内容
Ctrl + U 前往当前光标所在的方法的父类的方法 / 接口定义
Ctrl + B 进入光标所在的方法/变量的接口或是定义处,等效于 Ctrl + 左键单击
Ctrl + K 版本控制提交项目,需要此项目有加入到版本控制才可用
Ctrl + T 版本控制更新项目,需要此项目有加入到版本控制才可用
Ctrl + H 显示当前类的层次结构
Ctrl + O 选择可重写的方法
Ctrl + I 选择可继承的方法
Ctrl + + 展开代码
Ctrl + - 折叠代码
Ctrl + / 注释光标所在行代码,会根据当前不同文件类型使用不同的注释符号 (必备)
Ctrl + [ 移动光标到当前所在代码的花括号开始位置
Ctrl + ] 移动光标到当前所在代码的花括号结束位置
Ctrl + F1 在光标所在的错误代码处显示错误信息
Ctrl + F3 调转到所选中的词的下一个引用位置
Ctrl + F4 关闭当前编辑文件
Ctrl + F8 在 Debug 模式下,设置光标当前行为断点,如果当前已经是断点则去掉断点
Ctrl + F9 执行 Make Project 操作
Ctrl + F11 选中文件 / 文件夹,使用助记符设定 / 取消书签
Ctrl + F12
弹出当前文件结构层,可以在弹出的层上直接输入,进行筛选
Ctrl + Tab 编辑窗口切换,如果在切换的过程又加按上delete,则是关闭对应选中的窗口
Ctrl + Enter 智能分隔行
Ctrl + End 跳到文件尾
Ctrl + Home 跳到文件头
Ctrl + Space 基础代码补全,默认在 Windows 系统上被输入法占用,需要进行修改,建议修改为 ALT+/(必备)
Ctrl + Delete 删除光标后面的单词或是中文句
Ctrl + BackSpace 删除光标前面的单词或是中文句
Ctrl + 1,2,3...9 定位到对应数值的书签位置
Ctrl + 左键单击 在打开的文件标题上,弹出该文件路径
Ctrl + 光标定位 按 Ctrl 不要松开,会显示光标所在的类信息摘要
Ctrl + 左方向键 光标跳转到当前单词 / 中文句的左侧开头位置
Ctrl + 右方向键 光标跳转到当前单词 / 中文句的右侧开头位置
Ctrl + 前方向键 等效于鼠标滚轮向前效果
Ctrl + 后方向键 等效于鼠标滚轮向后效果三、Alt相关
Alt + ` 显示版本控制常用操作菜单弹出层
Alt + Q 弹出一个提示,显示当前类的声明 / 上下文信息
Alt + F1 显示当前文件选择目标弹出层,弹出层中有很多目标可以进行选择
Alt + F2 对于前面页面,显示各类浏览器打开目标选择弹出层
Alt + F3 选中文本,逐个往下查找相同文本,并高亮显示
Alt + F7 查找光标所在的方法 / 变量 / 类被调用的地方
Alt + F8 在 Debug 的状态下,选中对象,弹出可输入计算表达式调试框,查看该输入内容的调试结果
Alt + Home 定位 / 显示到当前文件的 Navigation Bar
Alt + Enter IntelliJ IDEA 根据光标所在问题,提供快速修复选择,光标放在的位置不同提示的结果也不同 (必备)
Alt + Insert 代码自动生成,如生成对象的 set / get 方法,构造函数,toString() 等(必备)
Alt + 左方向键 按左方向切换当前已打开的文件视图
Alt + 右方向键 按右方向切换当前已打开的文件视图
Alt + 前方向键 当前光标跳转到当前文件的前一个方法名位置
Alt + 后方向键 当前光标跳转到当前文件的后一个方法名位置
Alt + 1,2,3...9 显示对应数值的选项卡,其中 1 是 Project 用得最多四、Shift相关
Shift + F1 如果有外部文档可以连接外部文档
Shift + F2 跳转到上一个高亮错误 或 警告位置
Shift + F3 在查找模式下,查找匹配上一个
Shift + F4 对当前打开的文件,使用新Windows窗口打开,旧窗口保留
Shift + F6 对文件 / 文件夹 重命名
Shift + F7 在 Debug 模式下,智能步入。断点所在行上有多个方法调用,会弹出进入哪个方法
Shift + F8 在 Debug 模式下,跳出,表现出来的效果跟 F9 一样
Shift + F9 等效于点击工具栏的 Debug 按钮
Shift + F10 等效于点击工具栏的 Run 按钮
Shift + F11 弹出书签显示层
Shift + Tab 取消缩进
Shift + ESC 隐藏当前 或 最后一个激活的工具窗口
Shift + End 选中光标到当前行尾位置
Shift + Home 选中光标到当前行头位置
Shift + Enter 开始新一行。光标所在行下空出一行,光标定位到新行位置
Shift + 左键单击 在打开的文件名上按此快捷键,可以关闭当前打开文件
Shift + 滚轮前后滚动 当前文件的横向滚动轴滚动五、Ctrl + Alt相关
Ctrl + Alt + L
格式化代码,可以对当前文件和整个包目录使用 (必备)
Ctrl + Alt + M
提取方法:选中代码,快速抽取为方法 (必备)Ctrl + Alt + O 优化导入的类,可以对当前文件和整个包目录使用 (必备)
Ctrl + Alt + I 光标所在行 或 选中部分进行自动代码缩进,有点类似格式化
Ctrl + Alt + T 对选中的代码弹出环绕选项弹出层
Ctrl + Alt + J 弹出模板选择窗口,将选定的代码加入动态模板中
Ctrl + Alt + H 调用层次
Ctrl + Alt + B 在某个调用的方法名上使用会跳到具体的实现处,可以跳过接口
Ctrl + Alt + V 快速引进变量
Ctrl + Alt + Y 同步、刷新
Ctrl + Alt + S 打开 IntelliJ IDEA 系统设置
Ctrl + Alt + F7 显示使用的地方。寻找被该类或是变量被调用的地方,用弹出框的方式找出来
Ctrl + Alt + F11 切换全屏模式
Ctrl + Alt + Enter 光标所在行上空出一行,光标定位到新行
Ctrl + Alt + Home 弹出跟当前文件有关联的文件弹出层
Ctrl + Alt + Space 类名自动完成
Ctrl + Alt + 左方向键 退回到上一个操作的地方 (必备)
Ctrl + Alt + 右方向键 前进到上一个操作的地方 (必备)
Ctrl + Alt + 前方向键 在查找模式下,跳到上个查找的文件
Ctrl + Alt + 后方向键 在查找模式下,跳到下个查找的文件六、Ctrl + Shift相关
Ctrl + Shift + F 根据输入内容查找整个项目 或 指定目录内文件 (必备)
Ctrl + Shift + R 根据输入内容替换对应内容,范围为整个项目 或 指定目录内文件 (必备)
Ctrl + Shift + J 自动将下一行合并到当前行末尾 (必备)
Ctrl + Shift + Z 取消撤销 (必备)
Ctrl + Shift + W 递进式取消选择代码块。可选中光标所在的单词或段落,连续按会在原有选中的基础上再扩展取消选中范围 (必备)
Ctrl + Shift + N 通过文件名定位 / 打开文件 / 目录,打开目录需要在输入的内容后面多加一个正斜杠 (必备)
Ctrl + Shift + U 对选中的代码进行大 / 小写轮流转换 (必备)
Ctrl + Shift + T 对当前类生成单元测试类,如果已经存在的单元测试类则可以进行选择
Ctrl + Shift + C 复制当前文件磁盘路径到剪贴板
Ctrl + Shift + V 弹出缓存的最近拷贝的内容管理器弹出层
Ctrl + Shift + E 显示最近修改的文件列表的弹出层
Ctrl + Shift + H 显示方法层次结构
Ctrl + Shift + B 跳转到类型声明处
Ctrl + Shift + I 快速查看光标所在的方法 或 类的定义
Ctrl + Shift + A 查找动作 / 设置
Ctrl + Shift + / 代码块注释 (必备)
Ctrl + Shift + [ 选中从光标所在位置到它的顶部中括号位置
Ctrl + Shift + ] 选中从光标所在位置到它的底部中括号位置
Ctrl + Shift + + 展开所有代码
Ctrl + Shift + - 折叠所有代码
Ctrl + Shift + F7 高亮显示所有该选中文本,按Esc高亮消失
Ctrl + Shift + F8 在 Debug 模式下,指定断点进入条件
Ctrl + Shift + F9 编译选中的文件 / 包 / Module
Ctrl + Shift + F12 编辑器最大化
Ctrl + Shift + Space 智能代码提示
Ctrl + Shift + Enter 自动结束代码,行末自动添加分号 (必备)
Ctrl + Shift + Backspace 退回到上次修改的地方
Ctrl + Shift + 1,2,3...9 快速添加指定数值的书签
Ctrl + Shift + 左键单击 把光标放在某个类变量上,按此快捷键可以直接定位到该类中 (必备)
Ctrl + Shift + 左方向键 在代码文件上,光标跳转到当前单词 / 中文句的左侧开头位置,同时选中该单词 / 中文句
Ctrl + Shift + 右方向键 在代码文件上,光标跳转到当前单词 / 中文句的右侧开头位置,同时选中该单词 / 中文句
Ctrl + Shift + 左方向键 在光标焦点是在工具选项卡上,缩小选项卡区域
Ctrl + Shift + 右方向键 在光标焦点是在工具选项卡上,扩大选项卡区域
Ctrl + Shift + 前方向键 光标放在方法名上,将方法移动到上一个方法前面,调整方法排序
Ctrl + Shift + 后方向键 光标放在方法名上,将方法移动到下一个方法前面,调整方法排序七、Alt + Shift相关
Alt + Shift + N 选择 / 添加 task
Alt + Shift + F 显示添加到收藏夹弹出层 / 添加到收藏夹
Alt + Shift + C 查看最近操作项目的变化情况列表
Alt + Shift + I 查看项目当前文件
Alt + Shift + F7 在 Debug 模式下,下一步,进入当前方法体内,如果方法体还有方法,则会进入该内嵌的方法中,依此循环进入
Alt + Shift + F9 弹出 Debug 的可选择菜单
Alt + Shift + F10 弹出 Run 的可选择菜单
Alt + Shift + 左键双击 选择被双击的单词 / 中文句,按住不放,可以同时选择其他单词 / 中文句
Alt + Shift + 前方向键 移动光标所在行向上移动
Alt + Shift + 后方向键 移动光标所在行向下移动八、其他
F2 跳转到下一个高亮错误 或 警告位置 (必备)
F3 在查找模式下,定位到下一个匹配处
F4 编辑源
F7 在 Debug 模式下,进入下一步,如果当前行断点是一个方法,则进入当前方法体内,如果该方法体还有方法,则不会进入该内嵌的方法中
F8 在 Debug 模式下,进入下一步,如果当前行断点是一个方法,则不进入当前方法体内
F9 在 Debug 模式下,恢复程序运行,但是如果该断点下面代码还有断点则停在下一个断点上
F11 添加书签
F12 回到前一个工具窗口
Tab 缩进
ESC 从工具窗口进入代码文件窗口Ctrl + Shift + Alt + V 无格式黏贴
Ctrl + Shift + Alt + N 前往指定的变量 / 方法
Ctrl + Shift + Alt + S 打开当前项目设置
Ctrl + Shift + Alt + C 复制参考信息
9、idea其他操作技巧
- 输入
sout
:会输出System.out.prinln()
- 输入
main
:会输出public static void main(String[] args) {}
- 输入
4.fori
:会输出for (int i = 0; i < 4; i++) {}
- 输入
arr.length.fori
:会输出for (int i = 0; i < arr.length; i++) {}
10、推荐插件
- Chinese (Simplified) Language Pack
- Alibaba Java Coding Guidelines阿里巴巴代码规范检查插件
- Presentation Assistant 快捷键展示
Key Promoter X 快捷键提示插件
弃用,前一个好用 - Gsonformat
- Translation翻译插件
- One Dark Theme
- Rainbow Brackets彩虹括号插件
- Codota
- MybatisX 高效操作Mybatis plus插件
- PTG 自动生成JavaBean
- HighlightBracketPair —— 括号开始结尾 高亮显示。
- Grep Console 控制台日志 高亮
- google-java-format —— 代码自动格式化
- Leetcode Editor 可以在IDEA中在线刷题。
- Material Theme UI ——IDEA主题插件
- RoboPOJOGenerator—JSON(根据json生成类)(GsonFormat也可以,但是好久没更新过了)
- Atom Material File Icons
三、融合其他框架
1、jwt
1.1、加入依赖
<!-- JWT -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
1.2、配置
config:
jwt:
# 是否校验 1 开 ; 0 关
isOpen: 1
# 加密密钥
secret: 92df4304-80c6-43b6-9bb2-beb6cf9b6845
# token有效时长
expire: 3600
# header 名称
header: token
1.3、配置类
package cn.tjhis.hisapi.config;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTPayload;
import cn.hutool.jwt.signers.JWTSignerUtil;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import cn.hutool.jwt.JWTUtil;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;
/**
* 描述:JWT的token,区分大小写
* 路径:cn.tjhis.hisapi.config
* 工程:hisApi
* 作者:wanghx
* 日期:2023-02-06 10:24
*/
@ConfigurationProperties(prefix = "config.jwt") // 用于绑定属性,其中prefix表示所绑定的属性的前缀。
@Component // 表示将该类标识为Bean
@Data
public class JwtConfig {
private int isOpen;
private String secret;
private long expire;
private String header;
/**
* 生成token
* @param payload
* @return
*/
public String createToken (Map<String,Object> payload){
Date nowDate = new Date();
Date expireDate = new Date(nowDate.getTime() + expire * 1000);//过期时间
//签发时间
payload.put(JWTPayload.ISSUED_AT, nowDate);
//生效时间
payload.put(JWTPayload.NOT_BEFORE, nowDate);
//过期时间 最大有效期1天强制过期
payload.put(JWTPayload.EXPIRES_AT, expireDate);
return JWTUtil.createToken(payload, JWTSignerUtil.hs256(secret.getBytes(StandardCharsets.UTF_8)));
}
/**
* 解析token
* @param token
* @return
*/
public JWT parse(String token){
return JWT.create().setSigner(JWTSignerUtil.hs256(secret.getBytes(StandardCharsets.UTF_8))).parse(token);
}
}
1.4、编写controller层下UserController类
package cn.tjhis.hisapi.controller;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;
import cn.tjhis.hisapi.config.JwtConfig;
import cn.tjhis.hisapi.entity.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.ssssssss.magicapi.core.model.JsonBean;
import org.ssssssss.magicapi.core.service.MagicAPIService;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* 描述:登录
* 路径:cn.tjhis.hisapi.controller
* 工程:hisApi
* 作者:wanghx
* 日期:2023-02-06 06:07
*/
@RestController
public class LoginController {
private final MagicAPIService service;
private static final Logger logger = LoggerFactory.getLogger(LoginController.class);
@Resource
private JwtConfig jwtConfig ;
public LoginController(MagicAPIService service) {
this.service = service;
}
@GetMapping("/login")
public Object login(String userName, String password) {
if (StrUtil.isEmpty(userName)){
return new JsonBean<>(-1, "用户名不能为空!");
}
if (StrUtil.isEmpty(password)){
return new JsonBean<>(-1, "密码不能为空!");
}
// 根据用户名获取信息
Map<String, Object> params = new HashMap<>();
// 注入变量信息
params.put("userName", userName.toUpperCase());
// 内部调用接口不包含code以及message信息,同时也不走拦截器。
try {
LinkedHashMap linkedHashMap = service.execute("GET", "/comm/getUserByUserName", params);
if (linkedHashMap == null){
return new JsonBean<>(-1, "用户不存在!");
}
// 将obj转换成User对象
User user = JSONUtil.toBean(JSONUtil.parseObj(linkedHashMap),User.class);
//获取密文字节数组
String pwd = (user.getUserPwd() + "wanghx").toUpperCase();
// 字符串反转后md5加密
String pwdEnc = SecureUtil.md5(StrUtil.reverse(pwd));
if (password.equals(pwdEnc))
{
// token中不携带密码
linkedHashMap.remove("userPwd");
String token = jwtConfig.createToken(linkedHashMap);
return new JsonBean<>(200,"success",token);
}
else
{
return new JsonBean<>(-1, "密码不正确!");
}
}
catch (Exception e){
return new JsonBean<>(-1, e.getMessage());
}
}
}
1.5、拦截器
package cn.tjhis.hisapi.interceptor;
import cn.hutool.jwt.JWT;
import cn.tjhis.hisapi.config.JwtConfig;
import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.ssssssss.magicapi.core.interceptor.RequestInterceptor;
import org.ssssssss.magicapi.core.model.ApiInfo;
import org.ssssssss.magicapi.core.model.JsonBean;
import org.ssssssss.magicapi.core.model.Options;
import org.ssssssss.script.MagicScriptContext;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 自定义请求拦截器,可实现鉴权
* https://ssssssss.org/magic-api/pages/senior/interceptor/
*
* @see RequestInterceptor
*/
@Component
@Order(1) //拦截器顺序,可选
public class CustomRequestInterceptor implements RequestInterceptor {
@Resource
private JwtConfig jwtConfig;
private static final Logger logger = LoggerFactory.getLogger(CustomRequestInterceptor.class);
/**
* 接口请求之前
*
* @param info 接口信息
* @param context 脚本变量信息
*/
@Override
public Object preHandle(ApiInfo info, MagicScriptContext context, HttpServletRequest request, HttpServletResponse response) throws Exception {
String path = request.getRequestURI();
logger.info("请求接口:{},{}", info.getName(), Options.REQUIRE_LOGIN);
// 是否开启
if (jwtConfig.getIsOpen()==1){
//获取请求头中的令牌
String token = request.getHeader(jwtConfig.getHeader());
try {
//验证令牌
JWT verify = jwtConfig.parse(token);
return null;
} catch (SignatureVerificationException e) {
return new JsonBean<>(-1,"无效签名");
} catch (TokenExpiredException e) {
return new JsonBean<>(-1,"token过期");
} catch (AlgorithmMismatchException e) {
return new JsonBean<>(-1,"token算法不一致");
} catch (Exception e) {
return new JsonBean<>(-1,"token无效");
}
}
return null;
}
/**
* 接口执行之后
*
* @param info 接口信息
* @param context 变量信息
* @param value 即将要返回到页面的值
*/
@Override
public Object postHandle(ApiInfo info, MagicScriptContext context, Object value, HttpServletRequest request, HttpServletResponse response) throws Exception {
logger.info("{} 执行完毕,返回结果:{}", info.getName(), value);
return null;
}
}
1.6、magic-api中使用token
import cn.tjhis.hisapi.config.JwtConfig;
var jwt = JwtConfig.parse(header.token)
return jwt.payloads.id;
2、Redis
2.1、引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.2、注入后编写代码
- 注入的时候用
Resource
注解或者构造器,不推荐用Autowired
redisTemplate
这个名字不能写错,否则报错:expected single matching bean but found 2: redisTemplate,stringRedisTemplate
@Resource
注解是javax
包中的注解,它是优先byName
来装配的,如果byName
无法装配,则会自动尝试byType
装配,在byType
装配时,要求匹配类型的对象必须有且仅有1个,如果无法装配,则会报告错误。@Autowired
注解是Spring框架中的注解,它是优先byType
来装配的,@Autowired
为Spring提供的注解,需要导入包:org.springframework.beans.factory.annotation.Autowired
@Resource
注解由J2EE提供,需要导入包:javax.annotation.Resource
package cn.tjhis.springredis.controller;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* 描述:
* 路径:cn.tjhis.springredis.controller
* 工程:spring-redis
* 作者:wanghx
* 日期:2023-02-07 06:15
*/
@RestController
public class TestController {
@Resource
private RedisTemplate redisTemplate;
@GetMapping("get")
public Object get(String key){
return redisTemplate.boundValueOps(key).get();
}
@GetMapping("set")
public void set(String key,String name){
redisTemplate.boundValueOps(key).set(name);
}
}
3、logback
-
基本信息(不用添加任何pom引用)
- SpringBoot版本2.4.5
- 日志框架SLF4J
- 日志框架的实现LockBack
-
使用xml配置可以完成yml配置实现不了的功能,比如按天将日志归档。
-
xml有多种命名形式,但官方推荐的命名是logback-spring.xml
-
日志文件输出在项目根目录下的logs文件夹下。
<?xml version="1.0" encoding="UTF-8"?> <configuration scan="true" scanPeriod="60 seconds" debug="false"> <contextName>logback</contextName> <!--控制台输出内容的颜色转换以及格式--> <substitutionProperty name="logging.pattern.console" value="%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/> <!--日志文件输出内容的格式--> <substitutionProperty name="logging.pattern.file" value="%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/> <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/> <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/> <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/> <!--输出到控制台--> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <!--控制台使用layout节点--> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern> ${logging.pattern.console} </pattern> </layout> </appender> <!--按天生成日志--> <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender"> <Prudent>true</Prudent> <!--滚动策略,我配置了按天生成日志文件--> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!--相对路径,生成的文件就在项目根目录下--> <FileNamePattern> logs/%d{yyyy-MM-dd}.log </FileNamePattern> <!--注意超过365天的日志文件会被删除,即使已经按天分开也会删除--> <MaxHistory>365</MaxHistory> </rollingPolicy> <!--日志文件里只保存ERROR及以上级别的日志 INFO --> <!-- <filter class="ch.qos.logback.classic.filter.ThresholdFilter">--> <!-- <level>INFO</level>--> <!-- </filter>--> <!--文件使用encoder节点--> <encoder> <Pattern> ${logging.pattern.file} </Pattern> </encoder> </appender> <!--这个logger里的配置相当于之前yml里的logging.level.com.lpc: trace--> <!--additivity的作用--> <!--true,则子Logger不止会在自己的appender里输出,还会在root的logger的appender里输出--> <!--而这个logger里没配置appender,所以得交给root打印--> <!--所以cn.tjhis.hisapi包里的日志从TRACE级别开始--> <!--其他包里的日志根据root的配置从INFO级别开始打印--> <logger name="cn.tjhis.hisapi" level="TRACE" additivity="true"> </logger> <root level="INFO"> <appender-ref ref="console"/> <appender-ref ref="file"/> </root> </configuration>
4、hutool
4.1、db
-
Maven项目中在
src/main/resources
目录下添加db.setting
文件(非Maven项目添加到ClassPath中即可),[mysql]
是分组,如果只连接一个数据库,可不写,如果写了,必须显式的指定,否则报错No config for group: []
## db.setting文件 [mysql] url = jdbc:mysql://localhost:3306/net6Api user = admin pass = Admin@123 ## 可选配置 # 是否在日志中显示执行的SQL showSql = true # 是否格式化显示的SQL formatSql = false # 是否显示SQL参数 showParams = true # 打印SQL的日志等级,默认debug,可以是info、warn、error sqlLevel = debug
-
添加依赖
<properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <mysql.version>8.0.27</mysql.version> <hutool.version>5.8.12</hutool.version> </properties> <dependencies> <!--mysql数据库驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <!-- 引入 hutool --> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>${hutool.version}</version> </dependency> </dependencies>
-
测试
import java.sql.SQLException; import java.util.List; /** * 描述:hutool的DB测试类 * 路径:cn.tjhis.hutool * 工程:testHutool * 作者:wanghx * 日期:2023-02-11 07:50 */ public class DbTest { public static void main(String[] args) { // 只有一个数据库,可不写,[mysql] Db db = Db.use("mysql"); try { // 查询全部 List<Entity> payrollInfo = db.findAll("payroll_info"); Console.log(payrollInfo.get(0).getStr("employee_name")); // 条件查询 List<Entity> list = db.findAll(Entity.create("payroll_info").set("id", 5)); JSON json = JSONUtil.parse(list); Console.error(json.getByPath("salary_month")); } catch (SQLException e) { throw new RuntimeException(e); } } }
5、mybatis
-
搭建工程
-
引入依赖
- 注意
spring-boot-starter
版本2.4.5
与mybatis-spring-boot-starter
的版本2.2.2
- 也不需要加
@Component
或者@Repository
或者@MapperScan
等等
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.5</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.2</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.8</version> </dependency> <dependency> <groupId>com.oracle.database.jdbc</groupId> <artifactId>ojdbc6</artifactId> <version>11.2.0.4</version> </dependency> <dependency> <groupId>com.oracle.database.nls</groupId> <artifactId>orai18n</artifactId> <version>19.7.0.0</version> </dependency>
- 注意
-
编写DataSource和mybatis相关配置proterties.yml
-
定义表和实体类
@Data public class Dept { private int deptNo; private String dName; private String loc; }
-
编写dao和mapper
@Mapper public interface DeptMapper { /** * 查询所有科室 * @return 返回所有科室 */ @Select("select deptno, dname, loc from scott.dept") public List<Dept> findDeptList(); }
-
编写controller
@RestController public class DeptController { @Resource private DeptMapper mapper; @GetMapping("getDeptAll") public String getDeptList(){ JSON json = JSONUtil.parse(mapper.findDeptList()); return json.toString(); } }
-
测试
@SpringBootTest class SpringbootMybatisApplicationTests { @Resource private DeptMapper mapper; @Test void test() { List<Dept> deptList = mapper.findDeptList(); String json = JSONUtil.parse(deptList).toString(); System.out.println(json); } }
6、Mybatis Plus(简称 MP)
-
优势:
- 是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
- 内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
- 只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
-
依赖
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.2</version> </dependency>
-
启动类中添加
@MapperScan
注解,扫描 Mapper 文件夹:@SpringBootApplication @MapperScan("cn.tjhis.springboot.mybatis.plus.mapper") public class SpringbootMybatisPlusApplication { public static void main(String[] args) { SpringApplication.run(SpringbootMybatisPlusApplication.class, args); } }
-
创建实体
- 默认生成的语句是:
SELECT dept_no,d_name,loc FROM scott.dept
,所以需要指定表名和映射的字段名。 - 需要指出表名:
@TableName
- 需要指定字段:
@TableField
@Data @TableName("scott.dept") public class Dept { @TableField("deptno") private int deptNo; @TableField("dname") private String dName; private String loc; }
- 默认生成的语句是:
-
创建mapper
- 不需要写
@Mapper
注解 - DeptMapper中的
selectList()
方法的参数为 MP 内置的条件封装器Wrapper
,所以不填写就是无任何条件
public interface DeptMapper extends BaseMapper<Dept> { }
- 不需要写
-
测试
@SpringBootTest class SpringbootMybatisPlusApplicationTests { @Resource private DeptMapper deptMapper; @Test void test() { System.out.println(("----- selectAll method test ------")); List<Dept> userList = deptMapper.selectList(null); userList.forEach(System.out::println); } }