环境
使用IDEA开发工具和Gradle构建工具
一、基础知识
1.gradle配置国内镜像仓库
a.全局配置
在用户家目录下的.gradle根目录新建一个init.gradle文件并键入以下内容
allprojects {
repositories {
// 定义变量 变量指向阿里镜像仓库地址
def ALIYUN_REPOSITORY_URL = 'http://maven.aliyun.com/nexus/content/groups/public'
def ALIYUN_JCENTER_URL = 'http://maven.aliyun.com/nexus/content/repositories/jcenter'
maven {
// 配置maven使用地址
url ALIYUN_REPOSITORY_URL
url ALIYUN_JCENTER_URL
}
}
}
b.单项目配置
在项目的build.gradle文件中配置(以配置华为镜像maven仓库为例)
repositories {
maven {
url 'https://mirrors.huaweicloud.com/repository/maven/'
}
}
c.gradle下载的jar包位置
gradle默认下载的jar包位置在**.gradle\caches\modules-2\files-2.1**文件夹下。
2.第一个boot工程
新建一个gradle的java工程,配置build.gradle如下
build.gradle
// 声明使用哪些插件
plugins {
id 'java'
id 'org.springframework.boot' version '2.1.3.RELEASE'
}
// 引用 spring boot 依赖传递插件
apply plugin: 'io.spring.dependency-management'
// 当前项目信息
group 'com.boot'
version '1.0-SNAPSHOT'
// 兼容性 -- jdk版本
sourceCompatibility = 1.8
// 项目依赖下载的库
repositories {
maven {
url 'https://mirrors.huaweicloud.com/repository/maven/'
}
}
// 项目依赖的jar包
dependencies {
// 导入spring boot starter依赖
implementation 'org.springframework.boot:spring-boot-starter-web'
}
新建一个类作为项目主起动类:
// @SpringBootApplication 表示这是该项目的启动类
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
新建一个类测试接口访问:
@RestController
public class TestController {
@GetMapping("/test")
public String test() {
return "hello";
}
}
运行主启动类的main方法,启动项目并访问localhost:8080/test测试接口是否能访问。
@SpringBootApplication
@SpringBootApplication是一个组合注解@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan三个注解的组合注解。分别是配置spring boot 、开启自动配置、配置包扫描。
二、基础配置
1.@Configuration
这个注解标注的类是一个配置类,类似于@Controller,@Component,@Service,@Repository都能把一个对象加入到spring 容器,只是有不同的语义。
2.定制启动banner
boot项目启动时默认界面:
在项目 resources目录下新建一个banner.txt,键入以下内容:
db db d88888b db db .d88b. d8888b. .d88b. .d88b. d888888b
88 88 88' 88 88 .8P Y8. 88 `8D .8P Y8. .8P Y8. `~~88~~'
88ooo88 88ooooo 88 88 88 88 88oooY' 88 88 88 88 88
88~~~88 88~~~~~ 88 88 88 88 88~~~b. 88 88 88 88 88
88 88 88. 88booo. 88booo. `8b d8' 88 8D `8b d8' `8b d8' 88
YP YP Y88888P Y88888P Y88888P `Y88P' Y8888P' `Y88P' `Y88P' YP
再次启动项目,启动界面就变了:
也可以是一个图片,在resources下添加一张图片并命名为bannber。
例如我在ppt中截图艺术字并保存命名为banner.png
再复制到resources下:
再次启动项目:
**说明:**名字不能写错 banner ,banner.txt优先使用。
3.配置tomcat
只要引入了web模块就默认引入了内置的tomcat,要配置tomcat的信息,可以在resources下新建一个application.properties来配置,如下配置端口号,容器配置默认已server开头
server.port=8081 # 配置端口号
server.servlet.session.timeout=30m // 配置session失效时间
server.servlet.context-path=/demo01 // 配置项目根目录
server.tomcat.uri-encoding=UTF-8 // 配置字符编码
server.tomcat.basedir=C:/demo // 配置tomcat日志目录,默认是系统临时目录
配置后访问路径就变成了:http://localhost:8081/demo01/test
4.替换默认servlet容器
configurations {
// 排除spring-boot-starter-tomcat
implementation.exclude module: 'spring-boot-starter-tomcat'
}
// 项目依赖的jar包
dependencies {
// 导入spring boot starter依赖
implementation 'org.springframework.boot:spring-boot-starter-web'
// 添加jetty容器
implementation "org.springframework.boot:spring-boot-starter-jetty"
}
5.配置文件
a.配置文件位置
Spring默认会在一下路径寻找配置文件 :
1 -> 项目根目录下的 config目录
2 -> 项目根目录下
3 -> 项目resources目录的config目录
4 -> 项目resource目录下
配置文件的名字必须是application且可以是properties格式或者yml格式。
b.读取配置文件
在配置文件中自定义内容,可以在代码中读取,如下配置文件中的内容
person.username=zhangsan
person.age=18
在代码中读取
通过**@ConfigurationProperties(prefix = “person”)**读取
@Bean
@ConfigurationProperties(prefix = "person")
public User user() {
return new User();
}
通过**@value**读取
@Configuration
public class User {
@Value("${user.username}")
private String username;
@Value("${user.age}")
private String age;
// 省略getter/setter...
c.多环境配置文件
方式一:
spring boot可以配置多个环境的配置文件,其中application.properties是公用的配置文件
application.properties
spring.profiles.active=dev
user.username=zhangsan
user.age=123
application-dev.properties
server.port=8080
user.username=lisi
application-test.properties
server.port=8081
spring boot在启动时默认读取application.properties配置文件,其中有这样一个配置spring.profiles.active=test,表示应用application-dev.properties文件中的配置。如果application-dev.properties和application.properties有相同的已application-dev.properties的为准。
方式二:
同一个配置文件中指定环境,用 —和spring.profiles 来区分不同环境的配置,在spring.profiles.active选择当前应用的配置
spring:
profiles:
active: dev
user:
username: zhangsan
age: 18
---
spring:
profiles: dev
server:
port: 8081
user:
username: lisi
---
spring:
profiles: test
server:
port: 8081
三、Web层
1.返回json数据
Spring Boot默认使用的是JackSon做的对象Json序列化的。
例子:
@RestController
public class TestController {
@Autowired
private User user;
@GetMapping("/test")
public Date test() {
return new Date();
}
}
@RestController注解可以返回json数据,这是@Controller和@ResponseBody的组合注解。
2.设置忽略字段
有个类Person.java,其中有个字段是password,这个字段不允许被返回到前端,那么就可以用**@JsonIgnore**标注改字段
public class Person {
private String name;
private int age;
private Date birth;
@JsonIgnore
private String password;
// ....
}
Controller中返回:
@GetMapping("/person")
public Person getPerson(){
Person zhangsan = new Person("zhangsan", 18,new Date(), "123456");
return zhangsan;
}
浏览器中访问,被标记了@JsonIgnore注解的字段不会被返回:
{
name: "zhangsan",
age: 18,
birth: "2019-02-25T09:46:31.800+0000"
}
3.自定义返回格式
Spring boot默认返回的日期格式是:"2019-02-25T09:46:31.800+0000"类似这样的字符串。要配置具体返回格式可以用过**@JsonFormat**来指定
public class Person {
private String name;
private int age;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date birth;
@JsonIgnore
private String password;
}
返回格式:
{
name: "zhangsan",
age: 18,
birth: "2019-02-25 09:52:58"
}
同时,如果这个对象作为请求参数,那么对应的参数也应该是yyyy-MM-dd HH:mm:ss这个格式
更简单的方式,通过配置文件配置:
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
返回时间戳
但前后端交换date类型的数据时,更通用的是使用时间戳。
配置返回时间戳,通过配置文件配置:
spring.jackson.serialization.write-dates-as-timestamps=true
6.配置静态资源访问
spring boot 提供了默认的静态资源访问路径,优先级依次是:/ -> resources/META-INF/resources -> resources/resources -> resources/static -> resources/public
7.上传文件
上传文件要通过MultipartFile类:
@PostMapping("/upload")
public String upload(MultipartFile file, HttpServletRequest request) {
// 获取本地保存文件的路径
String rootPath = request.getServletContext().getRealPath("/upload/images/");
String filePaths = new SimpleDateFormat("yyyy/MM/dd/").format(new Date());
// 获取文件对象 目录格式为 /upload/images/2019/01/10/
File fileSavePath = new File(rootPath + filePaths);
if (!fileSavePath.exists()) {
// 如果不存在就创建
fileSavePath.mkdirs();
}
// 获取上传的文件名
String originalFilename = file.getOriginalFilename();
// 保存文件时的名字 为保证唯一性 加UUID 保存时的名字为 UUID.文件后缀
String saveName = UUID.randomUUID().toString()
+ originalFilename.substring(
originalFilename.lastIndexOf("."), originalFilename.length()
);
try {
// 保存文件
file.transferTo(new File(fileSavePath, saveName));
// 保存后的访问路径是
String url = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
+ fileSavePath + saveName;
// 返回访问路径
return url;
} catch (IOException e) {
e.printStackTrace();
}
return "上传失败!";
}
下面是上传的文件,由于是内置tomcat,路径如下:
多文件上传,用户MultipartFile数组接收,然后遍历数组分别保存。
上传文件配置可通过application.properties配置。
8.控制器增强
@InitBinder
设置数据转换(请求参数格式转对象):
@ControllerAdvice
public class ControllerHandler {
@InitBinder
public void init(WebDataBinder binder) {
// date 类型按指定的格式转换 不允许为空
binder.registerCustomEditor(Date.class,new CustomDateEditor( new SimpleDateFormat("yyyy-MM-dd"), false));
}
}
@InitBinder的另一种用法:
@ControllerAdvice
public class ControllerHandler {
@InitBinder("a")// 处理@ModelAddribute("a") 标记的请求参数
public void handleA(WebDataBinder binder) {
// 请求参数都应该加 a_
binder.setFieldDefaultPrefix("a_");
}
}
实体类
public class User {
private String username;
private int age;
private String password;
private Timestamp birthday;
// getter/setter/construtor
}
接口:
@GetMapping("/user")
public User getUser(@ModelAttribute("a") User user) {
return user;
}
此时传递参数a_username,a_age,a_password,a_birthday也可以传入。这种方式适合请求参数是多个实体,多个实体有同名字段的情况。
@ExceptionHandler
@ControllerAdvice
public class ControllerHandler {
@ExceptionHandler(value = Exception.class)
public void handlerException(Exception e) {
// 方法参数接收 一个指定的异常
System.out.println("捕获到异常...");
// 可以return json数据 添加@ResponseBody 和返回类型即可
}
}
9自定义错误页面
spring boot 默认的错误页面是下面这样的,是由BasicErrorController这个类处理的:
在/resources/static/error下添加对应状态码的html文件即可,比如404.html,500.html等。
10配置跨域
- 方式一,@CrossOrigin注解
标记在请求方法或类上,属性value指定允许的访问的域,maxAge指定Options请求缓存时间也即多长时间内容不用发Options请求(时间s,默认1800),allowedHeaders属性表示允许的请求头。 - 方式二,配置类实现WebMvcConfigurer接口
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedHeaders("*")
.allowedMethods("*")
.allowedOrigins("http://192.168.1.120")
.maxAge(1800);
}
}
11.系统启动时任务
在系统启动时执行初始化数据库等任务,可能过实现CommandLineRunner或ApplicationRunner实现。
CommandLineRunner
多个实现类,通过@Order指定执行顺序,数值越小越先执行,args是接收的是环境参数,在这个地方设置
@Configuration
@Order(2)
class StartInit implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("--------------系统初始化--------------");
for (String arg : args) {
System.out.println(arg);
}
System.out.println("------------系统初始化完成------------");
}
}
@Configuration
@Order(1)
class BeforeStartInit implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("--------------before系统初始化--------------");
for (String arg : args) {
System.out.println(arg);
}
System.out.println("------------before系统初始化完成------------");
}
}
ApplicationRunner
也可以通过@order指定执行顺序,如果ApplicationRunner 和 CommandLineRunner 的Order一样,先执行ApplicationRunner 。两者的区别在于run方法的参数不同。这个参数指定是通过 java -jar xxx.jar --name=xx 这种形式指定的。
@Configuration
@Order(1)
public class AppInit implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("系统初始化...");
}
}
@Configuration
@Order(3)
class AfterAppInit implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("After系统初始化...");
}
}
自定义网站图标favicon
普通图标转ico的网站:https://jinaconvert.com/cn/convert-to-ico.php
.icon文件要命名为favicon.ico,并将favicon.ico文件放到/resources/static目录下即可。