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后 静态资源的存放位置就变了

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

代码方式

**注意:**只要将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));
    }
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

另一种方式,不继承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模板页

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Favicon(网站图标)

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

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

路径匹配策略

  • 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;
    }

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 但是如果将**放在路径的中间位置,@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;
    }
  • 就会报错【检测到无效的映射模式】

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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

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

修改配置文件后:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

内容协商

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

分为:

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

控制器方法

 /**
     * 测试内容协商
     * 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.dataformat</groupId>
         <artifactId>jackson-dataformat-xml</artifactId>
    </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格式的依赖

 <!--增加处理yaml的内容协商依赖-->
        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-yaml</artifactId>
        </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());
            }
        };
    }
}

效果

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

模板引擎

Thymeleaf整合

引入thymeleaf依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</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语法进行国际化内容显示

使用#{}

<button style="color: aqua" th:text="#{login}"/>
<button style="color: rosybrown" th:text="#{sign_in}"/>

错误处理

[原理][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自动将错误信息封装到Modal中,如果要打印错误信息只需要在页面中直接使用${}获取

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

前后端不分离方式

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

​ 400.html:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </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.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>3.0.2</version>
        </dependency>

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter-test</artifactId>
            <version>3.0.2</version>
            <scope>test</scope>
        </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映射文件

<?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="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

测试:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意:

在标注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"})……

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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

  • 2、激活环境

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

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

配置文件环境隔离

二:配置文件环境隔离

  • 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为准`
    
  •  注意:要激活某个环境,只能在主配置文件中设置
    

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外部化配置

  • 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

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

导入外配置文件

# 导入一个配置文件,这配置文件中配置了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核心原理

事件和监听器

生命周期监听

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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===  应用启动失败 ");
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/98579.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2023年高教社杯 国赛数学建模思路 - 案例:ID3-决策树分类算法

文章目录 0 赛题思路1 算法介绍2 FP树表示法3 构建FP树4 实现代码 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 算法介绍 FP-Tree算法全称是FrequentPattern Tree算法&#xff0c;就是频繁模…

本地部署体验LISA模型(LISA≈图像分割基础模型SAM+多模态大语言模型LLaVA)

GitHub地址&#xff1a;https://github.com/dvlab-research/LISA 该项目论文paper reading&#xff1a;https://blog.csdn.net/Transfattyacids/article/details/132254770 在GitHub上下载源文件&#xff0c;进入下载的文件夹&#xff0c;打开该地址下的命令控制台&#xff0c;…

Vue安装过程的困惑解答——nodejs和vue关系、vue的项目结构

文章目录 一、为什么在使用vue前要下载nodejs&#xff1f;二、为什么安装nodejs后就能使用NPM包管理工具&#xff1f;三、为什么是V8引擎并且使用C实现&#xff1f;四、为什么会安装淘宝镜像&#xff1f;五、什么是webpack模板&#xff0c;为什么需要他&#xff1f;六、vue项目…

深入探索C语言自定义类型:打造你的编程世界

一、什么是自定义类型 C语言提供了丰富的内置类型&#xff0c;常见的有int, char, float, double, 以及各种指针。 除此之外&#xff0c;我们还能自己创建一些类型&#xff0c;这些类型称为自定义类型&#xff0c;如数组&#xff0c;结构体&#xff0c;枚举类型和联合体类型。 …

Unreal5(虚幻5)学习记录 快捷键

虚幻5学习记录 快捷键 世界场景中漫游&#xff08;镜头移动): 按住鼠标右键 键盘的W(前) S(后) A(左) D(右) E(上) Q(下)键 透视 透视 ALTG 上部分 ALTJ 底视图ALTSHIFTJ 左视图 ALTK 右视图 ALTSHIFTK 前视图 ALTH 后视图 ALTSHIFTH 内容浏览器 Ctrl Space 内容浏览器…

stm32CubeMX HAL W5500芯片介绍 第一章

W5500芯片介绍 文章目录 W5500芯片介绍简单简绍以太网以太网分五层&#xff1a;第一层物理层&#xff1a;第二层&#xff1a;数据链路层&#xff1a;第三层&#xff1a;网络层&#xff1a;第四层&#xff1a;传输层&#xff1a;第五层&#xff1a;应用层&#xff1a;以太网应用…

Scala的特质trait与java的interface接口的区别,以及Scala特质的自身类型和依赖注入

1. Scala的特质trait与java接口的区别 Scala中的特质&#xff08;trait&#xff09;和Java中的接口&#xff08;interface&#xff09;在概念和使用上有一些区别&#xff1a; 默认实现&#xff1a;在Java中&#xff0c;接口只能定义方法的签名&#xff0c;而没有默认实现。而在…

Matlab(结构化程式和自定义函数)

目录 1.脚本编辑器 2.脚本流 2.1 控制流 2.2 关系&#xff08;逻辑&#xff09;操作符 3.脚本与函数 1.脚本编辑器 Matlab的命名规则&#xff1a; 常用功能&#xff1a; 智能缩进&#xff1a; 在写代码的时候&#xff0c;有的时候代码看起来并不是那么美观&#xff08;可读性…

单片机通用学习-​什么是寄存器?​

什么是寄存器&#xff1f; 寄存器是一种特殊的存储器&#xff0c;主要用于存储和检查微机的状态。CPU寄存器用于存储和检查CPU的状态&#xff0c;具体包括计算中途数据、程序因中断或子程序分支时的返回地址、计算结果为零时的负值、计算结果为零时的信息、进位值等。 由于CP…

怎么提取视频中的音乐保存到本地?其实方法很简单

当你想要使用视频中的音乐时&#xff0c;你可以考虑将它从视频中提取出来。这可以用于制作音频样本集&#xff0c;制作铃声或其他音频素材&#xff0c;或者向其他人展示视频的音乐部分而无需显示视频本身。如果你是一位音乐制作人员&#xff0c;你可能会需要一些特定类型的音效…

HTML之VSCode简单配置与创建

目录 插件下载 然后输入源码&#xff1a; 使用 效果 插件下载 下载这个插件后可以直接运行&#xff1a; 然后创建一个文件&#xff1a; 然后输入源码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"…

Vue3列表竖向滚动(包含使用swiper的翻页效果)

一、使用element-plus表格进行滚动&#xff1a; 可以满足的需求&#xff1a;表格一行一行竖向滚动&#xff0c;类似走马灯。 不能满足的需求&#xff1a;表格分页竖向滚动&#xff0c;有翻页的效果。 代码&#xff1a; <template><el-table:data"tableData"…

AMEYA360:兆易创新获得ISO 26262 ASIL D流程认证, 汽车功能安全管理体系再上新台阶

中国北京(2023年8月29日) —— 业界半导体器件供应商兆易创新GigaDevice(股票代码 603986)今日宣布&#xff0c;获得由国际公认的测试、检验和认证机构通标标准技术服务有限公司(以下简称SGS)授予的ISO 26262:2018汽车功能安全最高等级ASIL D流程认证证书&#xff0c;这标志着兆…

文心一言 VS CHATGPT

由于近几天来&#xff0c;我的手机短信不断收到百度公司对于“文心一言”大模型的体验邀请&#xff08;真是不胜其烦&#xff09;&#xff01;&#xff01;所以我就抱着试试看的态度点开了文心一言的链接&#xff1a;文心一言 目前看来&#xff0c;有以下两点与chatgpt是有比较…

【自学开发之旅】基于Flask的web开发(一)

web开发项目设计&#xff1a; 立项-需求分析-设计&#xff08;原型图、数据库、api设计&#xff09;-技术选型-写代码-测试-上线 web开发的本质上就是生成超文本。 前端负责展示&#xff0c;后端负责逻辑处理&#xff1a;后逻辑请求&#xff08;接收请求、响应请求&#xff0…

成集云 | 飞书审批同步金蝶云星空 | 解决方案

源系统成集云目标系统 方案介绍 飞书员工报销审批通过后&#xff0c;审批单据内容和审批状态实时同步金蝶云星空 飞书是字节跳动于2016年自研的新一代一站式协作平台&#xff0c;将即时沟通、日历、云文档、云盘和工作台深度整合&#xff0c;通过开放兼容的平台&#xff0c;…

Tomcat安装及配置教程-Windows和Linux

本文主要介绍Windows版本Tomcat部署的详细步骤和列出Linux部署的简要细节命令,其中Windows从一到七,Linux用第八个标题讲述 一,安装 1,打开官网,https://tomcat.apache.org/,选择Tomcat 8.5.93版本,点击Download,根据系统版本选择压缩包 2,下载完毕,将压缩包解压,将所有文件放…

IBM Spectrum LSF Explorer 为要求苛刻的分布式和任务关键型高性能技术计算环境提供强大的工作负载管理

IBM Spectrum LSF Explorer 适用于 IBM Spectrum LSF 集群的强大、轻量级报告解决方案 亮点 ● 允许不同的业务和技术用户使用单一解决方案快速创建和查看报表和仪表板 ● 利用可扩展的库提供预构建的报告 ● 自定义并生成性能、工作负载和资源使用情况的报…

day 43 | ● 123.买卖股票的最佳时机III ● 188.买卖股票的最佳时机IV

123.买卖股票的最佳时机III func maxProfit(prices []int) int {dp : make([][]int , len(prices))dp[0] []int{0, -prices[0], 0, -prices[0], 0}for i : 1; i < len(prices);i{val0 : dp[i - 1][0]val1 : max(dp[i - 1][0] - prices[i], dp[i - 1][1])val2 : max(dp[i - …

HTML 播放器效果

效果图 实现代码 <!DOCTYPE HTML> <html><head><title>爱看动漫社区 | 首页 </title><link href"css/bootstrap.css" relstylesheet typetext/css /><!-- jQuery --><script src"js/jquery-1.11.0.min.js"…