springBoot--终

目录

  • Web
    • 定制SpringMVC
      • 定制某些mvc配置
      • 定制mvc核心组件
      • 完全自定义mvc
    • 静态资源
      • 静态资源映射
      • 静态资源缓存
      • 示例
      • 自定义静态资源规则
        • 配置方式
        • 代码方式
    • 欢迎页
    • Favicon(网站图标)
    • 路径匹配策略
    • 内容协商
      • 制定返回json类型数据
      • 制定返回xml类型数据
      • 制定返回自定义类型数据
        • 新增其他内容协商
        • 系统提供的MessageConverter
        • 返回yaml类型数据
      • 效果
  • 模板引擎
    • Thymeleaf整合
  • 拦截器
  • 国际化
  • 错误处理
    • 实战
  • 数据访问
    • ssm整合
  • springBoot基础特性
    • profile环境隔离
      • 环境包含
      • 环境分组
      • 组件环境隔离
      • 配置文件环境隔离
    • 外部化配置
      • 配置生效优先级
      • 导入外配置文件
      • 属性占位符
    • 单元测试
  • springBoot核心原理
    • 事件和监听器
      • 生命周期监听

Web

定制SpringMVC

定制某些mvc配置

  • 如果您想保持Spring Boot MVC的默认配置,并在此基础上添加一些自定义配置,比如拦截器、格式化器、视图控制器等,可以创建一个使用@Configuration注解的配置类,并实现WebMvcConfigurer接口。同时不需要标注@EnableWebMvc注解。

    @Configuration
    public class CustomWebMvcConfigurer implements WebMvcConfigurer {
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            // 添加拦截器逻辑
        }
    
        @Override
        public void addFormatters(FormatterRegistry registry) {
            // 添加格式化器逻辑
        }
    
        @Override
        public void addViewControllers(ViewControllerRegistry registry) {
            // 添加视图控制器逻辑
        }
    }
    

例子

  • 自定义拦截器: 假设您希望在每个请求前后记录请求日志。首先,创建一个拦截器类来处理请求日志逻辑
public class LoggingInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 在请求之前记录日志
        System.out.println("请求开始:" + request.getRequestURI());
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        // 请求处理完成后记录日志
        System.out.println("请求结束:" + request.getRequestURI());
    }
}

  • 自定义格式化器: 假设您需要在URL参数中接收日期,并在处理请求时将其转换为java.util.Date类型。首先,创建一个格式化器类来完成日期的格式化/解析:
public class DateFormatter implements Formatter<Date> {

    @Override
    public Date parse(String text, Locale locale) throws ParseException {
        // 将文本解析为日期对象
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", locale);
        return dateFormat.parse(text);
    }

    @Override
    public String print(Date date, Locale locale) {
        // 将日期对象格式化为文本
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", locale);
        return dateFormat.format(date);
    }
}

  • 自定义视图控制器: 假设您希望处理一些简单的URL映射,而无需创建完整的Controller。首先,创建一个视图控制器类来处理URL映射:
@Controller
public class ViewController {

    @GetMapping("/hello")
    public String hello() {
        return "hello"; // 返回视图模板名称
    }
}
  • 在相关配置类中注册
@Configuration
public class CustomWebMvcConfigurer implements WebMvcConfigurer {
	//拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoggingInterceptor());
    }
    //格式化器
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addFormatter(new DateFormatter());
    }
    //视图控制器
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/hello").setViewName("hello");
    }
}

定制mvc核心组件

  1. 如果您只需要自定义一些核心组件实例,比如RequestMappingHandlerMappingRequestMappingHandlerAdapterExceptionHandlerExceptionResolver,可以通过创建一个WebMvcRegistrations组件并将其注册到Spring容器中实现。这样您可以自行创建和配置这些核心组件的实例,而不会影响其他默认配置。

    @Configuration
    public class Testconfig implements WebMvcRegistrations  {
        
        @Override
        public RequestMappingHandlerMapping getRequestMappingHandlerMapping(){
         	//重写自己的逻辑   
            return null;
    
        }
        @Override
        public RequestMappingHandlerAdapter getRequestMappingHandlerAdapter(){
            //重写自己的逻辑
            return null;
        }
        @Override
        public ExceptionHandlerExceptionResolver getExceptionHandlerExceptionResolver() {
            //重写自己的逻辑
            return null;
        }
    
    }
    

完全自定义mvc

需要注意的是,完全自定义Spring MVC可能需要更多的工作和理解框架的内部机制。在大多数情况下,使用Spring MVC的默认配置和特性已经足够满足绝大多数Web应用程序的需要。只有在特殊情况下才需要进行完全自定义。


用于启用Spring MVC的完整功能,但是使用它可能会覆盖Spring Boot的自动配置,因此请谨慎使用。如果您只需要部分自定义配置,通常不需要使用@EnableWebMvc注解,而是仅实现WebMvcConfigurer接口即可。

@Configuration
@EnableWebMvc//这个注解加上的话,会将springBoot的默认配置覆盖掉,全部使用你定义的规则
public class StaticConfig {
    @Bean
    //将WebMvcConfigurer放在容器中
    public WebMvcConfigurer webMvcConfigurer(){
        return new WebMvcConfigurer() {
            @Override
            public void addResourceHandlers(ResourceHandlerRegistry registry) {
                WebMvcConfigurer.super.addResourceHandlers(registry);
                registry.addResourceHandler("/static/**")
                        .addResourceLocations("classpath:/a/")
                        //缓存最大时间 单位秒
                        .setCacheControl(CacheControl.maxAge(7200, TimeUnit.SECONDS));
            }
        };
    }
}

静态资源

静态资源映射

  • 静态资源映射规则在 WebMvcAutoConfiguration 中进行了定义:
  • /webjars/** 的所有路径 资源都在 classpath:/META-INF/resources/webjars/
  • /** 的所有路径 资源都在 classpath:/META-INF/resources/classpath:/resources/classpath:/static/classpath:/public/

静态资源缓存

  1. 所有静态资源都定义了缓存规则。【浏览器访问过一次,就会缓存一段时间】,但此功能参数无默认值
    1. period: 缓存间隔。 默认 0S;
    2. cacheControl:缓存控制。 默认无;
    3. useLastModified:是否使用lastModified头。 默认 false;

示例

  1. 
    #1、spring.web:
    # 1.配置国际化的区域信息
    # 2.静态资源策略(开启、处理链、缓存)
    
    # 开启缓存映射
    spring.web.resources.add-mappings=true
    # 设置缓存间隔时间
    spring.web.resources.cache.period=3600
    # 缓存详细合并项控制,会覆盖.period这一项
    spring.web.resources.cache.cachecontrol.max-age=7200
    # 使用use-last-modified 服务器在接收到请求的时候,会给客户端返回一个时间
    # 这个时间就是静态资源最后一次修改的时间,如果客户端当前时间和这个返回的时间相同的话
    # 就说明这个资源没有被修改,客户端直接从缓存中获取,否则,将在服务器中重新获取这个静态资源
    # 不设置,默认为开启,true
    spring.web.resources.cache.use-last-modified=true 
    
    
    
    

自定义静态资源规则

配置方式

# 自定义静态资源文件夹的位置
spring.web.resources.static-locations=classpath:/a/

# 自定义静态资源规则
# 自定义webjars访问路径
spring.mvc.webjars-path-pattern=/wjs/**
# 自定静态资源访问路径
spring.mvc.static-path-pattern=/static/**

配置了访问路径.static-path-pattern以后,在浏览器请求时,请求路径就要写http://localhost:8080/static/hyp.jpg

在配置了资源文件夹位置static-locations后 静态资源的存放位置就变了

springBoot--终_第1张图片

代码方式

**注意:**只要将WebMvcConfigurer加入到容器中,配置的底层行为就会生效

​ 加上@EnableMvc注解就会禁用springBoot的默认配置

/**
 * 使用代码方式配置静态资源规则,代替使用properties配置
 * @author Han
 * @data 2023/7/17
 * @apiNode
 */
@Configuration
public class StaticConfig implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        //保留默认配置
        WebMvcConfigurer.super.addResourceHandlers(registry);
        //添加自己的配置【访问路径为/static/**】【修改静态资源所在包  为类路径下的a文件夹】
        registry.addResourceHandler("/static/**")
                //添加自己的配置【访问路径为/static/**】【修改静态资源所在包  为类路径下的a文件夹】
        registry.addResourceHandler("/static/**")
                .addResourceLocations("classpath:/a/")
                //缓存最大时间 单位秒
                .setCacheControl(CacheControl.maxAge(7200, TimeUnit.SECONDS));
    }
}

springBoot--终_第2张图片

springBoot--终_第3张图片

另一种方式,不继承WebMvcConfigurer类,将WebMvcConfigurer类作为一个Bean注册到容器中

@Configuration
@EnableWebMvc
public class StaticConfig {
    @Bean
    //将WebMvcConfigurer放在容器中
    public WebMvcConfigurer webMvcConfigurer(){
        return new WebMvcConfigurer() {
            @Override
            public void addResourceHandlers(ResourceHandlerRegistry registry) {
                WebMvcConfigurer.super.addResourceHandlers(registry);
                registry.addResourceHandler("/static/**")
                        .addResourceLocations("classpath:/a/")
                        //缓存最大时间 单位秒
                        .setCacheControl(CacheControl.maxAge(7200, TimeUnit.SECONDS));
            }
        };
    }
}

欢迎页

欢迎页规则在 WebMvcAutoConfiguration 中进行了定义:

  1. 静态资源目录下找 index.html
  2. 没有就在 templates下找index模板页

springBoot--终_第4张图片

Favicon(网站图标)

  1. 在静态资源目录下找 favicon.ico
  2. 将网站的图片放在静态资源目录下,并命名为favicon.ico,就可以改变网页的图标

springBoot--终_第5张图片

路径匹配策略

  • springBoot支持Ant风格的路径
  • 新版springBoot默认支持pathPatternParser风格路径
@GetMapping("/testPath/a*/b?/{pp}/**")
    public String testPath(@PathVariable("pp") String pp, HttpServletRequest request){
        var requestURL = request.getRequestURL();
        System.out.println(requestURL);

        return requestURL.toString()+"参数pp="+pp;
    }

springBoot--终_第6张图片

  • 但是如果将**放在路径的中间位置,@GetMapping("/testPath/**/a*/b?/{pp}/**")
@GetMapping("/testPath/**/a*/b?/{pp}/**")
    public String testPath(@PathVariable("pp") String pp, HttpServletRequest request){
        var requestURL = request.getRequestURL();
        System.out.println(requestURL);

        return requestURL.toString()+"参数pp="+pp;
    }
  • 就会报错【检测到无效的映射模式】

springBoot--终_第7张图片

  • 解决方法就是将路径匹配规则在配置文件中修改为spring.mvc.pathmatch.matching-strategy=ant_path_matcher

  • 这是因为新版springBoot默认支持的路径匹配风格是spring.mvc.pathmatch.matching-strategy=path_pattern_parser这个效率非常高但是不支持将**写在路径的中间位置

修改配置文件后:

springBoot--终_第8张图片

内容协商

一套系统支持返回多种数据类型

分为:

  • 基于请求头的内容协商
  • 基于请求参数的内容协商

控制器方法

 /**
     * 测试内容协商
     * 1、返回结果为json
     * 这里遇到了问题,网页无法显示json数据
     * 是因为当时没有给pojo类中提供get方法,提供以后正常了
     * @return
     */
    @GetMapping("/person")
    public Person person(){
        return new Person("小韩", 21);
    }

制定返回json类型数据

​ 因为springBoot化境下默认导入了json类型的内容协商,所以返回一个对象在浏览器默认显示的是Json

制定返回xml类型数据

  • 导入支持转换成xml格式的依赖

     <dependency>
         <groupId>com.fasterxml.jackson.dataformatgroupId>
         <artifactId>jackson-dataformat-xmlartifactId>
    dependency>
    
  • 给要返回的数据的类上标注@注解

    @JacksonXmlRootElement//可以写出为xml文档
    public class Person {
        private String name;
        private Integer age;
    
        public Person(String name, Integer age) {
            this.name = name;
            this.age = age;
        }
    …………
    
  • 配置配置文件

    注意:基于请求头的内容协商是默认开启的,但是基于请求参数的是需要手动开启的

    # 开启基于请求参数的内容协商
    spring.mvc.contentnegotiation.favor-parameter=true
    # 修改请求参数指定内容协商时的使用的参数名 默认为format
    spring.mvc.contentnegotiation.parameter-name=type
    
    

制定返回自定义类型数据

新增其他内容协商

1、增加媒体类型支持的依赖

2、编写properties媒体类型配置

3、编写自己的MessageConverter

4、编写HttpMessageConverter。也就是在配置类中配置MessageConverter,将编写的MessageConverter添加到底层

系统提供的MessageConverter

八个:

    • ByteArrayHttpMessageConverter: 支持字节数据读写
    • StringHttpMessageConverter: 支持字符串读写
    • ResourceHttpMessageConverter:支持资源读写
    • ResourceRegionHttpMessageConverter: 支持分区资源写出
    • AllEncompassingFormHttpMessageConverter:支持表单xml/json读写
    • MappingJackson2HttpMessageConverter: 支持请求响应体Json读写
  • 系统提供默认的MessageConverter 功能有限,仅用于json或者普通返回数据。额外增加新的内容协商功能,必须增加新的HttpMessageConverter

返回yaml类型数据

1、添加依赖

添加支持返回yaml格式的依赖

 
        <dependency>
            <groupId>com.fasterxml.jackson.dataformatgroupId>
            <artifactId>jackson-dataformat-yamlartifactId>
        dependency>

2、编写配置

# 增加yaml类型
spring.mvc.contentnegotiation.media-types.yaml=text/yaml

3、编写组件 自己的MessageConverter

作用是将对象转换成yaml格式写出【这一步可以将对象自己定义返回类型】


/**
 * 编写组件
 * 将对象可以返回为yaml格式
 * @author Han
 * @data 2023/7/22
 * @apiNode
 */
//编写自己的类,继承AbstractHttpMessageConverter类
public class MyYamlHttpConverters extends AbstractHttpMessageConverter<Object> {

    private ObjectMapper objectMapper;

    public MyYamlHttpConverters() {
        //定义媒体类型,这里的类型要和配置文件中一致
        super(new MediaType("text", "yaml", Charset.forName("utf-8")));
        
        YAMLFactory disableYaml = new YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER);
        //转xml或者Yaml都是ObjectMapper来起作用的
        this.objectMapper = new ObjectMapper(disableYaml);
    }

    @Override
    protected boolean supports(Class<?> clazz) {
        //这里可以添加逻辑判断
        // 判断传入的否是一个对象
        //在这里先不判断
        return true;
    }

    @Override
    protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        return null;
    }

    @Override//将对象写出去
    protected void writeInternal(Object methodReturnValue, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        //获取对应的输出流
        OutputStream body = outputMessage.getBody();
        try {
            this.objectMapper.writeValue(body, methodReturnValue);
        } finally {
            body.close();
        }

    }
}

4、在配置类中配置,增加HttpMessageConverter

在配置类中添加组件

@Configuration
public class StaticConfig {
    @Bean
    //将WebMvcConfigurer放在容器中
    public WebMvcConfigurer webMvcConfigurer(){
        return new WebMvcConfigurer() {
            @Override
            public void addResourceHandlers(ResourceHandlerRegistry registry) {
                WebMvcConfigurer.super.addResourceHandlers(registry);
                registry.addResourceHandler("/static/**")
                        .addResourceLocations("classpath:/a/")
                        //缓存最大时间 单位秒
                        .setCacheControl(CacheControl.maxAge(7200, TimeUnit.SECONDS));
            }

            @Override
            public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
                converters.add(new MyYamlHttpConverters());
            }
        };
    }
}

效果

springBoot--终_第9张图片

springBoot--终_第10张图片

springBoot--终_第11张图片

模板引擎

Thymeleaf整合

引入thymeleaf依赖

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-thymeleafartifactId>
dependency>

自动配置原理

  1. 开启了 org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration 自动配置
  2. 属性绑定在 ThymeleafProperties 中,对应配置文件spring.thymeleaf内容
  3. 所有的模板页面默认在 classpath:/templates文件夹下
  4. 默认效果
    1. 所有的模板页面在 classpath:/templates/下面找
    2. 找后缀名为.html的页面
  5. 这部分看语雀文档

拦截器

以用户登录为例子

使用步骤

  1. 编写一个拦截器实现 HandlerInterceptor 接口
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
    /**
     * 目标方法执行之前
     */
    @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 loginUser = session.getAttribute("loginUser");

        if (loginUser != null) {
            //放行
            return true;
        }
        //拦截住。未登录。跳转到登录页
        request.setAttribute("msg", "请先登录");
        // re.sendRedirect("/");
        request.getRequestDispatcher("/").forward(request, response);
        return false;
    }

    /**
     * 目标方法执行完成以后
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse
            response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("postHandle执行{}", modelAndView);
    }

    /**
     * 页面渲染以后
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse
            response, Object handler, Exception ex) throws Exception {
        log.info("afterCompletion执行异常{}", ex);
    }
}

2.拦截器注册到容器中(实现 WebMvcConfigurer 的 addInterceptors() )

3.指定拦截规则(注意,如果是拦截所有,静态资源也会被拦截】

@Configuration
public class AdminWebConfig implements WebMvcConfigurer{
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    	registry.addInterceptor(new LoginInterceptor())//拦截器注册到容器中
   				.addPathPatterns("/**") //所有请求都被拦截包括静态资源
            	//放行的请求
            	.excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**", "/js/**","/aa/**"); 
}

国际化

在springBoot核心配置文件中进行配置时使用的是 spring.messages

编写国际化配置文件

默认:

​ 配置文件名:message.properties 无区域代码

login=login
sign_in=sign_in

英文版:使用区域代码_en_US

​ 配置文件名:message_en_US.properties _en_US前的名称随意取

login=login
sign_in=sign_in

中文版:使用区域代码_zh_CN

​ 配置文件名:message_zh_CN.properties _zh_CN前的名称随意取

login=登录
sign_in=注册

使用thymeleaf语法进行国际化内容显示

使用#{}

错误处理

[原理][https://www.yuque.com/leifengyang/springboot3/wp5l9qbu1k64frz1#mMAt4]可查看语雀文档的错误处理章节

实战

1.前后端分离项目

​ 前后端分离项目可使用@ControllerAdvice+@ExceptionHandler进行统一异常处理

2.服务端页面渲染【前后端不分离】

​ HTTP状态错误

​ 给classpath:/templetes/error目录下放精确码html页面【404.html/500.html……】

​ 给classpath:/templetes/error目录下放模糊码html页面【4xx.html/5xx.html……】
​ 发生业务错误

​ 核心业务**,每一种错误,都应该代码控制,跳转到自己定制的错误页

​ 通用业务**,classpath:/templates/error.html页面,显示错误信息

springBoot--终_第12张图片

注意: springBoot自动将错误信息封装到Modal中,如果要打印错误信息只需要在页面中直接使用${}获取

springBoot--终_第13张图片

前后端不分离方式

最后出现什么错误就会到对应的错误页面去显示错误信息

​ 400.html:

DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
    head>
    <body>
        请求参数错误
        <br>
        错误信息:[[${message}]]
    body>
html>

​ 控制器方法

@Controller
@Slf4j
public class HtmlController {
    @GetMapping("/hello")
    public String hello(@RequestParam("name") String name , Model model){
        //log.info(name);
        //使用model向前端页面展示数据
        model.addAttribute("name", name);
        return "hello";
    }
}

前后端分离方式

​ 只需要集中处理错误,页面由前端负责

返回json数据,在页面的错误信息中显示json数据

/**
 * @ControllerAdvice 这个注解表明这个类集中处理所有controller发生的错误
 * @author Han
 * @data 2023/7/26
 * @apiNode
 */
@RestControllerAdvice
public class AllExceptionHandler {
    @ExceptionHandler(Exception.class)//传入发生异常的类型
    @ResponseBody
    /**
     * 写错误信息处理方法  可返回对象
     * 发生什么错误返回什么对象
     */
    public String handlerException(Exception e) {
        return "错误!! 原因:"+e.getMessage();
    }
}

数据访问

ssm整合

  • 首先导入要使用的starter
<dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.mybatis.spring.bootgroupId>
            <artifactId>mybatis-spring-boot-starterartifactId>
            <version>3.0.2version>
        dependency>

        <dependency>
            <groupId>com.mysqlgroupId>
            <artifactId>mysql-connector-jartifactId>
            <scope>runtimescope>
        dependency>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <optional>trueoptional>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
        <dependency>
            <groupId>org.mybatis.spring.bootgroupId>
            <artifactId>mybatis-spring-boot-starter-testartifactId>
            <version>3.0.2version>
            <scope>testscope>
        dependency>
    dependencies>
  • 配置基础的连接数据源
# 配置数据源
# 驱动
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# url
spring.datasource.url=jdbc:mysql://localhost:3306/p_springBoot
# 数据库用户名及密码
spring.datasource.username=root
spring.datasource.password=hyp
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
  • 以查询User对象为例
    • 首先要创建数据库表映射对象User
@Data
public class User {
    private Long id;
    private String loginName;
    private String nickName;
    private String passwd;
}

编写相关Mapper接口和Mapper.xml映射文件

@Mapper//标记@Mapper注解表明这个接口是一个Mapper
public interface UserMapper {

    User getUserByID(@Param("id") Long id);
}

编写SQL映射文件


DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.hyp.ssm.mapper.UserMapper">
    <select id="getUserByID" resultType="user">
        select * from t_user where id = #{id}
    select>
mapper>

编写controller控制器方法

@RestController
@Slf4j
public class UserController {
    // 将Mapper接口注入
    @Autowired
    UserMapper userMapper;

    @GetMapping("/getUserById/{id}")
    public User getUserById(@PathVariable("id") Long id) {
        log.info("查询id为【{}】的用户",id);
        return userMapper.getUserByID(id);
    }
}

mybatis相关配置

# 配置mybatis
# 别名机制 在Sql映射文件UserMapper.xml文件中的resultType属性使用别名
mybatis.type-aliases-package=com.hyp.ssm.bean
# 告诉mybatis SQL映射文件在哪里
mybatis.mapper-locations=classpath:/mapper/*.xml
# 开启驼峰命名映射
mybatis.configuration.map-underscore-to-camel-case=true

测试:

springBoot--终_第14张图片

注意:

在标注Mapper接口时有两种方法

  • 在Mapper接口上添加@Mapper注解,加了这个注解后,明示了这个接口是一个Mapper接口,并且还将它作为一个bean交给ioc容器进行管理
  • 还可以在主启动类上添加注解@MapperScan(basePackages = "填写Mapper接口所在包")
/**
 *@MapperScan 这个注解是用来扫描Mapper接口的
 *              如果在Mapper接口上添加了@Mapper注解,就不用再加这个注解了
 */
@SpringBootApplication
@MapperScan(basePackages = "com.hyp.ssm.mapper")
public class SsmApplication {

    public static void main(String[] args) {
        SpringApplication.run(SsmApplication.class, args);
    }

}
  • 他们只要存在一个就可以,但也可以同时存在

springBoot基础特性

profile环境隔离

  • Spring Profiles 提供一种隔离配置的方式,使其仅在特定环境生效;
  • 任何@Component, @Configuration 或 @ConfigurationProperties 可以使用 @Profile 标记,来指定何时被加载。【容器中的组件都可以被 @Profile标记】
@Profile({"test"})
@Component
public class Cat {
    private Integer id;
    private String name;
}
@Profile({"prod"})
@Component
public class Person {
    private String name;
    private Integer age;
    private User user;
    private Cat cat;
    private Map<String, Dog> dogMap;
    private List<Dog> dogs;

在配置文件中选择激活的环境进行激活

  • 这时候,ioc容器中只有Person组件,没有Cat组件
# 激活prod环境
spring.profiles.active=prod

环境包含

  • 生效的环境 = 激活的环境/默认环境 + 包含的环境

  • 项目里面这么用

    • 基础的配置mybatislogxxx:写到包含环境中
    • 需要动态切换变化的 dbredis:写到激活的环境中
# 包含环境
# 不管是否激活了Dev 和 test 环境 总是要生效的环境
spring.profiles.include=prod,test

环境分组

# 环境分组
spring.profiles.group.must=dev,test
spring.profiles.group.A = prod,test
# 可以选择一个组来激活
spring.profiles.active=must

组件环境隔离

  • 一:组件环境隔离
    • 1、标识环境
      • 1、给定区分几个环境 : dev(开发) text(测试) prod(生产)
      • 2、指定每个组件在那个环境下生效 【在组件类上添加@profile注解】
        • 通过:@Profile({"prod"})……

springBoot--终_第15张图片

  • 如果组件没有标注@Profile 那么就是所有环境下都能使用这个组件
  • 如果标注了@Profile({"default"}) 在没有激活指定环境时,默认只有这一个组件

springBoot--终_第16张图片

  • 3、只有激活这些指定的环境,这些组件才能生效

  • 2、激活环境

    • 1、通过配置文件激活 spring.profiles.active=prod

springBoot--终_第17张图片

配置文件环境隔离

二:配置文件环境隔离

  • 1、application.properties 主配置文件,在任何环境下都生效
  • 2、其他profile环境下配置文件命名规范:

    •  `application-dev.properties`
      
    • application-test.properties

      …… …… ……

    •  格式:`application-{profile标识}.properties`
      
  •  3、激活指定环境即可  会自动选择对应环境的配置文件进行配置
    
  •  4、**项目的所有生效配置=激活的配置文件的所有项+主配置文件和激活文件`不冲突`的所有项**
     *      如果发生了配置冲突 以激活的配置文件的配置为准
     *      如:
            *      在`application.properties`中配置的端口号为`8080`
            *      在`application-dev.properties`中配置的端口号为`9090`
            *      我们激活了`dev环境`,那么会以dev环境中的端口号`9090为准`
    
  •  注意:要激活某个环境,只能在主配置文件中设置
    

springBoot--终_第18张图片

外部化配置

  • application-{profile}.properties可以作为指定环境的配置文件

  • 激活这个环境,配置就会生效。最终生效的所有配置

    • application.properties:主配置文件,任意时候都生效
    • application-{profile}.properties:指定环境配置文件,激活指定环境生效

profile优先级 > application

配置生效优先级

常用的有:

  • 默认属性【SpringApplication.setDefaultProperties指定,在启动类中设置】
  • 配置文件 【application.properties/yml等】
  • 命令行参数

注意:
配置文件优先级如下**(返序)**

  1. jar 包内application.properties/yml
  2. jar 包内application-{profile}.properties/yml
  3. jar 包外application.properties/yml
  4. jar 包外application-{profile}.properties/yml

springBoot--终_第19张图片

导入外配置文件

# 导入一个配置文件,这配置文件中配置了server.port=9999
spring.config.import=classpath:aaa.properties
# 然后这里也设置了端口,但是因为是导入的配置,
# 所以优先级大于本身所有的,则最终端口是aaa.properties所定义的
server.port=8080

属性占位符

# 属性占位符,可以获取配置文件中的配置项的值
# 在controller中使用@value注解拿出来
portValue = 端口号是:${server.port}
@RestController
public class HelloController {
    
    @Value("${portValue}")
    String portValue;
    
    @GetMapping("/getPort")
    public String getPortValue(){
        return portValue;
    }
}

最终页面上显示:端口号是9999

springBoot--终_第20张图片

单元测试

springBoot核心原理

事件和监听器

生命周期监听

springBoot--终_第21张图片

package com.example.texing.CoreTeXing.listener;

import org.springframework.boot.ConfigurableBootstrapContext;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;

import java.time.Duration;

/**
 *
 *
 *   Listener先要从 META-INF/spring.factories 读到
 *
 *  1、引导: 利用 BootstrapContext 引导整个项目启动
 *        starting:              应用开始,SpringApplication的run方法一调用,只要有了 BootstrapContext 就执行
 *       environmentPrepared:   环境准备好(把启动参数等绑定到环境变量中),但是ioc还没有创建;【调一次】
 *   2、启动:
 *        contextPrepared:       ioc容器创建并准备好,但是sources(主配置类)没加载。并关闭引导上下文;组件都没创建  【调一次】
 *        contextLoaded:         ioc容器加载。主配置类加载进去了。但是ioc容器还没刷新(我们的bean没创建)。
 *        =======截止以前,ioc容器里面还没造bean呢=======
 *        started:               ioc容器刷新了(所有bean造好了),但是 runner 没调用。
 *        ready:                  ioc容器刷新了(所有bean造好了),所有 runner 调用完了。
 *   3、运行
 *       以前步骤都正确执行,代表容器running。
 *   4、运行失败
 *      failed  以上任意一个步骤如果发生了异常,就会启动失败
 *
 */
public class MyListener implements SpringApplicationRunListener {
    @Override
    public void starting(ConfigurableBootstrapContext bootstrapContext) {
        System.out.println("===starting===  正在启动 ");
    }

    @Override
    public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
        System.out.println("===environmentPrepared===  环境准备完成 ");
    }

    @Override
    public void contextPrepared(ConfigurableApplicationContext context) {
        System.out.println("===contextPrepared===  ioc容器准备完成 ");

    }

    @Override
    public void contextLoaded(ConfigurableApplicationContext context) {
        System.out.println("===contextLoaded===  ioc容器加载完成 ");

    }

    @Override
    public void started(ConfigurableApplicationContext context, Duration timeTaken) {
        System.out.println("===started===  启动完成 ");
    }

    @Override
    public void ready(ConfigurableApplicationContext context, Duration timeTaken) {
        System.out.println("===ready===  准备就绪 ");
    }

    @Override
    public void failed(ConfigurableApplicationContext context, Throwable exception) {
        System.out.println("===failed===  应用启动失败 ");
    }
}

你可能感兴趣的:(SpringBoot,spring,boot,后端,java)