SpringBoot

Posted 364.99°

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot相关的知识,希望对你有一定的参考价值。

目录

前言

springboot: springboot整合了所有框架,并默认配置了很多框架的使用方式。

本文主要是从实际开发的角度来写springboot相关的内容,当前并未更新完,会持续更新。

1.模块一

1. 基础依赖

<dependencies>
    <!--核心依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--导入配置文件处理器,配置文件进行绑定就会有提示-->
    <dependency>
        groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

<!-- 
	这个插件,可以将应用打包成一个可执行的jar包;
	直接使用 java -jar 进行打包
-->
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>
  • spring-boot-starter
    • springboot场景启动器,帮我们导入模块正常运行所依赖的组件
    • springboot会将所有的功能场景都抽取出来,做成一个个starter,只需要在项目中引入starter,相关的所有依赖都会自动导入

2. SpringBootApplication注解

@SpringBootApplication 
	- 标注一个主程序类,说明这是一个springboot应用
    - springboot运行改类的main方法来启动springboot应用
    - 由三个注解构成(除去四个元注解之外):@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan
  • @SpringBootConfiguration
    	- 标注在类上,表明这是一个springboot配置类
        - 底层是@Configuration
    
  • @EnableAutoConfiguration
    	- 开启自动配置功能的注解
        - 其底层由两个注解构成:
            - @AutoConfigurationPackage 自动配置包
              将添加该注解的类所在的package作为 自动配置package 进行管理
            - @Import(AutoConfigurationImportSelector.class) 
              - 将 AutoConfigurationImportSelector类 导入到spring容器中
              - AutoConfigurationImportSelector类 可以帮助springboot应用将所有符合条件(@Conditional)的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器
              	- 需要导入的组件会以全类名的方式返回,然后添加到容器中;同时会给容器中加入很多自动配置类 xxxAutoConfiguration(免去我们手动配置的过程)
              	- springboot会在启动的时候从类路径 META-INF/spring.factories 中获取 EnableAutoConfiguration 指定的值,将这些值自动配置导入容器中
    
  • @ComponentScan
    	- 定义扫描的路径从中找出标识了需要装配的类自动装配到spring的bean容器中
    	- 默认装配标识了@Component注解的类到spring容器中
    	- @Component的派生注解有:@Controller@Service@Repository
    

3. Conditional注解

@Conditional
	- 按照一定的条件进行判断,满足条件给容器注册bean,配置配里面的内容才生效
	- 加在方法上(和@Bean搭配使用): 表明要满足对应条件,才注册此方法的组件
	- 加在类上(搭配@Component使用): 表明要满足对应条件,此配置类才会生效

派生注解:

注解说明
@ConditionalOnJava系统的java版本符合要求
@ConditionalOnBean容器中存在指定的Bean
@ConditionalOnMissingBean容器中不存在指定的Bean
@ConditionalOnExpression满足SpEL表达式指定
@ConditionalOnClass系统中有指定的类
@ConditionalOnMissingClass系统中没有指定的类
@ConditionalOnSingleCandidate容器中只有一个指定的Bean,或者这个Bean是首选Bean
@ConditionalOnProperty 系统中指定的属性有指定的值
@ConditionalOnResource 类路径下存在指定资源文件
@ConditionalOnWebApplication 当前是web环境
@ConditionalOnNotWebApplication当前不是web环境
@ConditionalOnJndiJNDI存在指定项

5. Bean注解

@Bean
	- 用于方法方法上:产生一个Bean对象,然后这个Bean对象交给Spring管理
		- 产生这个Bean对象的方法Spring只会调用一次,随后这个Spring将会将这个Bean对象放在自己的IOC容器中
		- 搭配@Scope("prototype") 可以使得方法被多次调用,每次都实例一个Bean对象
	- 用于注解上:在运行时提供注册

4. yml配置文件

1.格式

格式:key: value

  • 缩进:

    # 对象:
    man:
     tom:
      name: 汤姆
      age: 17
    # 数组
    roles:
     - jack
     - rose
    
  • 字符串默认不加引号

    • ‘’:会转义特殊字符:a: '\\n' 输出:\\n
    • “”:不会转义特殊字符:a: '\\n' 输出:换行
  • 占位符

    num: 16
    human:
     name: 李四
    
    man:
     name: $human.name
     age: $num
     salary: $random.int 
    

2.加载与读取

加载配置文件:

  • 加载指定的配置文件:@PropertySource(value = "classpath: 配置文件名.后缀")

  • 导入Spring的配置文件(springmvc.xml、spring.xml):@ImportResource( locations = "classpath = bean.xml" )放在主入口函数的类上

读取配置文件:

  • 类读取配置文件 @ConfigurationProperties(prefix = "xxx")

    tom:
     name: 汤姆
     num: 17.00
    
    /**
     * @Component 注册为一个组件,只有容器中的组件才能享有springboot提供的各种功能
     * @ConfigurationProperties 
     * 		- 将该类中的所有属性与配置文件中的相关配置进行绑定
     *		- prefix = "xxx" 与配置文件中哪一个key下的所有属性进行一一映射
     */
    @PropertySource(value = "classpath: person.yml")
    @Component
    @ConfigurationProperties(prefix = "tom")
    public class Tom 
        private String name;
        private double num;
    
    
  • 属性读取配置文件 @Value("$xxx")

    tom:
     name: 汤姆
     num: 17.00
    
    /**
     * @Value("$") 获取对应属性文件中定义的属性值
     * @Value("#") 表示 SpEl 表达式通常用来获取 bean 的属性,或者调用 bean 的某个方法
     *
     */
    @Component
    public class Tom 
        @Value("$tom.name")
        private String name;
        @Value(@Value("# T(java.lang.Math).random() * 100.0 "))
        private String age;
    
    

3.profile

在实际项目中,配置文件可能会有多个,如下图,这时候就需要通过spring.profile.active指定生效的文件了

spring:
  profiles:
    active: dev,datasource,websecurity,token

4.加载

配置文件的加载优先级(从高到低):
springboot启动后会扫描application.properties或者application.yml文件作为springboot的默认配置文件

  • 高优先级的配置文件内容会覆盖低优先级的

  • springboot中的classpath路径为

    • src/main/java
    • src/main/resouces
  • springboot中的classpath*除了上述两个路径,还包含:

    • 第三方jar包的根路径
  • file: ./config/
  • file:./
  • classpath:/config/
  • classpath:./

5. Slf4j日志

依赖:

        <!--提供Slf4j日志-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

使用:

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class LogDemo 
	public static String test() 
		logger.trace("trace日志");
        logger.debug("debug日志");
        logger.info("info日志");
        logger.warn("warn日志");
        logger.error("error日志");
        return "日志系统";
	

  • 默认日志级别是:info
  • 可在配置文件中通过如下配置设置默认日志级别
    logging:
      level:
        com:
          example:
            demo: warn
    

2.模块二

1. json接口

1. 代码实例

代码:

import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author: chenJY
 * @Description:
 * @Date: 2022-10-25 15:27
 */
@RestController // 这里也可以直接用@Controller
@RequestMapping("/boot")
public class Controller 
    @PostMapping("/chgGend")
    public Object chgGend(@RequestBody Map<String, Object> params) 
        Object gend = params.get("gend");
        if (gend.equals("1")) 
            params.put("gend", "男");
         else if (gend.equals("0")) 
            params.put("gend", "女");
         else 
            params.put("gend", "性别未知");
        
        return params;
    

    @PostMapping("/chgName")
    public Map<String, Object> chgName(
            @RequestParam(value = "gend", required = false, defaultValue = "男") String gend,
            @RequestParam("name") String name) 
        Map<String, Object> res = new HashMap<>();
        String resName =  name == "张三" ? "法外狂徒" : name;
        res.put("name", resName);
        res.put("gend", gend);
        return res;
    

接口测试:

2. RequestBody注解和RequestParam注解

@RequestBody
	- 主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的)
	- 一般都用POST方式进行提交
	- 一个请求,只有一个RequestBody
	- 可以和@RequestParam()同时使用

@RequestParam
	- 获取请求中的参数(不支持post请求)
	- value 请求中的参数名
	- required 是否必传该参数
	- defaultValue 当请求中没有传递该参数的时候的默认值(需要与required 搭配使用)

两者对比:

注解支持的类型支持的请求类型支持的Content-Type请求示例
@RequestParamurlGET所有chgName?name=张三
@RequestBodyBodyPOST/PUT/DELETE/PATCHjson“name”: “张三”

2.Filter

1.代码实例

import lombok.extern.slf4j.Slf4j;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * @Author: chenJY
 * @Description:
 * @Date: 2022-10-25 16:18
 */
@Slf4j
@Order(1)
@WebFilter(urlPatterns = "/*")
public class RequestFilter implements Filter 

    @Override
    public void init(FilterConfig filterConfig) throws ServletException 
        log.info("过滤器初始化......");
    

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException 
        log.info("过滤器执行......");
        chain.doFilter(request, response);
    

    @Override
    public void destroy() 
        log.info("过滤器销毁......");
    

记得在主程序上加上注解@ServletComponentScan,不然过滤器无法生效。

启动项目,过滤器初始化:

发送请求,过滤器执行:

结束程序,过滤器销毁:

2. 小结

  • 过滤器工作流程:

  • 注解:

    @WebFilter(urlPatterns = "/*") 
    	- 将一个类声明为过滤器,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为过滤器
    	- 常用属性
    		- urlPatterns 指定一组过滤器的url匹配模式
    		- value等同于urlPatterns,但两者不能同时使用
    		- servletNames 指定过滤器将应用于哪些servlet
    		以上三个属性,至少得使用一个
    		- initParams 指定一组过滤器初始化参数
    
    @Order(1) 
    	- 设置过滤器的优先级,数值越小,优先级越高
    
  • 方法:

    • init

      • 初始化过滤器,可以在init()方法中获取Filter中的初始化参数
      • 只在应用启动的时候执行一次
    • doFilter

      • 完成过滤操作,当请求发过来的时候,过滤器将执行doFilter方法
      • 每次发送请求都会执行
    • destroy

      • Filter对象创建后会驻留在内存,当web应用移除或服务器停止时调用destroy()方法进行销毁
      • 仅执行一次,执行后可以释放过滤器占用的资源

3.在配置类中注册filter

public class RequestFilter implements Filter 

    @Override
    public void init(FilterConfig filterConfig) throws ServletException 
        log.info("过滤器初始化......");
    

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException 
        log.info("过滤器执行......");
        chain.doFilter(request, response);
    

    @Override
    public void destroy() 
        log.info("过滤器销毁......");
    

import com.example.sb_demo.common.filter.RequestFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Author: chenJY
 * @Description:
 * @Date: 2022-10-25 16:52
 */
@Configuration
public class WebConfiguration 
    @Bean
    public FilterRegistrationBean filterRegistrationBean() 
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(new RequestFilter());
        registrationBean.addUrlPatterns("/*");
        registrationBean.addInitParameter("paramName", "paramValue");
        registrationBean.setName("RequestFilter");
        registrationBean.setOrder(1);
        return registrationBean;
    

可以在配置类中注册多个过滤器,通过setOrder指定其优先级,如下:

    @Bean
    public FilterRegistrationBean filterRegistrationBean1() 
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(new RequestFilter());
        ...
        registrationBean.setOrder(1);
        return registrationBean;
    
    @Bean
    public FilterRegistrationBean filterRegistrationBean1() 
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(new AnotherFilter());
        ...
        registrationBean.setOrder(2);
        return registrationBean;
    

3. Interceptor

拦截器类(implements HandlerInterceptor):

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * @Author: chenJY
 * @Description:
 * @Date: 2022-10-26 7:58
 */
@Slf4j
public class LoginInterceptor implements HandlerInterceptor 

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception 
        log.info("执行了拦截器的preHandle方法");
        String userName = request.getParameter("name");
        Object password = request.getParameter("password");
        if (userName.equals("张三") && password.equals("123456")) 
            log.info("身份验证通过");
            return true;
        
        return false;
    


    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception 
        log.info("执行了拦截器的postHandle方法");
    


    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception 
        log.info("执行了拦截器的afterCompletion方法");
    

WebMvcConfig(implements WebMvcConfigurer

import com.example.sb_demo.common.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @Author: chenJY
 * @Description:
 * @Date: 2022-10-26 8:07
 */
public class WebMvcConfig implements WebMvcConfigurer 
    @Override
    public void addInterceptors(InterceptorRegistry registry) 
        InterceptorRegistration registration = registry.addInterceptor(new LoginInterceptor());
        /*
            addPathPatterns 需要拦截的url
            excludePathPatterns 不需要拦截的url
         */
        registration以上是关于SpringBoot的主要内容,如果未能解决你的问题,请参考以下文章

java算汤姆猫体重实现的功能

我读汤姆大叔的深入理解js

iOS_5_汤姆猫

如何开发像会说话的汤姆猫一样的语音识别应用程序

汤姆大叔的博客-menu

洛谷 P1796 汤姆斯的天堂梦_NOI导刊2010提高(05)