SpringBoot核心技术
1、使用Spring Initializer快速创建Spring Boot项目
IDEA:使用 Spring Initializer快速创建项目
- IDEA支持使用Spring的项目创建向导快速创建一个Spring Boot项目;
- 选择我们需要的模块;向导会联网创建Spring Boot项目;
- 默认生成的Spring Boot项目;
- resources文件夹中目录结构
- static:保存所有的静态资源; js css images;
- templates:保存所有的模板页面;(Spring Boot默认jar包使用嵌入式的Tomcat,默认不支持JSP页面);可以使用模板引擎(freemarker、thymeleaf);
- application.properties:Spring Boot应用的配置文件;可以修改一些默认设置
- resources文件夹中目录结构
2、配置文件
配置文件
- SpringBoot使用一个全局的配置文件,配置文件名是固定的;
- application.properties
- application.yml
- 作用:修改SpringBoot自动配置的默认值;SpringBoot在底层给我们自动配置好;
YAML语法:
1、基本语法
-
k:(空格)v:表示一对键值对(空格必须有);
-
以空格的缩进来控制层级关系;只要是左对齐的一列数据,都是同一个层级的
-
属性和值也是大小写敏感
server: port: 8081
2、值的写法
字面量:普通的值(数字,字符串,布尔)
- k: v:字面直接来写;
- 字符串默认不用加上单引号或者双引号;
- “”:双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思
- name: “zhangsan \n lisi”:输出;zhangsan 换行 lisi
- ‘’:单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据
- name: ‘zhangsan \n lisi’:输出;zhangsan \n lisi
对象、Map(属性和值)(键值对):
-
k: v:在下一行来写对象的属性和值的关系;注意缩进
- 对象还是k: v的方式
friends: lastName: zhangsan age: 20
-
行内写法:
friends: {lastName: zhangsan,age: 18}
数组(List、Set):
-
用- 值表示数组中的一个元素
pets: - cat - dog
-
行内写法
pets: [cat,dog]
配置文件值注入
步骤(三步)
第一步:编写配置文件(application.yml)
person:
username: fzk
password: 123
lists:
- fff
- zzz
- kkk
maps:
k1: v1
k2: v2
第二步:编写javaBean类(Person.java)
/**
* 将配置文件中配置的每一个属性的值,映射到这个组件中
* @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定;
* prefix = "person":配置文件中哪个下面的所有属性进行一一映射
* 只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能;
*/
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String username;
private String password;
private List<String> lists;
private Map<String, String> maps;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public List<String> getLists() {
return lists;
}
public void setLists(List<String> lists) {
this.lists = lists;
}
public Map<String, String> getMaps() {
return maps;
}
public void setMaps(Map<String, String> maps) {
this.maps = maps;
}
@Override
public String toString() {
return "Person{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", lists=" + lists +
", maps=" + maps +
'}';
}
}
第三步:导入配置文件处理器,以后编写配置就有提示了
<!--导入配置文件处理器,配置文件进行绑定就会有提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
@Value获取值和@ConfigurationProperties获取值比较
@ConfigurationProperties | @Value | |
---|---|---|
功能 | 批量注入配置文件中的属性 | 一个个指定 |
松散绑定(松散语法) | 支持 | 不支持 |
SpEL | 不支持 | 支持 |
JSR303数据校验 | 支持 | 不支持 |
复杂类型封装 | 支持 | 不支持 |
- 配置文件yml还是properties他们都能获取到值;
- 只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value;
- 专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties;
配置文件注入值数据校验
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
@Email //username必须是邮箱格式
private String username;
private String password;
private List<String> lists;
private Map<String, String> maps;
@PropertySource、@ImportResource、@Bean
@PropertySource:加载指定的配置文件;
@PropertySource(value = {"classpath:person.properties"})
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
}
@ImportResource:导入Spring的配置文件,让配置文件里面的内容生效;
- Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别;
- 想让Spring的配置文件生效,加载进来;@ImportResource标注在一个配置类上
@ImportResource(locations = {"classpath:beans.xml"})
导入Spring的配置文件让其生效
- SpringBoot推荐给容器中添加组件的方式;推荐使用全注解的方式
@Bean
- 配置类**@Configuration**------>Spring配置文件
- 使用**@Bean**给容器中添加组件
/**
* @Configuration:指明当前类是一个配置类;就是来替代之前的Spring配置文件
* 在配置文件中用<bean><bean/>标签添加组件
*/
@Configuration
public class MyAppConfig {
//将方法的返回值添加到容器中;容器中这个组件默认的id就是方法名
@Bean
public HelloService Service(){
return new HelloService();
}
}
配置文件占位符
随机数
${random.value}、${random.int}、${random.long}
${random.int(10)}、${random.int[1024,65536]}
占位符获取之前配置的值,如果没有可以是用:指定默认值
person.last-name=张三${random.uuid}
person.age=${random.int}
person.birth=2017/12/15
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
person.dog.name=${person.hello:hello}_dog
person.dog.age=15
Profile
多Profile文件
- 我们在主配置文件编写的时候,文件名可以是 application-{profile}.properties/yml
- 默认使用application.properties的配置;
yml支持多文档块方式
server:
port: 8001
spring:
profiles:
active: fff #指定属于哪个环境
---
server:
port: 8002
spring:
profiles: fff
---
server:
port: 8003
spring:
profiles: zzz
激活指定profile
- 1、在配置文件中指定 spring.profiles.active=fff
- 2、命令行:
- java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev;
- 可以直接在测试的时候,配置传入命令行参数
- 3、虚拟机参数;
- -Dspring.profiles.active=dev
配置文件加载位置
- springboot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件
- –file:./config/ (根目录下的 config 目录下的配置文件)
- –file:./ (根目录下的配置文件)
- –classpath:/config/ (resources目录下的 config 目录下的配置文件)
- –classpath:/ (resources 目录下的配置文件)
- 优先级由高到底,高优先级的配置会覆盖低优先级的配置;
- SpringBoot会从这四个位置全部加载主配置文件;互补配置;
- 我们还可以通过spring.config.location来改变默认的配置文件位置
- 项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;指定配置文件和默认加载的这些配置文件共同起作用形成互补配置;
- java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.location=G:/application.properties
- 项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;指定配置文件和默认加载的这些配置文件共同起作用形成互补配置;
外部配置加载顺序
- SpringBoot也可以从以下位置加载配置; 优先级从高到低;高优先级的配置覆盖低优先级的配置,所有的配置会形成互补配置
- 命令行参数
- 所有的配置都可以在命令行上进行指定
- java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc
- 多个配置用空格分开; --配置项=值
- 所有的配置都可以在命令行上进行指定
- 来自java:comp/env的JNDI属性
- Java系统属性(System.getProperties())
- 操作系统环境变量
- RandomValuePropertySource配置的random.*属性值
- jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件
- 先加载带有 profile 的配置文件
- jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
- 先加载带有 profile 的配置文件
- jar包外部的application.properties或application.yml(不带spring.profile)配置文件
- 先加载带有 profile 的配置文件,再加载不带 profile 的配置文件
- jar包内部的application.properties或application.yml(不带spring.profile)配置文件
- 先加载带有 profile 的配置文件,再加载不带 profile 的配置文件
- @Configuration注解类上的@PropertySource
- 通过SpringApplication.setDefaultProperties指定的默认属性
3、日志
推荐观看: https://blog.csdn.net/qq_44002865/article/details/106105533
日志框架
- 市面上的日志框架;
- JUL、JCL、Jboss-logging、logback、log4j、log4j2、slf4j…
日志门面 (日志的抽象层) | 日志实现 |
---|---|
SLF4j(Simple Logging Facade for Java) | Log4j JUL(java.util.logging) Log4j2 Logback |
- 左边选一个门面(抽象层)、右边来选一个实现
- 日志门面:SLF4J
- 日志实现:Logback
- SpringBoot:底层是Spring框架,Spring框架默认是用JCL
- SpringBoot选用 SLF4j和logback
SLF4j使用
在系统中使用SLF4j
-
官方参考文档:https://www.slf4j.org
-
以后开发的时候,日志记录方法的调用,不应该来直接调用日志的实现类,而是调用日志抽象层里面的方法
-
给系统里面导入slf4j的jar和 logback的实现jar
import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class HelloWorld { public static void main(String[] args) { Logger logger = LoggerFactory.getLogger(HelloWorld.class); logger.info("Hello World"); } }
-
图示
- 每一个日志的实现框架都有自己的配置文件。使用slf4j以后,配置文件还是做成日志实现框架自己本身的配置文件;
遗留问题
-
如何让系统中所有的日志都统一到slf4j;
-
1、将系统中其他日志框架先排除出去
-
2、用中间包来替换原有的日志框架
-
3、我们导入slf4j其他的实现
-
日志使用:
日志级别
-
由低到高:trace < debug < info < warn < error
-
可以调整输出的日志级别,日志就只会在这个级别及更高级别生效
-
SpringBoot 默认使用的是 info 级别
-
SpringBoot默认帮我们配置好了日志
//记录器 Logger logger = LoggerFactory.getLogger(getClass()); @Test public void contextLoads() { logger.trace("这是trace日志..."); logger.debug("这是debug日志..."); //SpringBoot默认使用的是info级别的,没有指定级别的就用SpringBoot默认规定的级别 logger.info("这是info日志..."); logger.warn("这是warn日志..."); logger.error("这是error日志..."); }
-
修改日志的默认级别(application.properties)
#com.itfzk.springboot_test:项目的权限定包名 #trace:修改日志级别为 trace logging.level.com.itfzk.springboot_test=trace
日志输出位置(application.properties)
-
写入指定的日志文件
-
名称可以是确切的位置,也可以相对于当前目录
logging.file.name=springboot.log
-
-
写入spring.log指定的目录
-
名称可以是确切的位置,也可以相对于当前当前磁盘的目录
logging.file.path=/springboot/fzk
-
自定义日志的配置
日志输出格式
%d :日期时间
%thread :线程名
%-5level :级别从左显示5个字符宽度
%logger{50} :logger名字最长50个字符,否则按照句点分割。
%msg: :日志消息,
%n :换行符
控制台上要使用的日志模式
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
文件中使用的日志模式
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} === [%thread] === %-5level === %logger{50} === - %msg%n
指定配置
- 给类路径下放上每个日志框架自己的配置文件即可;SpringBoot就不使用他默认配置的了
Logging System | Customization |
---|---|
Logback | logback-spring.xml, logback-spring.groovy, logback.xmlor logback.groovy |
Log4j2 | log4j2-spring.xmlor log4j2.xml |
JDK (Java Util Logging) | logging.properties |
-
logback.xml:直接就被日志框架识别了;
-
logback-spring.xml:日志框架就不直接加载日志的配置项,由SpringBoot解析日志配置,可以使用SpringBoot的高级Profile功能
<springProfile name="staging">
<!-- configuration to be enabled when the "staging" profile is active -->
可以指定某段配置只在某个环境下生效
</springProfile>
4、Web开发
SpringBoot对静态资源的映射规则
-
**1、所有 /webjars/ ,都去 classpath:/META-INF/resources/webjars/ 找资源
- webjars:以jar包的方式引入静态资源
- 导入配置
<!--引入jquery-webjar-->在访问的时候只需要写webjars下面资源的名称即可 <dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId> <version>3.4.1</version> </dependency>
- 访问:http://www.localhost:8080/webjars/jquery/3.4.1/jquery.js
-
2、"/**" 访问当前项目的任何资源,都去(静态资源的文件夹)找映射
- 优先级:由高到低
- “classpath: /META-INF/resources/”
- “classpath:/resources/”
- “classpath:/static/”
- “classpath: /public/”
- 优先级:由高到低
-
**3、欢迎页; 静态资源文件夹下的所有index.html页面;被"/"映射
-
localhost:8080/ 找index页面
-
**4、**所有的 **/favicon.ico 都是在静态资源文件下找
模板引擎
- JSP、Velocity、Freemarker、Thymeleaf
- SpringBoot推荐的Thymeleaf
- 参考手册:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html
引入thymeleaf
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Thymeleaf使用
- 禁用模板引擎的缓存
- 修改完页面,不用重新启动Tomcat
- spring.thymeleaf.cache=false
参考手册:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html
package org.springframework.boot.autoconfigure.thymeleaf;
@ConfigurationProperties(prefix = "spring.thymeleaf")
public class ThymeleafProperties {
private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;
public static final String DEFAULT_PREFIX = "classpath:/templates/"; //前缀
public static final String DEFAULT_SUFFIX = ".html"; //后缀
-
把HTML页面放在classpath:/templates/,thymeleaf自动渲染
-
使用:
-
1、导入thymeleaf的名称空间
<html lang="en" xmlns:th="http://www.thymeleaf.org">
-
2、使用thymeleaf语法;
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!-- thyeleaf的使用 --> <p th:value="fzk"></p> </body> </html>
-
3、编写Controller类
@Controller public class thymeleafController { @ResponseBody @RequestMapping(path = "toThymeleaf") public String toThymeleaf(){ return "thymeleaf"; } }
-
标准语法规则
参考手册:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html
- th: 任意html属性;来替换原生属性的值
th: 使用的优先级
表达语法
- 简单表达式:
- 变量表达式:
${...}
- 选择变量表达式:
*{...}
- 消息表达:
#{...}
- 链接URL表达式:
@{...}
- 片段表达式:
~{...}
- 变量表达式:
- 文字
- 文本文字:
'one text'
,'Another one!'
,… - 号码文字:
0
,34
,3.0
,12.3
,… - 布尔文字:
true
,false
- 空文字:
null
- 文字标记:
one
,sometext
,main
,…
- 文本文字:
- 文字操作:
- 字符串串联:
+
- 文字替换:
|The name is ${name}|
- 字符串串联:
- 算术运算:
- 二元运算符:
+
,-
,*
,/
,%
- 减号(一元运算符):
-
- 二元运算符:
- 布尔运算:
- 二元运算符:
and
,or
- 布尔否定(一元运算符):
!
,not
- 二元运算符:
- 比较和平等:
- 比较:
>
,<
,>=
,<=
(gt
,lt
,ge
,le
) - 等号运算符:
==
,!=
(eq
,ne
)
- 比较:
- 条件运算符:
- 如果-则:
(if) ? (then)
- 如果-则-否则:
(if) ? (then) : (else)
- 默认:
(value) ?: (defaultvalue)
- 如果-则:
- 特殊令牌:
- 无操作:
_
- 无操作:
SpringMVC自动配置
https://docs.spring.io/spring-boot/docs/2.2.6.RELEASE/reference/htmlsingle/#boot-features-spring-mvc
Spring MVC auto-configuration
Spring Boot 自动配置好了SpringMVC
以下是SpringBoot对SpringMVC的默认配置:(WebMvcAutoConfiguration)
- 包含
ContentNegotiatingViewResolver
和BeanNameViewResolver
。 - 支持服务静态资源,包括对WebJars的支持
- 自动注册
Converter
,GenericConverter
和Formatter
豆类。 - 支持
HttpMessageConverters
- 自动注册
MessageCodesResolver
- 静态
index.html
支持。 - 定制
Favicon
支持 - 自动使用
ConfigurableWebBindingInitializer
bean
扩展SpringMVC
xml配置视图映射方法
<mvc:view-controller path="/hello" view-name="success"/>
配置类(@Configuration)方法,是 WebMvcConfigurer 类型;不能标注@EnableWebMvc;
- 既保留了所有的自动配置,也能用我们扩展的配置;
方法一:重写 WebMvcConfigurer 的 addViewControllers 方法(不推荐使用)
@Configuration
public class My implements WebMvcConfigurer {
//添加视图映射
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//浏览器发送/fzk123,将跳转到 /templates/success.html页面
registry.addViewController("/fzk123").setViewName("success");
}
}
方法二:使用 Bean 注入 WebMvcConfigurer,修改 WebMvcConfigurer 配置(推荐使用)
@Configuration
public class My implements WebMvcConfigurer {
//所有的 WebMvcConfigurer 组件到会一起起作用
@Bean //将组件注入容器中
public WebMvcConfigurer webMvcConfigurer(){
WebMvcConfigurer configurer = new WebMvcConfigurer() {
//添加视图映射
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//浏览器发送/fzk123,将跳转到 /templates/success.html页面
registry.addViewController("/fzk123").setViewName("success");
}
};
return configurer;
}
}
全面接管SpringMVC
-
SpringBoot对SpringMVC的自动配置不需要了
-
我们需要在配置类中添加@EnableWebMvc
@EnableWebMvc @Configuration public class My implements WebMvcConfigurer { //添加视图映射 @Override public void addViewControllers(ViewControllerRegistry registry) { //浏览器发送/fzk123,将跳转到 /templates/success.html页面 registry.addViewController("/fzk123").setViewName("success"); } }
如何修改SpringBoot的默认配置
- SpringBoot在自动配置很多组件的时候,先看容器中有没有自己配置的(@Bean、@Component)如果有就用用户配置的,如果没有,才自动配置;如果有些组件可以有多个(ViewResolver)将用户配置的和自己默认的组合起来
- 在SpringBoot中会有非常多的xxxConfigurer帮助我们进行扩展配置
- 在SpringBoot中会有很多的xxxCustomizer帮助我们进行定制配置
拦截器进行登陆检查
注册拦截器功能
@Configuration
public class My implements WebMvcConfigurer {
@Bean //将组件注入容器中
public WebMvcConfigurer webMvcConfigurer(){
WebMvcConfigurer configurer = new WebMvcConfigurer() {
/**
* 添加拦截器
* 以 LoginHandlerInterceptor 方法为前提
* addPathPatterns("/**"):拦截所有
* excludePathPatterns("/", "/index.html", "/user/login", "/static/**", "/webjars/**"):
* 不拦截:"/", "/index.html", "/user/login", "/static/**", "/webjars/**"
* "/user/login" :Controller下的方法
* "/static/**" :自己编写的静态资源
* "/webjars/**" :webjars包的内容
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**")
.excludePathPatterns("/", "/index.html", "/user/login", "/static/**", "/webjars/**");
}
};
return configurer;
}
}
拦截器
public class LoginHandlerInterceptor implements HandlerInterceptor {
//目标方法执行之前
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Object username = request.getSession().getAttribute("username");
if(username == null){
//未登录
//不放行
request.setAttribute("info", "请先登录");
//转发到相应的页面
request.getRequestDispatcher("/index.html").forward(request, response);
return false;
}else{
//已登录
//放行
return true;
}
}
//目标方法执行之后
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
//网页执行之后
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
错误处理机制
- 一但系统出现4xx或者5xx之类的错误;ErrorPageCustomizer就会生效(定制错误的响应规则);就会来到/error请求;就会被BasicErrorController处理;
定制错误的页面
-
有模板引擎的情况下:
-
error/状态码: (error/404)(状态码:错误数(400, 404,405, 500…))
- 1、精准状态码:
- 将错误页面命名为错误 状态码.html 放在模板引擎文件夹里面的error文件夹下, 发生此状态码的错误就会来到对应的页面;
- 2、模糊状态码:
- 我们可以使用4xx和5xx作为错误页面的文件名来匹配这种类型的所有错误,精确优先(优先寻找精确的状态码.html) ;
- 1、精准状态码:
-
2、页面能获取的信息:
timestamp :时间戳
status :状态码
error :错误提示
exception :异常对象
message :异常消息
errors : JSR303数据校验的错误都在这里
-
-
没有模板引擎(模板引擎找不到这个错误页面),静态资源文件夹下找
-
以上都没有错误页面,就是默认来到SpringBoot默认的错误提示页面;
如何定制错误的json数据;
1)、自定义异常处理&返回定制json数据;
@ControllerAdvice
public class MyExceptionHandler {
@ResponseBody
@ExceptionHandler(UserNotExistException.class)
public Map<String,Object> handleException(Exception e){
Map<String,Object> map = new HashMap<>();
map.put("code","user.notexist");
map.put("message",e.getMessage());
return map;
}
}
//没有自适应效果...
2)、转发到/error进行自适应响应效果处理
@ExceptionHandler(UserNotExistException.class)
public String handleException(Exception e, HttpServletRequest request){
Map<String,Object> map = new HashMap<>();
//传入我们自己的错误状态码 4xx 5xx,否则就不会进入定制错误页面的解析流程
/**
* Integer statusCode = (Integer) request
.getAttribute("javax.servlet.error.status_code");
*/
request.setAttribute("javax.servlet.error.status_code",500);
map.put("code","user.notexist");
map.put("message",e.getMessage());
//转发到/error
return "forward:/error";
}
配置嵌入式Servlet容器
- SpringBoot默认使用Tomcat作为嵌入式的Servlet容器
定制和修改Servlet容器的相关配置;
1、修改和server有关的配置(ServerProperties【也是webServerFactoryCustomizer】)
server.port=8080
server.context-path=/crud
server.tomcat.uri-encoding=UTF-8
#通用的Servlet容器设置
server.xxx
#Tomcat的设置
server.tomcat.xxx
2、编写一个webServerFactoryCustomizer:嵌入式的Servlet容器的定制器;来修改Servlet容器的配置
@Configuration
public class ServletConfig {
/**
* 嵌入式的Servlet容器的定制器,来修改Servlet容器的配置
*/
@Bean //将这个定制器加入到容器中
public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer(){
return new WebServerFactoryCustomizer<ConfigurableWebServerFactory>() {
@Override
public void customize(ConfigurableWebServerFactory factory) {
//修改端口号为 8000
factory.setPort(8000);
}
};
}
}
注册Servlet三大组件【Servlet、Filter、Listener】
注册Servlet组件,ServletRegistrationBean
/**
* 注册Servlet组件
*/
@Bean
public ServletRegistrationBean<Servlet> myServlet(){
//new MyServlet() :需要注册的Servlet类
//"/myservlet" :映射路径
ServletRegistrationBean<Servlet> servletServletRegistrationBean = new ServletRegistrationBean<Servlet>(new MyServlet(), "/myServlet");
return servletServletRegistrationBean;
}
注册Filter组件 , FilterRegistrationBean
/**
* 注册Filter组件
*/
@Bean
public FilterRegistrationBean<Filter> myFilter(){
FilterRegistrationBean<Filter> filterFilterRegistrationBean = new FilterRegistrationBean<Filter>();
//需要注册的Filter类
filterFilterRegistrationBean.setFilter(new MyFilter());
//需要拦截的映射路径
filterFilterRegistrationBean.setUrlPatterns(Arrays.asList("/myFilter"));
return filterFilterRegistrationBean;
}
注册Listener组件 , ServletListenerRegistrationBean
/**
* 注册Listener组件
*/
@Bean
public ServletListenerRegistrationBean myListener(){
ServletListenerRegistrationBean<EventListener> servletListenerRegistrationBean = new ServletListenerRegistrationBean<EventListener>();
//监听的类
servletListenerRegistrationBean.setListener(new MyListener());
return servletListenerRegistrationBean;
}
替换为其他嵌入式Servlet容器
- 容器:
- Tomcat (默认)
- Jetty
- Undertow
Tomcat(默认使用)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
引入web模块默认就是使用嵌入式的Tomcat作为Servlet容器;
</dependency>
Jetty
<!-- 引入web模块 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<!--引入其他的Servlet容器-->
<dependency>
<artifactId>spring-boot-starter-jetty</artifactId>
<groupId>org.springframework.boot</groupId>
</dependency>
Undertow
<!-- 引入web模块 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<!--引入其他的Servlet容器-->
<dependency>
<artifactId>spring-boot-starter-undertow</artifactId>
<groupId>org.springframework.boot</groupId>
</dependency>
使用外置的Servlet容器
- 嵌入式Servlet容器:应用打成可执行的jar
- 优点:简单、便携;
- 缺点:默认不支持JSP、优化定制比较复杂
- 外置的Servlet容器:外面安装Tomcat—应用war包的方式打包;
步骤
第一步:创建一个war项目;(利用idea创建好目录结构)
第二步:将嵌入式的Tomcat指定为provided;
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
第三步:编写一个SpringBootServletInitializer的子类,并调用configure方法
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
//传入SpringBoot应用的主程序
return application.sources(SpringBoot04WebJspApplication.class);
}
}
第四步:启动服务器就可以使用;
5、SpringBoot与数据访问
JDBC
引入配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
在 application.properties 中加入 JDBC 的 DataSource 配置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
- 效果:
- 默认是用 com.zaxxer.hikari.HikariDataSource 作为数据源
- 自动配置原理:
- org.springframework.boot.autoconfigure.jdbc:
- 参考DataSourceConfiguration,根据配置创建数据源,默认使用Tomcat连接池;可以使用spring.datasource.type指定自定义的数据源类型
- SpringBoot默认可以支持
- com.zaxxer.hikari.HikariDataSource(默认)
- org.apache.tomcat.jdbc.pool.DataSource
- org.apache.commons.dbcp2.BasicDataSource
- 自定义数据源类型
/**
* Generic DataSource configuration
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type")
static class Generic {
@Bean
DataSource dataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().build();
}
}
- 默认只需要将文件命名为:
schema-*.sql、data-*.sql
默认规则:schema.sql,schema-all.sql;
可以使用
schema:
- classpath:department.sql
指定位置
-
操作数据库:自动配置了JdbcTemplate操作数据库
@Autowired DataSource dataSource; @Autowired JdbcTemplate jdbcTemplate; @Test void contextLoads() { try { System.out.println(dataSource.getClass()); System.out.println(dataSource.getConnection()); List<Map<String, Object>> maps = jdbcTemplate.queryForList("select * from test"); System.out.println(maps); dataSource.getConnection().close(); } catch (SQLException e) { e.printStackTrace(); } }
整合Druid数据源
第一步:引入配置(pom.xml)
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.20</version>
</dependency>
第二步:配置数据源(在 application.properties 文件添加配置)
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
#若只是这样配置,下面的配置不会生效,要想生效需配置 Druid 的配置文件 @Configuration
spring.datasource.initialSize=5
spring.datasource.maxActive=20
spring.datasource.minIdle=5
第三步:编写配置文件 @Configuration 使 Druid 生效
@Configuration
public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druid(){
return new DruidDataSource();
}
//配置Druid的监控
//1、配置一个管理后台的Servlet
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
Map<String,String> initParams = new HashMap<>();
initParams.put("loginUsername","admin");
initParams.put("loginPassword","123456");
initParams.put("allow","");//默认就是允许所有访问
initParams.put("deny","192.168.15.21");
bean.setInitParameters(initParams);
return bean;
}
//2、配置一个web监控的filter
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
Map<String,String> initParams = new HashMap<>();
initParams.put("exclusions","*.js,*.css,/druid/*");
bean.setInitParameters(initParams);
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
}
整合MyBatis
步骤
-
第一步:引入配置
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.0.1</version> </dependency>
-
第二步:配置数据源相关属性(再上一节 Druid 的 application.properties 文件下添加配置)
# Mapper 资源文件存放的路径(classpath表示:存放在resource路径下,classpath后面的是自定义路径) mybatis.mapper-locations=classpath:xxx/xxx/*.xml # 自动加载实体类(实体类路径) mybatis.type-aliases-package=com.itfzk.entity
-
第三步:创建JavaBean
-
第四步:注解版
@Mapper @Repository("userDaoMyBatis") public interface IUserDaoMyBatis { //查询所有信息 @Select("select * from test") public List<User> findAllMyBatis(); //根据 id 查询信息 @Select("select * from test where userId=#{userId}") public User findByIdMyBatis(int userId); //添加信息 @Insert("insert into test(userName) value(#{userName})") public void saveMyBatis(String userName); //修改 @Update("update test set userName=#{userName} where userId=#{userId}") public void updateMyBatis(User user); //根据 id来删除信息 @Delete("delete from test where userId=#{userId}") public void deleteMyBatis(int userId); }
更多使用参照
http://www.mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/
整合SpringData JPA
JPA:ORM(Object Relational Mapping);
1)、编写一个实体类(bean)和数据表进行映射,并且配置好映射关系;
//使用JPA注解配置映射关系
@Entity //告诉JPA这是一个实体类(和数据表映射的类)
@Table(name = "tbl_user") //@Table来指定和哪个数据表对应;如果省略默认表名就是user;
public class User {
@Id //这是一个主键
@GeneratedValue(strategy = GenerationType.IDENTITY)//自增主键
private Integer id;
@Column(name = "last_name",length = 50) //这是和数据表对应的一个列
private String lastName;
@Column //省略默认列名就是属性名
private String email;
2)、编写一个Dao接口来操作实体类对应的数据表(Repository)
//继承JpaRepository来完成对数据库的操作
public interface UserRepository extends JpaRepository<User,Integer> {
}
3)、基本的配置JpaProperties
spring:
jpa:
hibernate:
# 更新或者创建数据表结构
ddl-auto: update
# 控制台显示SQL
show-sql: true