springBoot--终

news2024/12/23 9:23:19

目录

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

layui框架学习(43:文件上传模块-下)

上一篇文章介绍文件上传模块使用示例时介绍了done和error事件&#xff0c;这两个事件是在文件上传成功&#xff08;原文&#xff1a;在上传接口请求完毕后触发&#xff0c;但文件不一定是上传成功的&#xff09;及上传失败&#xff08;原文&#xff1a;请求上传出现异常&#x…

一篇文章带你快速入门使用Git

文章目录 前言一、什么是版本控制二、Git与SVN的主要区别三、下载及使用1.安装2.启动Git3.常用的Linux命令4.Git配置 四、Git基本理论1.三个区域2.工作流程 五、Git项目搭建1.创建工作目录与常用指令2.本地仓库搭建3.克隆远程仓库 六、Git文件操作1.文件的四种状态2.查看文件状…

ElasticSearch最全详细使用教程:入门、索引管理、映射详解

导读&#xff1a;本文介绍了ElasticSearch的必备知识&#xff1a;从入门、索引管理到映射详解。 一、快速入门 1. 查看集群的健康状况 http://localhost:9200/_cat http://localhost:9200/_cat/health?v 说明&#xff1a;v是用来要求在结果中返回表头 状态值说明 Green - eve…

JavaScript基础语法01——初识JavaScript

哈喽&#xff0c;大家好&#xff0c;我是雷工&#xff01; 最近有项目用到KingFusion软件&#xff0c;由于KingFusion是B/S架构的客户端组态软件&#xff0c;因此在学习KingFusion产品时会涉及许多前端的知识。 像JavaScript语言就是需要用的&#xff0c;俗话说&#xff1a;活到…

工单管理报修系统有什么用?的修工单系统助您解决报修难点

随着互联网的快速发展&#xff0c;许多企业都开始使用“的修”工单管理系统&#xff0c;这是一款企业管理软件&#xff0c;可以帮助管理员用户针对不同的机构、单位以及外部客户的需求来选择性地管理、维护及追踪各种各样的问题和请求&#xff0c;也可用作公司内部员工工作上的…

【数据结构与算法 模版】高频题刷题模版

废话不多说&#xff0c;喊一句号子鼓励自己&#xff1a;程序员永不失业&#xff0c;程序员走向架构&#xff01;本篇Blog的主题是【】&#xff0c;使用【】这个基本的数据结构来实现&#xff0c;这个高频题的站点是&#xff1a;CodeTop&#xff0c;筛选条件为&#xff1a;目标公…

nacos在windows和linux的安装(教程都是完全一样的,因为是java写的)

文章目录 nacos下载Java安装&#xff08;作者用的是java8&#xff09;Windows编辑启动脚本文件编辑配置文件集群配置&#xff08;非常简单&#xff09; Linux其他 nacos下载 点击进入github下载页面nacos手册nacos是用java写的&#xff0c;可以跨平台&#xff0c;根本不存在li…

C. Divisor Chain

题目&#xff1a;样例&#xff1a; 输入 3 3 5 14 输出 3 3 2 1 4 5 4 2 1 6 14 12 6 3 2 1 题意&#xff1a; 输入 x &#xff0c;使得 x 一直减某个数值 一直减到 1&#xff0c;所减的这个数值不能出现两次&#xff0c;输出该过程 x 的变化情况。 思路&#xff1a; 我们可…

uniapp项目实战系列(2):新建项目,项目搭建,微信开发工具的配置

目录 系列文章目录uniapp项目实战系列(1)&#xff1a;导入数据库&#xff0c;启动后端服务&#xff0c;开启代码托管&#xff08;点击跳转&#xff09;1.新建项目2.托管项目的操作&#xff1a;&#xff08;无勾选托管项目可无视&#xff09;3.项目编译预览3.1游览器编译3.2微信…

自然语言处理(五):子词嵌入(fastText模型)

子词嵌入 在英语中&#xff0c;“helps”“helped”和“helping”等单词都是同一个词“help”的变形形式。“dog”和“dogs”之间的关系与“cat”和“cats”之间的关系相同&#xff0c;“boy”和“boyfriend”之间的关系与“girl”和“girlfriend”之间的关系相同。在法语和西…

DP读书:不知道干什么就和我一起读书吧

DP读书&#xff1a;不知道干什么就和我一起读书吧 为啥写博客&#xff1a;好处一&#xff1a;记录自己的学习过程优点二&#xff1a;让自己在各大社群里不那么尴尬推荐三&#xff1a;坚持下去&#xff0c;找到一个能支持自己的伙伴 虽然清楚知识需要靠时间沉淀&#xff0c;但在…

KylinOS配置完静态IP地址后,保存按钮是灰色

问题: 配置完静态IP地址后,保存按钮置灰,并且提示“无效设置IPv4设置:ipv4.gateway:网关与”never-default”不兼容”。 原因: 这是由于禁止添加默认路由导致的。 解决方案: 1、使用nmcli命令: nmcli con modify "有线连接 1" ipv4.never-default no 执…

keras深度学习框架构建LeNet5神经网络模型实现手写数字识别

之前两篇文章分别通过keras深度学习框架构建简单神经网络和卷积神经网络实现过手写数字识别实验。这篇文章分享我根据LeNet5模型构建的卷积神经网络来实现手写数字识别。 这个实验是根据LeNet5模型构建卷积神经网络&#xff0c;LeNet5模型的原理图如下所示&#xff1a; 相信大家…

3、DVWA——CSRF

文章目录 一、CSRF概述二、low2.1 通关思路2.2 源码分析 三、medium3.1 通关思路3.2 源码分析 四、high4.1 通关思路4.2 源码分析 五、impossible 一、CSRF概述 CSRF全称为跨站请求伪造&#xff08;Cross-site request forgery&#xff09;&#xff0c;是一种网络攻击方式&…

基于向量加权平均算法优化的BP神经网络(预测应用) - 附代码

基于向量加权平均算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码 文章目录 基于向量加权平均算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码1.数据介绍2.向量加权平均优化BP神经网络2.1 BP神经网络参数设置2.2 向量加权平均算法应用 4.测试结…

华为 连接OSPF和RIP网络---OSPF和RIP网络相互引入

路由引入简介 不同路由协议之间不能直接共享各自的路由信息&#xff0c;需要依靠配置路由的引入来实现。 获得路由信息一般有3种途径&#xff1a;直连网段、静态配置和路由协议。可以将通过这3种途径获得的路由信息引入到路由协议中&#xff0c;例如&#xff0c;把直连网段引入…

vue3+element plus 封装上传组件(图片、文件)

vue3element plus 封装上传组件&#xff08;图片、文件&#xff09; 1、新建封装组件components/upload.vue2、引入upload组件3、效果展示 1、新建封装组件components/upload.vue <template><el-upload v-model:file-list"waitFileList" class"upload…

阿里云矢量图标透明背景转换/展示时变为黑色解决方法

下载了一个矢量图标&#xff0c;背景是透明的 上传到minio然后在前端展示&#xff0c;发现透明&#xff08;白色&#xff09;的地方变成黑色了 处理方法&#xff1a;去除透明的底色。使用window的画图程序打开保存一遍&#xff0c;将透明色转为白色 OK

【UniApp开发小程序】小程序首页完善(滑到底部数据翻页、回到顶端、基于回溯算法的两列数据高宽比平衡)【后端基于若依管理系统开发】

文章目录 说明细节一&#xff1a;首页滑动到底部&#xff0c;需要查询下一页的商品界面预览页面实现 细节二&#xff1a;当页面滑动到下方&#xff0c;出现一个回到顶端的悬浮按钮细节三&#xff1a;商品分列说明优化前后效果对比使用回溯算法实现ControllerService回溯算法 优…

Mac网页开发工具 RapidWeaver 9

RapidWeaver是一款Mac上的网页设计和开发工具&#xff0c;它使用户能够快速创建专业级别的网站&#xff0c;而无需编写代码。 以下是RapidWeaver软件的一些主要特点和功能&#xff1a; 模板和主题&#xff1a;RapidWeaver提供了大量的预先设计好的模板和主题&#xff0c;使用…