一些开发技巧

Lombok 简化

引入 Lombok 依赖:

1
2
3
4
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>

Lombok 主要解决 Bean 的臃肿问题,需要注意的是 Lombok 无法生成多种参数的构造器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Setter // 注解在类或字段,注解在类时为所有字段生成 setter 方法,注解在字段上时只为该字段生成 setter 方法。
@Getter // 使用方法同上,区别在于生成的是 getter 方法。
@ToString // 生成 toString 方法
@EqualsAndHashCode // 生成 eauqls 和 hashCode 方法
@NoArgsConstructor // 生成无参构造器
@AllArgsConstructor // 生成全参数构造器
@RequiredArgsConstructor // 注解在类,为类中需要特殊处理的字段生成构造方法,比如 final 和被 @NonNull 注解的字段
@Data //生成 getter setter toString equals hashCode 方法
public class Uesr {
@NonNull // 该注解用在属性或构造器上,Lombok会生成一个非空的声明,可用于校验参数,能帮助避免空指针
private String userName;
private String password;
private Address address;

public Uesr(String userName, String password) {
this.userName = userName;
this.password = password;
}
}

还可以注入日志:

1
2
3
4
5
6
7
8
@Slf4j //引入日志
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
log.info("启动完成!"); //直接调用 log 就可以使用日志系统。
}
}

Lombok 本质上就是一个实现了 “JSR 269 API” 的程序。在使用 javac 的过程中,它产生作用的具体流程如下:

  1. javac 对源代码进行分析,生成了一棵抽象语法树(AST)
  2. 运行过程中调用实现了 “JSR 269 API” 的 Lombok 程序
  3. 此时 Lombok 就对第一步骤得到的AST进行处理,找到 @Data 注解所在类对应的语法树(AST),然后修改该语法树(AST),增加 getter 和 setter 方法定义的相应树节点
  4. javac 使用修改后的抽象语法树(AST)生成字节码文件,即给 class 增加新的节点(代码块)

Dev-Tools

这个工具主要是解决热更新的问题(其实就是重启),引入依赖之后,按 Ctrl+F9 来更新页面。

1
2
3
4
5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>

Spring init

在创建项目的时候选择 Spring 项目,然后勾选所需要的组件,IDEA 会自动加载所有的依赖,并创造出完整的目录结构。

application.yaml

application.yaml 是和 application.properties 作用都是完全一样的,不过 yaml 语法格式有点区别。

yml/yaml 是一种类似于 json 的数据保存格式,它的表示形式是 key: value 记得中间有个空格,它的包含关系是通过缩进来解决的,类似于 Python。

基本值

基本值支持一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 整形 int
age: 123

# 浮点型 float
money: 23213.21

# 布尔型 boolean
alive: true

# 日期 data
date: 2020-02-02

# 空 null
point: null

# 字符串 string
name: Xorex \n is Xorex
name: 'Xorex \n is Xorex'
name: "Xorex \n is Xorex"
# 前两者相同,都会转义 \n,而后者不会转义 \n 表示为换行。

对象

当内容为对象的时候,比如 Bean,Map 的时候,可以新增一个层级写多行 key: value ,或者使用 json 的大括号格式写成一行 {key: value,key: value} 逗号隔开,需要空格。

1
2
3
4
5
6
7
user:
username: Tempest Xorex
password: 123456
gender: M
address: ChengDu

user: {user: Tempest Xorex,password: 123456,gender: M,address: ChengDu}

数组列表

同样是两种,多行格式开头没了 key,用 - 表示新的一行开头,或者用单行写法:[XXX,XXX,XXX]

1
2
3
4
5
6
pet:
- dog
- monkey
- cat

pet: [dog,monkey,cat]

小例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Data
@ToString
@Component
@ConfigurationProperties(prefix = "test")
public class Test {
private String name;
private Boolean alive;
private Integer age;
private Address address;
private String[] interests;
private List<Integer> level;
private Map<String,Object> score;
private User user;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
test:
name: Xorex
alive: true
age: 18
address:
userName: Xorex
address:
- ChengDu
- SiChuan
- China
interests: [Sing,jump,Rap,Basketball]
level: [1,2,3,4,5,6]
score:
Chinese: 59
Math: 100
English: 100
user: {userName: Xorex,password: 123456}

成功完成 yaml 版本的自动配置:

Test(name=Xorex, alive=true, age=18, address=Address(userName=Xorex, address=[ChengDu, SiChuan, China]), interests=[Sing, jump, Rap, Basketball], level=[1, 2, 3, 4, 5, 6], score={Chinese=59, Math=100, English=100}, user=User(userName=Xorex, password=123456))

静态资源映射

静态资源文件夹

SpringBoot 是使用 ResourceHttpRequestHandler 来处理请求的,对于一个请求来说,如果 Controller 可以处理,就会交给它,不能处理的则会会依次从 META-INF/resources/resources/static/public 按照请求的静态文件名从里面找同名的静态文件。

这四个文件夹都可以放静态文件,同名文件的优先级顺序为上面的排列顺序,从源码中也可以看出来:

1
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};

修改静态资源文件夹映射路径

是路径和文件夹的映射,以前四个文件夹是映射到根目录的,现在可以通过在配置中设置:

1
2
3
spring:
mvc:
static-path-pattern: /res/**

这样访问静态资源需要在原本路径下前面提娜佳 /res/ 的 pattern 才可以访问。

修改静态资源文件夹

当我们在配置中设置 static-locations 这一项之后,原本的四大静态资源文件夹只会保留一个 META-INF/resources 毕竟是 JavaWeb 原生的东西肯定会保留(剩下三个会被取消),但访问优先级会下降到最低。而新配置的文件夹优先级按照配置顺序来。

1
2
3
4
5
spring:
web:
resources:
static-locations: [classpath:/Static-Resource/,classpath:/Static-Resource2/]
# 这里记得写 classpath 哇

Webjar

Webjar 是指 SpringBoot 将前端所需依赖会打包成一个 Webjar 来供你使用,而我们下载之后的 Webjar 包里面的内容的访问路径则是 /webjars/**,比如我们引入 jQuery 的 Webjar:

1
2
3
4
5
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.5.1</version>
</dependency>

然后可以看到已经下载过的 jQuery,可以看到是放在 /META-INF/resources/webjars/ 下面的,这也是为什么修改 static-locations 之后,还保留 /META-INF/resources,并且 webjar 的内容访问路径为 /webjars/** 了:

322.jpg

对应源码地方就是:

1
this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");

然后访问 http://localhost:8080/res/webjars/jquery/3.5.1/jquery.js 成功!

欢迎页

对于官方的欢迎页的设置来说,可以用 index.html 的文件名放到静态资源文件夹里面,这样直接访问主机名就可以看到 index.html,但是这个时候是不可以配置静态资源访问前缀的,也就是 static-path-pattern ,不然就会失效,理由如下:

1
2
3
4
5
6
7
8
9
10
11
12
WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders,
ApplicationContext applicationContext, Resource welcomePage, String staticPathPattern) {
if (welcomePage != null && "/**".equals(staticPathPattern)) {
//这自己设置了 staticPathPattern 之后,判断就不成立了。
logger.info("Adding welcome page: " + welcomePage);
setRootViewName("forward:index.html");
}
else if (welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) {
logger.info("Adding welcome page template: index");
setRootViewName("index");
}
}

想要实现就只能通过 Controller 映射 / 页面转发到 index.html 了。

favicon.ico

配置网页小图标只需要将文件命名为 favicon.ico 然后放到静态资源目录即可,这个生效也不能配置 static-path-pattern。

这是因为浏览器获取小图标的方式就是访问 网页根目录+favicon.ico 更改了 static-path-pattern 之后也自然无法找到小图标了。