注:本文介绍的内容都是相对基础的部分,有些地方挖坑未填,请按需阅读谢谢。
1. 相关介绍
SpringBoot用于简化Spring应用开发,有以下优点:
- 能快速创建独立的Spring项目
- 使用嵌入式的Servlet容器,无需打成war包,打成jar包用java -jar即可运行
- 很多配置都是自动配置的,我们也可以修改对应的默认值
2. 快速入门
需求:发送一个hello请求,响应Hello World
1、创建一个maven工程,在pom.xml中添加如下内容
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
2、编写一个controller
package pers.ljc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class HelloController {
/**
* @ResponseBody
* 1.不加该注解,返回字符串时会认为是jsp页面
* 2.加上该注解,当返回对象时会转换为json数据,当返回字符串时则原样返回
*/
@ResponseBody
@RequestMapping("/hello")
public String hello() {
return "Hello World";
}
}
3、编写主程序,启动SpringBoot应用
package pers.ljc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @SpringBootApplication 用于标注一个主程序类,说明这是一个SpringBoot应用
*/
@SpringBootApplication
public class App {
public static void main(String[] args) {
// run方法传入的参数一必须是@SpringBootApplication注解标注的类
SpringApplication.run(App.class, args);
}
}
4、运行主程序的main方法即可实现需求
5、在pom.xml中添加如下内容,并双击下图中的"package"即可打包成jar包
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
6、使用java -jar命令也能运行
3. 配置文件
全局配置文件有一个,application.properties或者application.yml,用于修改SpringBoot自动配置的默认值。yml文件格式比较简洁,例子如下
# 使用缩进表示上下级关系,左对齐的是同级关系,冒号与内容之间有一个空格
server:
port: 8081
3.1 yaml语法
3.1.1 字面量
直接填写即可,字符串不需要加单引号或双引号。
- 单引号,会转义特殊字符:如 name: 'zhangsan \n lisi' 则输出zhangsan 换行 lisi
- 双引号,不会转义特殊字符:如 name: "zhangsan \n lisi" 则输出zhangsan \n lisi
3.1.2 对象
两种写法,如下所示
student:
name: zhangsan
age: 20
student: {name: zhangsan, age: 20}
3.1.3 数组
两种写法,如下所示
pets:
- cat
- dog
- pig
pets: [cat, dog, pig]
3.2 获取配置文件自定义内容
1、在application.yml配置文件中有如下内容
student:
name: zhangsan
age: 20
2、在pom.xml加入如下依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
3、自定义Student类并加上两个注解
/**
* @ConfigurationProperties 默认从全局文件获取数据
* @PropertySource 可以从指定文件中获取数据
* @ImportResource 可以导入Spring的配置文件,一般写在启动类上
*/
@Component
@ConfigurationProperties(prefix = "student")
public class Student {
private String name;
private int age;
// get和set方法...
}
4、在测试类中可以使用@Autowired注解就能自动注入内容
@SpringBootTest
class SpringbootTestApplicationTests {
@Autowired
private Student student;
@Test
void contextLoads() {
System.out.println(student);
}
}
3.3 给容器添加组件
/**
* @Configuration 指明当前类是一个配置类
*/
@Configuration
public class MyConfig {
/**
* @Bean 将方法的返回值添加到容器中,该组件的id就是方法名
*/
@Bean
public HelloService helloService() {
System.out.println("配置文件生效");
return new HelloService();
}
}
3.4 Profile
用于快速切换不同环境(开发、测试、运维等)的配置文件。yml配置文件可以用"---"来分隔各个环境的配置文件。
server:
port: 8081
spring:
profiles:
active: prod # 激活prod环境配置,运行时就会看到端口号为8083
--- # 分隔各个配置块
server:
port: 8082
spring:
profiles: dev # 声明这是dev环境的配置
---
server:
port: 8083
spring:
profiles: prod # 声明这是prod环境的配置
3.5 配置文件加载顺序
SpringBoot的配置文件加载顺序如下,会从以下位置去找application.properties或application.yml,优先级由高到低,相同配置则高优先级的会覆盖低的,且是互补配置。
-
-file:./config/
-
-file:./
-
-classpath:/config/
-
-calsspath:/
以IDEA为例,当这四个位置都配置了端口号时,最终采取的是配置文件1
4. 日志
-
常见的日志框架如下
抽象层 具体实现 jcl、slf4j、jboss-logging log4j、jul、log4j2、logback -
SpringBoot采用slf4j+logback,开发时应该调用抽象层的方法,而配置文件应该写具体实现框架的配置文件
-
日志级别由高到低排序:error > warn > info > debug > trace,SpringBoot默认级别是info
-
常用配置
# 在application.properties中配置 # pers.ljc包下的日志级别为warn logging.level.pers.ljc=warn # 在E:/log文件夹下生成spring.log日志文件 logging.file.path=E:/log
5. Web开发
5.1 静态资源映射关系
-
/webjars/** 访问的是 classpath:/META-INF/resources/webjars/
webjars:以jar包方式引入的静态资源
-
/** 访问当前项目的任何路径,如果没处理,则去下列位置(静态资源文件夹)找
- classpath:/META-INF/resources/
- classpath:/resources/
- classpath:/static/
- classpath:/public/
- / (当前项目的根路径)
(注:classpath后面的'/'是IDEA工程中的resources文件夹)
-
项目首页(如index.html)是放在静态资源文件夹中
-
所有页面的小图标都是从静态资源文件夹中找
5.2 Thymeleaf模板引擎
SpringBoot推荐的模板引擎是Thymeleaf。
5.2.1 导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
5.2.2 快速使用
/**
* 如果这里使用@RestController,则不会把字符串作为html页面的前缀,就找不到相应的html页面
*/
@Controller
public class HelloController {
@RequestMapping("/hello")
public String hello(Map<String, Object> map) {
// 会去classpath:/templates/下找hello.html
return "hello";
}
}
5.2.3 语法格式
官方语法说明点这里。
1、在html页面导入Thymeleaf命名空间
<html lang="en" xmlns:th="http://www.thymeleaf.org">
2、使用${}可获取controller层放置的数据
@RequestMapping("/hello")
public String hello(Map<String, Object> map) {
map.put("hello", "你好");
return "hello";
}
<body>
<h1>欢迎</h1>
<!-- th:text设置div的文本内容 -->
<div th:text="${hello}"></div>
</body>
更多内容可查看官方文档。
5.3 SpringMVC的自动配置
(该部分暂未理解清楚...)
根据官方文档,SpringBoot为SpringMVC配置了如下内容
-
Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.
配置了ViewResolver即视图解析器,根据方法的返回值得到视图对象,视图对象决定如何渲染(转发、重定向等)
ContentNegotiatingViewResolver:组成所有视图解析器
-
Support for serving static resources, including support for WebJars.
-
Automatic registration of Converter, GenericConverter, and Formatter beans.
-
Support for HttpMessageConverters.
-
Automatic registration of MessageCodesResolver.
-
Static index.html support.
-
Custom Favicon support.
-
Automatic use of a ConfigurableWebBindingInitializer bean.
5.4 错误处理
(该部分暂未理解清楚...)
在ErrorMvcAutoConfiguration类中,有下列这些组件:
-
DefaultErrorAttributes
-
BasicErrorController:两个处理/error请求的方法,浏览器的请求会响应html页面,其他客户端的请求会响应JSON数据
-
ErrorPageCustomizer
-
DefaultErrorViewResolver
一旦出现4xx或5xx的错误,内部类ErrorPageCustomizer就会生效并定制错误的响应规则,发送/error请求,然后BasicErrorController来处理该/error请求。
5.4.1 定制错误页面
以IDEA工程为例,在/resources/templates(或者static)文件夹下建立error文件夹,里面放置html页面。比如要响应404错误,就放置404.html页面,也可以放置4xx.html来响应以4开头的错误。
5.4.2 定制错误JSON数据
1、没有自适应效果,即浏览器和其他客户端都是响应JSON数据
@ControllerAdvice
public class MyExceptionHandler {
@ResponseBody
@ExceptionHandler(MyException.class)
public Map<String, Object> handleException(Exception e) {
Map<String, Object> map = new HashMap<>();
map.put("code", "404");
map.put("message", e.getMessage());
return map;
}
}
2、有自适应效果,浏览器响应html页面,其他客户端响应JSON数据
@ControllerAdvice
public class MyExceptionHandler {
@ExceptionHandler(MyException.class)
public String handleException(Exception e, HttpServletRequest request) {
Map<String, Object> map = new HashMap<>();
map.put("code", "404");
map.put("message", e.getMessage());
request.setAttribute("javax.servlet.error.status_code", 404);
return "forward:/error";
}
}
5.5 配置Server相关
5.5.1 修改配置
# application.properties
# 修改server相关配置
server.xxx
# 修改tomcat相关配置
server.tomcat.xxx
5.5.2 注册Servlet、Filter、Listener
1、自定义MyServlet、MyFilter、MyListener
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("Hello MyServlet!");
}
}
/**
* 实现的接口是javax.servlet包下的
*/
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("My filter process...");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {}
}
public class MyListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("contextInitialized -> web应用启动");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("contextDestroyed -> 销毁web项目");
}
}
2、自定义配置类,注册这三个组件
@Configuration
public class MyServerConfig {
/**
* 注册Servlet
*/
@Bean
public ServletRegistrationBean myServlet() {
// 该servlet对应的映射路径是/myServlet
return new ServletRegistrationBean(new MyServlet(), "/myServlet");
}
/**
* 注册Filter
*/
@Bean
public FilterRegistrationBean myFilter() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new MyFilter());
// 该过滤器拦截以下url
registrationBean.setUrlPatterns(Arrays.asList("/hello", "/myServlet"));
return registrationBean;
}
/**
* 注册Listener
*/
@Bean
public ServletListenerRegistrationBean myListener() {
return new ServletListenerRegistrationBean<MyListener>(new MyListener());
}
}
5.6 整合Mybatis
1、导入相关依赖
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
2、编写连接数据库的接口及其xml文件
public interface StudentMapper {
Student getStudentById(String id);
}
<!-- StudentMapper.xml,位于classpath:/mapper/下 -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="pers.ljc.springboot_mybatis.mapper.StudentMapper">
<select id="getStudentById" resultType="student" parameterType="java.lang.String">
select SId id, Sname name, Sage age, Ssex sex from student where SId = #{id}
</select>
</mapper>
3、配置application.yml
spring:
datasource:
username: root
password: persona5
url: jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC&useSSL=false
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
mapper-locations: classpath:/mapper/*Mapper.xml
type-aliases-package: pers.ljc.springboot_mybatis.model
4、响应的调用层调用即可
@RestController
@RequestMapping("/student")
public class StudentController {
// 这里按照规范应该是放在service层中
@Autowired
private StudentMapper studentMapper;
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public Student getStudentById(@PathVariable String id) {
return studentMapper.getStudentById(id);
}
}