SpringBoot核心功能
- 二、SpringBoot核心功能
- 1、配置文件
- 1.1、properties文件
- 1.2、yml文件
- 1.2.1、简介
- 1.2.2、基本语法
- 1.2.3、数据类型
- 1.2.4、配置提示
- 2、Web开发
- 2.1、SpringBoot中SpringMVC自动配置
- 2.2、功能分析
- 1、静态资源目录
- 2、静态资源访问前缀
- 3、支持webjars
- 4、欢迎页支持
- 5、自定义Favicon
- 6、普通参数与基本注解
- 7、视图解析与模板引擎
- 视图解析:SpringBoot默认不支持jsp,需要引入第三方模板引擎技术实现页面渲染
- thymeleaf模板引擎
- 8、拦截器
- 1、HandlerInterceptor接口
- 2、配置拦截器
- 3、验证拦截器
- 9、文件上传
- 10、Web原生组件的注入(Servlet、Filter、Listener)
- 1、使用Servlet API
- 2、RegistrationBean
- 11、定制化SpringMVC原理
- 1、定制化的常见方式
- web应用 编写一个自定义类实现WebMvcConfigurer接口定制web功能 ;(推荐使用)+ @Bean 给容器中扩展组件
- 2、定制化原理
- 3、数据访问
- 1、SQL
- 1、数据源的自动配置 HikariDataSource
- 2、使用Druid数据源
- 1、druid官方github地址
- 2、自定义方式
- 3、引入starter官方场景
- 3、整合MyBatis操作
- 3.1纯配置方式
- 3.2纯注解版
- 3.3混合版
- 4、SpringBoot整合mybatis-plus
- 4、单元测试
- 1、Junit5常用注解
- 2、SpringBoot整合Junit
- 5、原理解析
- 1、application-profile功能
- 2、@Profile条件装配功能
- 3、profile分组
二、SpringBoot核心功能
1、配置文件
1.1、properties文件
1.2、yml文件
1.2.1、简介
YAML 是 “YAML Ain’t Markup Language”(YAML 不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:“Yet Another Markup Language”(仍是一种标记语言)。
非常适合用来做以数据为中心的配置文件
1.2.2、基本语法
- key: value;kv之间有空格
- 大小写敏感
- 使用缩进表示层级关系
- 缩进不允许使用tab,只允许空格
- 缩进的空格数不重要,只要相同层级的元素左对齐即可
- '#'表示注释
- 字符串无需加引号,如果要加,’'与""表示字符串内容 会被 转义/不转义
1.2.3、数据类型
- 字面量:单个的、不可再分的值。date、boolean、string、number、null
k: v
- 对象:键值对的集合。map、hash、set、object
行内写法: k: {k1: v1,k2: v2,k3: v3}
#或
k:
k1: v1
k2: v2
k3: v3
- 数组:一组按次序排列的值。array、list、queue
行内写法: k: [v1,v2,v3]
#或者
k:
- v1
- v2
- v3
1.2.4、配置提示
自定义类绑定的配置提示
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
2、Web开发
2.1、SpringBoot中SpringMVC自动配置
- 内容协商视图解析器(ContentNegotiatingViewResolver)和BeanName视图解析器(BeanNameViewResolver)
- 静态资源(包括webjars)
- 自动注册
Converter,GenericConverter,Formatter
- 支持
HttpMessageConverters
(后来我们配合内容协商理解原理) - 自动注册
MessageCodesResolver
(国际化用) - 静态index.html 页支持
- 自定义
Favicon
- 自动使用
ConfigurableWebBindingInitializer
,(DataBinder负责将请求数据绑定到JavaBean上)
2.2、功能分析
1、静态资源目录
只要静态资源放在类路径下:called/static
(or /public
or /resources
or /META-INF/resources
)
访问:当前项目根路径/+静态资源名
原理:静态资源映射:/**
请求进来,先去找Controller看能不能处理,不能处理则交给静态资源处理,如果静态资源也不能处理则404,。
修改默认的静态资源目录
spring:
resources:
static-locations: classpath:/haha/
2、静态资源访问前缀
spring:
mvc:
static-path-pattern: /res/**
访问静态资源:当前项目名+ static-path-pattern + 静态资源名 = 静态资源目录下寻找
3、支持webjars
自动映射:/webjars/**
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.6.0</version>
</dependency>
访问:http://localhost:8080/webjars/jquery/3.6.0/jquery.js
4、欢迎页支持
- 静态资源目录下index.html
- 可以是配置后的资源路径,但是不能配置静态资源访问前缀,会导致index.html不能访问
spring:
# mvc:
# static-path-pattern: /res/** 这个会导致welcome page 功能失效
resources:
static-locations: classpath:/haha/
- 也可以是默认的static静态资源目录下(没有配置)
- controller能处理的 /index 请求
5、自定义Favicon
将favicon.ico放在静态资源目录下即可。
#spring:
# mvc:
# static-path-pattern: /res/** 会导致这个 Favicon 功能失效
6、普通参数与基本注解
- 注解:
@PathVariable、@ReqestHeader、@RequestAttribute、@RequestParam、@MatrixVariable、@CookieVariable、@RequestBody
//@PathVariable、@ReqestHeader、@RequestParam、@CookieVariable 注解的使用
@RestController
public class ParameterTestController {
@GetMapping("/car/{id}/owner/{username}")
public Map<String,Object> getCar(@PathVariable("id") Integer id,
@PathVariable("username") String username,
@PathVariable Map<String,String> pv,
@RequestHeader("User-Agent") String userAgent,
@RequestHeader Map<String,String> header,
@RequestParam List<String> interests,
@RequestParam Map<String,Object> Param,
// @CookieValue("_ga") String _ga,
@CookieValue("_ga") Cookie cookie){
Map<String,Object> map = new HashMap<>();
// map.put("id",id);
// map.put("username",username);
// map.put("pv",pv);
// map.put("User-Agent",userAgent);
// map.put("header",header);
map.put("interests",interests);
map.put("Param",Param);
// map.put("_ga",_ga);
System.out.println(cookie.getName()+"===>"+cookie.getValue());
return map;
}
}
@RequestAttribute注解的使用
@Controller
public class RequestController {
@GetMapping("/goto")
public String goToPage(HttpServletRequest request){
request.setAttribute("msg","成功了....");
request.setAttribute("code",200);
return "forward:/success";
}
//模拟读取数据回显到页面
@ResponseBody
@GetMapping("/success")
public Map success(@RequestAttribute("msg") String msg,
@RequestAttribute("code") Integer code,
HttpServletRequest request){
Object msg1 = request.getAttribute("msg");
Map<String,Object> map = new HashMap<>();
map.put("HttpServletRequest_msg",msg1);
map.put("annotation_msg",msg);
map.put("code",code);
return map;
}
}
@RequestBody注解的使用
@RestController
public class ParameterTestController {
@PostMapping("/save")
public Map getFormValues(@RequestBody String content){ //获取表单的所有提交的值
Map<String,Object> map = new HashMap<>();
map.put("content",content);
return map;
}
}
@MatrixVariable注解的使用
@RestController
public class ParameterTestController {
//1、语法: /cars/sell;low=34;brand=zhangsan,lisi,wangwu
//2、SpringBoot默认是禁用掉了矩阵变量
// 手动开启:原理。对于路径的处理:UrlPathHelper
// RemoveSemicolonContent 移除分号后面的内容
//3、矩阵变量必须要有 url 路径变量 才能被解析
@GetMapping("/cars/{path}")
public Map matrixVariable(@MatrixVariable("low") String low,
@MatrixVariable("brand") List<String> brand,
@PathVariable("path") String path){
Map<String,Object> map = new HashMap<>();
map.put("low",low);
map.put("brand",brand);
map.put("path",path);
return map;
}
// /boss/1;age=30/2;age=18
@GetMapping("/boss/{bossId}/{empId}")
public Map boss(@MatrixVariable(value = "age",pathVar = "bossId") Integer bossAge,
@MatrixVariable(value = "age",pathVar = "empId") Integer empAge){
Map<String,Object> map = new HashMap<>();
map.put("bossAge",bossAge);
map.put("empAge",empAge);
return map;
}
}
对应的index.html首页
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
测试基本注解:
<ul>
<a href="car/3/owner/zhangsan?age=17&interests=basketball&interests=game">car/{id}/owner/{username}</a>
<li>@PathVariable(路径变量)</li>
<li>@RequestHeader(请求头)</li>
<li>@RequestParam(获取请求参数)</li>
<li>@CookieValue(获取cookie的值)</li>
<li>@RequestBody(获取请求体)</li>
<li>@RequestAttribute(获取request域属性)</li>
<li>@MatrixVariable(矩阵变量)</li>
</ul>
<form action="/save" method="post">
测试@RequestBody(获取请求体)<br/>
用户名:<input type="text" name="username"/><br/>
邮箱:<input name="email"/><br/>
<input type="submit" value="提交"/>
</form>
/cars/sell;low=34;brand=zhangsan;brand=lisi 矩阵变量<br/>
页面开发时,cookie被禁用掉了,怎么使用session中的内容;<br/>
session.set(a,b)---> jssessionid ---> cookie ---> 每次发请求携带<br/>
url重写:/abc;jssessionid=xxx 把cookie的值使用矩阵变量的形式传递<br/>
<a href="/cars/sell;low=34;brand=zhangsan,lisi,wangwu">@MatrixVariable(矩阵变量)</a><br/>
<a href="/cars/sell;low=34;brand=zhangsan;brand=lisi;brand=wangwu">@MatrixVariable(矩阵变量)</a><br/>
<a href="/boss/1;age=30/2;age=18">@MatrixVariable(矩阵变量)</a><br/>
</body>
</html>
7、视图解析与模板引擎
视图解析:SpringBoot默认不支持jsp,需要引入第三方模板引擎技术实现页面渲染
视图处理方式:转发、重定向、自定义视图
thymeleaf模板引擎
使用方法:
1、引入thymeleaf的starter场景
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
2、在默认的目录templates下,创建html页面并引入名称空间
<html xmlns:th="http://www.thymeleaf.org">
例:success.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 th:text="${msg}">哈哈</h1>
<h2><a href="www.baidu.com" th:href="${link}"/>我的博客</h2>
<h2><a href="www.baidu.com" th:href="@{link}"/>我的博客2</h2>
</body>
</html>
相应的处理器:ViewController
@Controller
public class ViewController {
@GetMapping("/page")
public String toPage(Model model){
model.addAttribute("msg","成功了....");
model.addAttribute("link","https://www.tainfei.top/");
return "success";
}
}
8、拦截器
1、HandlerInterceptor接口
2、配置拦截器
/**
* 登录检测
* 拦截器:
* 1、配置拦截器要拦截哪些
* 2、拦截器添入容器中
*
* @author: Herz
* @date: 2021/5/28 9:23
*/
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
/**
* 目标方法执行之前
*
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String requestURI = request.getRequestURI();
log.info("preHandle 拦截的请求路径:" + requestURI);
//登录检查逻辑
HttpSession session = request.getSession();
Object attribute = session.getAttribute("loginUser");
if (attribute != null) {
//放行
return true;
} else {
//拦截住,未登录
// session.setAttribute("msg", "请先登录");
request.setAttribute("msg","请先登录");
//跳转登录页
// response.sendRedirect("/"); //重定向取不到session 域中得值
request.getRequestDispatcher("/").forward(request,response);
return false;
}
}
/**
* 目标方法执行之后
*
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("postHandle的ModelAndView{}",modelAndView);
}
/**
* 页面渲染以后
*
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("afterCompletion异常:",ex);
}
}
将拦截器注册到容器中
/**
* 1、编写一个拦截器实现 HandlerInterceptor 接口
* 2、拦截器注册到容器中(实现 WebMvcConfigurer 接口的 addInterceptors 方法)
* 3、指定拦截器规则【如果是拦截所有请求,静态资源的访问也会被拦截】
*
*
* @author: Herz
* @date: 2021/5/28 10:17
*/
@Configuration
public class AdminWebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**") //拦截的请求路径,静态资源访问也被拦截
.excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**"); //不拦截的请求路径
}
}
3、验证拦截器
9、文件上传
@Slf4j
@Controller
public class FormTestController {
/**
* 自动封装上传过来的文件
* @param email
* @param username
* @param headerImg
* @param photos
* @return
* @throws IOException
*/
@PostMapping("/upload")
public String uploads(@RequestParam("email") String email,
@RequestParam("username") String username,
@RequestParam("headerImg") MultipartFile headerImg,
@RequestParam("photos") MultipartFile[] photos) throws IOException {
log.info("上传的信息:email={},username={},headerImg={},Photos={}",email,username,headerImg.getSize(),photos.length);
if (!headerImg.isEmpty()){
//上传到文件服务器,OSS服务器
String originalFilename = headerImg.getOriginalFilename();
headerImg.transferTo(new File("F:\\FormTest\\"+originalFilename));
}
for (MultipartFile photo : photos) {
if (!photo.isEmpty()){
String originalFilename = photo.getOriginalFilename();
photo.transferTo(new File("F:\\FormTest\\"+originalFilename));
}
}
return "main";
}
@GetMapping("/form_layouts")
public String form_layouts(){
return "form/form_layouts";
}
}
对应的文件上传表单
<form role="form" th:action="@{/upload}" method="post" enctype="multipart/form-data">
<div class="form-group">
<label for="exampleInputEmail1">邮箱</label>
<input type="email" class="form-control" name="email" id="exampleInputEmail1" placeholder="Enter email">
</div>
<div class="form-group">
<label for="exampleInputUsername1">姓名</label>
<input type="text" class="form-control" name="username" id="exampleInputUsername1" placeholder="username">
</div>
<div class="form-group">
<label for="exampleInputFile">头像</label>
<input type="file" id="exampleInputFile" name="headerImg">
</div>
<div class="form-group">
<label for="InputFiles">生活照</label>
<input type="file" id="InputFiles" name="photos" multiple>
</div>
<div class="checkbox">
<label>
<input type="checkbox"> Check me out
</label>
</div>
<button type="submit" class="btn btn-primary">提交</button>
</form>
配置文件上传的大小与总的请求大小
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=100MB
10、Web原生组件的注入(Servlet、Filter、Listener)
1、使用Servlet API
Servlet
@WebServlet(urlPatterns = "/my") //效果:直接响应,没有经过拦截器
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("666666");
}
}
@ServletComponentScan(basePackages = "com.tianfei.admin") //指明原生Servlet组件放在哪里
@SpringBootApplication
public class Boot04WebAdminApplication {
public static void main(String[] args) {
SpringApplication.run(Boot04WebAdminApplication.class, args);
}
}
Filter
@Slf4j
@WebFilter(urlPatterns = {"/css/*","/images/*"})
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("MyFilter初始化");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("方法被过滤");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
log.info("MyFilter销毁");
}
}
Listener
@Slf4j
@WebListener
public class MyContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
log.info("MyContextListener监听到项目初始化完成");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
log.info("MyContextListener监听到项目销毁");
}
}
注意:需要在SpringBoot的主方法上添加 @ServletComponentScan(basePackages = “com.tianfei.admin”) //指明原生Servlet组件放在哪里
2、RegistrationBean
自定义一个Servlet
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("666666");
}
}
自定义一个Filter
@Slf4j
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("MyFilter初始化");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("MyFilter工作");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
log.info("MyFilter销毁");
}
}
自定义一个Listener
@Slf4j
public class MyContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
log.info("MyContextListener监听到项目初始化完成");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
log.info("MyContextListener监听到项目销毁");
}
}
使用RegistrationBean注册到容器中
//(proxyBeanMethods = true):保证依赖的组件始终是单实例的
@Configuration(proxyBeanMethods = true)
public class MyRegisterConfig {
@Bean
public ServletRegistrationBean getServlet(){
MyServlet myServlet = new MyServlet();
return new ServletRegistrationBean(myServlet,"/my","/my02");
}
@Bean
public FilterRegistrationBean getFilter(){
// return new FilterRegistrationBean(new MyFilter(),getServlet()); //过滤路径和 getServlet()映射路径相同
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new MyFilter());
filterRegistrationBean.setUrlPatterns(Arrays.asList("/my","/css/*"));
return filterRegistrationBean;
}
@Bean
public ServletListenerRegistrationBean getListener(){
return new ServletListenerRegistrationBean(new MyContextListener());
}
}
11、定制化SpringMVC原理
1、定制化的常见方式
- 修改配置文件;
- 编写自定义配置类 xxxxConfiguration; + @Bean替换、增加容器中得组件;视图解析器;
- 编写自定义类 xxxCustomizer
@Component
public class MyWebServerFactoryCustomizer implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
@Override
public void customize(ConfigurableServletWebServerFactory server) {
server.setPort(9000);
}
}
web应用 编写一个自定义类实现WebMvcConfigurer接口定制web功能 ;(推荐使用)+ @Bean 给容器中扩展组件
@Configuration
public class AdminWebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**") //拦截的请求路径,静态资源访问也被拦截
.excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**"); //不拦截的请求路径
}
}
- @EnableWebMvc + 实现WebMvcConfigurer接口 —— @Bean 可以完全接管SpringMVC,自己重新指定规则;实现定制和扩展功能
2、定制化原理
场景starter导入---- xxxAutoConfiguration --导入依赖组件 --绑定properties配置文件 ----- 绑定配置文件项
3、数据访问
1、SQL
1、数据源的自动配置 HikariDataSource
导入JDBC场景依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
导入数据库驱动:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
这里数据库驱动有版本仲裁(默认版本:8.0.25),想要修改到自己所需要的版本:
1、导入驱动时直接指定版本号(maven中得依赖就近原则)
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
2、在pom.xml配置文件中配置属性(maven中得属性就近原则)
<properties>
<mysql.version>5.1.47</mysql.version>
</properties>
修改自动配置属性:
spring:
datasource:
url: jdbc:mysql://localhost:3306/userdb
username: root
password: tianfei
driver-class-name: com.mysql.jdbc.Driver
jdbc:
template:
query-timeout: 3
测试代码:
@Slf4j
@SpringBootTest
class Boot05JdbcApplicationTests {
@Autowired
JdbcTemplate jdbcTemplate;
@Test
void contextLoads() {
Long nums = jdbcTemplate.queryForObject("select COUNT(*) from t_account", Long.class);
log.info("总记录数为:"+nums);
}
}
2、使用Druid数据源
1、druid官方github地址
https://github.com/alibaba/druid
整合第三方技术的两种方式:
- 自定义
- 引入starter场景
2、自定义方式
引入相关依赖
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
@Configuration
public class MyDataSourceConfig {
@ConfigurationProperties(prefix = "spring.datasource")
//默认的自动配置数据源是容器中没有才会配置@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
@Bean
public DataSource dataSource() throws SQLException {
DruidDataSource dataSource = new DruidDataSource();
//打开监控功能、防火墙
dataSource.setFilters("stat,wall");
dataSource.setMaxActive(10);
return dataSource;
}
/**
* 监控页面的 sql监控
* web.xml中得配置
* <servlet>
* <servlet-name>DruidStatView</servlet-name>
* <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
* </servlet>
* <servlet-mapping>
* <servlet-name>DruidStatView</servlet-name>
* <url-pattern>/druid/*</url-pattern>
* </servlet-mapping>
*
*
* @return
*/
@Bean
public ServletRegistrationBean statViewServlet(){
StatViewServlet statViewServlet = new StatViewServlet();
ServletRegistrationBean<StatViewServlet> registrationBean = new ServletRegistrationBean<>(statViewServlet,"/druid/*");
//配置监控页访问密码
registrationBean.addInitParameter("loginUsername","druid");
registrationBean.addInitParameter("loginPassword","druid");
return registrationBean;
}
/**
* 监控页面的 web应用监控
* web.xml中得配置
* <filter>
* <filter-name>DruidWebStatFilter</filter-name>
* <filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>
* <init-param>
* <param-name>exclusions</param-name>
* <param-value>*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*</param-value>
* </init-param>
* </filter>
* <filter-mapping>
* <filter-name>DruidWebStatFilter</filter-name>
* <url-pattern>/*</url-pattern>
* </filter-mapping>
*
*
* @return
*/
@Bean
public FilterRegistrationBean webStatFilter(){
WebStatFilter webStatFilter = new WebStatFilter();
FilterRegistrationBean<WebStatFilter> registrationBean = new FilterRegistrationBean<>(webStatFilter);
registrationBean.setUrlPatterns(Arrays.asList("/*"));
registrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
return registrationBean;
}
}
3、引入starter官方场景
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.17</version>
</dependency>
相关配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/userdb?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&useSSL=false
username: root
password: tianfei
driver-class-name: com.mysql.jdbc.Driver
druid:
stat-view-servlet:
enabled: true #功能开启
login-username: druid
login-password: druid
reset-enable: false #重置按钮
web-stat-filter:
enabled: true
url-pattern: /*
exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'
aop-patterns: com.tianfei.admin/* #监控的包
filters: stat,wall #底层功能开启,stat(sql监控功能),wall(防火墙功能)
filter:
stat:
slow-sql-millis: 1000
log-slow-sql: true #日志记录慢查询
wall:
enabled: true
3、整合MyBatis操作
starter
官方的starter:spring-boot-starter-*
第三方的starter:*-spring-boot-starter
3.1纯配置方式
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/userdb?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&useSSL=false
username: root
password: tianfei
#mybatis配置规则
mybatis:
config-location: classpath:mybatis/mybatis-config.xml #mybatis的核心配置文件位置
mapper-locations: classpath:mybatis/mapper/*.xml #sql映射文件文职
整合步骤:
- 导入官方的starter
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
- 编写mapper接口(注意标注 @Mapper 注解)
@Mapper
public interface AccountMapper {
public Account getById(Integer id);
}
- 编写sql映射文件,并绑定mapper接口。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!-- 开启驼峰命名规则 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
</configuration>
- 在application.yaml配置文件中,指定mybatis核心配置文件位置和sql映射文件位置以及全局配置文件的信息(建议:配置在yaml文件中mybatis.configuration)
3.2纯注解版
@Mapper
public interface CityMapper {
@Select("select * from city where id=#{id}")
public City getById(Integer id);
@Insert("insert into city(`name`,`state`,`country`) values (#{name},#{state},#{country})")
@Options(useGeneratedKeys = true,keyProperty = "id")
public void insert(City city);
}
3.3混合版
@Mapper
public interface CityMapper {
@Select("select * from city where id=#{id}")
public City getById(Integer id);
public void insert(City city);
}
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tianfei.boot06mybatisannotation.mapper.CityMapper">
<insert id="insert" parameterType="com.tianfei.boot06mybatisannotation.bean.City" useGeneratedKeys="true" keyProperty="id">
insert into city(`name`,`state`,`country`) values (#{name},#{state},#{country});
</insert>
</mapper>
最佳实战:
- 导入mybatis的官方starter
- 在配置文件application.yaml中配置mapper-locations sql映射文件的位置
- 编写mapper接口,并添加@Mapper注解
- 简单的sql语句直接使用注解方式
- 复杂的sql语句编写mapper接口后,进行绑定映射
- @MapperScan(“com.tianfei.boot06mybatisannotation.mapper”) 可以简化,其他接口不用添加 @Mapper 注解
4、SpringBoot整合mybatis-plus
- 导入mybatis-plus官方starter
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
- 在application.yaml配置文件中配置数据源
spring:
datasource:
url: jdbc:mysql://localhost:3306/userdb?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&useSSL=false
username: root
password: tianfei
driver-class-name: com.mysql.jdbc.Driver
- 编写一个mapper接口继承BaseMapper 接口
public interface UserMapper extends BaseMapper<User> {
}
- 编写一个Service接口继承 IService接口,并编写Service的实现类继承ServiceImpl<M,T>类
public interface UserService extends IService<User> {
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
- 编写一个controller
@Controller
public class TableController {
@Autowired
UserService service;
@GetMapping("/dynamic_table")
@ResponseBody
public String dynamic_table(@RequestParam(value = "pn",defaultValue = "1") Integer pn, Model model) {
//分页查询数据
Page<User> userPage = new Page<>(pn,2);
//分页查询的结果
Page<User> page = service.page(userPage, null);
model.addAttribute("page",page);
List<User> records = page.getRecords();
long pages = page.getPages();
return "dynamic_table";
}
}
- 在主程序上添加@MapperScan(“com.tianfei.boot07mybatisplus.mapper”) 注解,开启扫描mapper包下的mapper接口
@MapperScan("com.tianfei.boot07mybatisplus.mapper")
@SpringBootApplication
public class Boot07MybatisplusApplication {
public static void main(String[] args) {
SpringApplication.run(Boot07MybatisplusApplication.class, args);
}
}
- 测试访问:localhost:8080/项目名/dynamic_table
注意!!!!使用mybatisPlus的分页插件时,需创建一个配置类MybatisPlusConfig
@Configuration
@MapperScan("com.tianfei.admin.mapper.*")
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false
// paginationInterceptor.setOverflow(false);
// 设置最大单页限制数量,默认 500 条,-1 不受限制
// paginationInterceptor.setLimit(500);
// 开启 count 的 join 优化,只针对部分 left join
//分页拦截器
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
paginationInnerInterceptor.setOverflow(true);
paginationInnerInterceptor.setMaxLimit(500L);
interceptor.addInnerInterceptor(paginationInnerInterceptor);
return interceptor;
}
}
4、单元测试
1、Junit5常用注解
https://junit.org/junit5/docs/current/user-guide/#writing-tests-annotations
2、SpringBoot整合Junit
- 编写测试方法:@Test标注(注意需要使用junit5版本的注解)
- Junit类具有Spring的功能,@Autowired、比如 @Transactional 标注测试方法,测试完成后自动回滚
5、原理解析
1、application-profile功能
- 默认配置文件 application.yaml;任何时候都会加载
- 指定环境配置文件 application-{env}.yaml
- 激活指定环境
- 配置文件激活
- 命令行激活:java -jar xxx.jar –spring.profiles.active=prod --person.name=haha
- 修改配置文件的任意值,命令行优先
- 默认配置与环境配置同时生效
- 同名配置项,profile配置优先
2、@Profile条件装配功能
//@Profile("prod")
@Configuration
public class MyConfig {
@Profile("prod")
@Bean
public Color red(){
return new Color();
}
@Profile("test")
@Bean
public Color green(){
return new Color();
}
}
3、profile分组
spring.profiles.group.myprod[0]=proddb
spring.profiles.group.myprod[1]=prodmq
使用:spring.profiles.active=myprod 激活