天天看点

SpringBoot 学习笔记

常用注解

主程序类:@SpringBootApplication

等同 @SpringBootConfiguration  @EnableAutoConfiguration  @ComponentScan("com.atguigu.boot")

/* 主程序类
 * @SpringBootApplication:这是一个SpringBoot应用*/
@SpringBootApplication
public class MainApplication {
    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class,args);
    }
}      

控制器:@RestController

@RequestMapping("/hello")

@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String handle01(){
        return "Hello, Spring Boot 2!";
    }
}      

配置类:@Configuration

告诉SpringBoot这是一个配置类 == 配置文件

参数 proxyBeanMethods

=false 返回新的实例 配置类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断

=ture  单实例,是默认值,配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,组件依赖必须使用用Full模式

添加组件:@Bean

给容器中添加组件,组件id为方法名

@Bean("componentName")

@Configuration(proxyBeanMethods = false)
public class MyConfig {
    @Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
    public User user01(){
        User zhangsan = new User("zhangsan", 18);
        //user组件依赖了Pet组件
        zhangsan.setPet(tomcatPet());
        return zhangsan;
    }


################################@Configuration测试代码如下########################################
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.atguigu.boot")
public class MainApplication {

    public static void main(String[] args) {
        //1、返回我们IOC容器
        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);

        //2、查看容器里面的组件
        String[] names = run.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
        }

        //3、从容器中获取组件

        Pet tom01 = run.getBean("tom", Pet.class);
        Pet tom02 = run.getBean("tom", Pet.class);
        System.out.println("组件:"+(tom01 == tom02));

        //4、com.atguigu.boot.config.MyConfig$$EnhancerBySpringCGLIB$$51f1e1ca@1654a892
        MyConfig bean = run.getBean(MyConfig.class);
        System.out.println(bean);

        //如果@Configuration(proxyBeanMethods = true)代理对象调用方法。SpringBoot总会检查这个组件是否在容器中有。
        //保持组件单实例
        User user = bean.user01();
        User user1 = bean.user01();
        System.out.println(user == user1);


        User user01 = run.getBean("user01", User.class);
        Pet tom = run.getBean("tom", Pet.class);

        System.out.println("用户的宠物:"+(user01.getPet() == tom));

    }
}      

自动创建组件:@Import

给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名

@Import({User.class, DBHelper.class})
@Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
public class MyConfig {
}      

条件配置:@Conditionalxxx

@Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
//@ConditionalOnBean(name = "tom")
@ConditionalOnMissingBean(name = "tom")
public class MyConfig {


    /**
     * Full:外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
     * @return
     */

    @Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
    public User user01(){
        User zhangsan = new User("zhangsan", 18);
        //user组件依赖了Pet组件
        zhangsan.setPet(tomcatPet());
        return zhangsan;
    }

    @Bean("tom22")
    public Pet tomcatPet(){
        return new Pet("tomcat");
    }
}

public static void main(String[] args) {
        //1、返回我们IOC容器
        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);

        //2、查看容器里面的组件
        String[] names = run.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
        }

        boolean tom = run.containsBean("tom");
        System.out.println("容器中Tom组件:"+tom);

        boolean user01 = run.containsBean("user01");
        System.out.println("容器中user01组件:"+user01);

        boolean tom22 = run.containsBean("tom22");
        System.out.println("容器中tom22组件:"+tom22);


    }      

原生配置引入:@ImportResource

@ImportResource("classpath:beans.xml")
public class MyConfig {}

======================测试=================
        boolean haha = run.containsBean("haha");
        boolean hehe = run.containsBean("hehe");
        System.out.println("haha:"+haha);//true
        System.out.println("hehe:"+hehe);//true      

扫描位置:@ComponentScan

配置绑定 :@ConfigurationProperties

原始写法:

public class getProperties {
     public static void main(String[] args) throws FileNotFoundException, IOException {
         Properties pps = new Properties();
         pps.load(new FileInputStream("a.properties"));
         Enumeration enum1 = pps.propertyNames();//得到配置文件的名字
         while(enum1.hasMoreElements()) {
             String strKey = (String) enum1.nextElement();
             String strValue = pps.getProperty(strKey);
             System.out.println(strKey + "=" + strValue);
             //封装到JavaBean。
         }
     }
 }      
/**
 * 只有在容器中的组件,才会拥有SpringBoot提供的强大功能
 */
@Component
@ConfigurationProperties(prefix = "mycar")
public class Car {
    private String brand;
    private Integer price;
}      

yaml写法

@Component
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
@ConfigurationProperties(prefix = "user")
public class User {
    private String username;
    private int age;
    private Pet pet;
    private List<Pet> pets;
    private String[] courses;
}      
user:
  age: 12
  pet:
    name: ap
    age: 3
  pets:
    - {name: bp, age: 4}
    - {name: cp, age: 5}
  courses: ['math', 'chinese', 'english']
  username: Jack

server:
  port: 8081      

配置提示和优化

<!--配置提示-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

<plugin> 
  <groupId>org.springframework.boot</groupId>  
  <artifactId>spring-boot-maven-plugin</artifactId>  
  <configuration> 
    <excludes> 
      <!--打包时排除配置的提示,优化JVM启动-->  
      <exclude> 
        <groupId>org.springframework.boot</groupId>  
        <artifactId>spring-boot-configuration-processor</artifactId> 
      </exclude> 
    </excludes> 
  </configuration> 
</plugin>      

配置连接池

方案1 java 代码注入

jdbc.properties

jdbc.driver: com.mysql.jdbc.Driver
jdbc.url: jdbc:mysql://192.168.31.133:3306/boot
jdbc.username: jack
jdbc.password: jack      

配置类

@Configuration
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    @Bean
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }

}      

注入 controller

    @Autowired
    private DataSource dataSource;      

方案2 属性注入

@Bean
@ConfigurationProperties(prefix = "jdbc")
public DataSource dataSource() {
    return new DruidDataSource();
}      

application.properties

jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://192.168.31.133:3306/mybatis
jdbc.username=jack
jdbc.password=jack      

静态资源访问

只要静态资源放在类路径下: /static (or  /publicor/resourcesor/META-INF/resources`

访问 : 当前项目根路径/ + 静态资源名

改变默认的静态资源路径

spring:
  mvc:
    static-path-pattern: /res/**

  resources:
    static-locations: [classpath:/haha/]      

静态资源访问前缀

 默认:/**
  web:
    resources:
      static-locations: [classpath:/haha]      

webjar 自动映射

https://www.webjars.org/

访问地址:http://localhost:8080/webjars/jquery/3.5.1/jquery.js  后面地址要按照依赖里面的包路径

YML 配置文件

application.yml

jdbc:
  driverClassName: com.mysql.cj.jdbc.Driver
  url: jdbc:mysql://192.168.31.133/boot
  username: jack
  password: jack


spring:
  profiles:
    active:
      1      

配置多个 yml 文件

application-1.yml

user:
  name: "杨青林"
  email: [email protected]      

配置日志

需要输出日志的类上添加注解 @Slf4j

@Slf4j
public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.debug("MyInterceptor ----  preHandle");
        return true;
    }
}      
logging:
  level:
    cn.lin: debug
    org.spring: info      

配置拦截器

编写拦截器类

@Slf4j
public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, 
    	HttpServletResponse response, Object handler) throws Exception {
    	
        log.debug("MyInterceptor ----  preHandle");
        return true;
    }
}      

springmvc配置类

@Configuration
public class SpringmvcConfig implements WebMvcConfigurer {

    // 注册拦截器到 Spring IOC 容器中
    @Bean
    public MyInterceptor myInterceptor() {
        return new MyInterceptor();
    }

    // 将拦截器添加到拦截器链
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myInterceptor());
    }
}      

整合mybatis

事务配置

添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>      

添加注解

@Transactional

配置Hikari连接池

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>      

配置 application.yml

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.31.133/springboot_test
    username: jack
    password: jack      

添加mybatis场景启动器

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.4</version>
</dependency>      

mybatis

编写application.yml

mybatis:
  #  实体类别名路径
  type-aliases-package: cn.lin.pojo
  #  映射文件目录
  #  mapper-locations:
  configuration:
    #  控制台输出 sql
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl      

扫描mybatis的mapper接口

  • 启动类中添加注解 @MapperScan (推荐)
  • 在Mapper接口中添加注解 @Mapper

整合通用Mapper

<dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper-spring-boot-starter</artifactId>
    <version>2.1.5</version>
</dependency>      

编写实体类

@Data
@Table(name = "tb_user")
public class User {
    @Id
    @KeySql(useGeneratedKeys = true)
    private Long id;
    private String user_name;
    private String password;
    private String name;
    private Integer age;
    private Short sex;
    private Date birthday;
    private String note;
    private Date created;
    private Date updated;
}      

配置包扫描

@SpringBootApplication
@MapperScan("cn.lin.mapper")
public class Application {}      

测试代码

@GetMapping("/{id}")
public User queryById(@PathVariable Long id) {
    log.debug("queryById");
    return userService.queryByID(id);
}


@Transactional
public User queryByID(Long id) {
    return userMapper.selectByPrimaryKey(id);
}      

整合redis

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>      

配置application.yml

spring:
  redis:
    host: 192.168.31.133
    port: 6379      
public class RedisTest {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    public void test(){
        //string 字符串
        //redisTemplate.opsForValue().set("str", "heima");
        redisTemplate.boundValueOps("str").set("heima");
        System.out.println("str = " + redisTemplate.opsForValue().get("str"));

        //hash 散列
        redisTemplate.boundHashOps("h_key").put("name", "heima");
        redisTemplate.boundHashOps("h_key").put("age", 13);
        //获取所有域
        Set set = redisTemplate.boundHashOps("h_key").keys();
        System.out.println(" hash散列的所有域:" + set);
        //获取所有值
        List list = redisTemplate.boundHashOps("h_key").values();
        System.out.println(" hash散列的所有域的值:" + list);

        //list 列表
        redisTemplate.boundListOps("l_key").leftPush("c");
        redisTemplate.boundListOps("l_key").leftPush("b");
        redisTemplate.boundListOps("l_key").leftPush("a");
        //获取全部元素
        list = redisTemplate.boundListOps("l_key").range(0, -1);
        System.out.println(" list列表中的所有元素:" + list);

        // set 集合
        redisTemplate.boundSetOps("s_key").add("a", "b", "c");
        set = redisTemplate.boundSetOps("s_key").members();
        System.out.println(" set集合中的所有元素:" + set);

        // sorted set 有序集合
        redisTemplate.boundZSetOps("z_key").add("a", 30);
        redisTemplate.boundZSetOps("z_key").add("b", 20);
        redisTemplate.boundZSetOps("z_key").add("c", 10);
        set = redisTemplate.boundZSetOps("z_key").range(0, -1);
        System.out.println(" zset有序集合中的所有元素:" + set);
    }
}      

简化开发

Lombok

<!--简化JavaBean开发-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>      

dev-tools

<!--Ctrl+F9刷新项目-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
</dependency>      

log4j

<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE >
ALL -->
<!--Configuration 后面的 status 用于设置 log4j2 自身内部的信息输出,可以不设置,
当设置成 trace 时,可以看到 log4j2 内部各种详细输出-->
<configuration status="INFO">
    <!--先定义所有的 appender-->
    <appenders>
        <!--输出日志信息到控制台-->
        <console name="Console" target="SYSTEM_OUT">
            <!--控制日志输出的格式-->
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-
5level %logger{36} - %msg%n"/>
        </console>
    </appenders>
    <!--然后定义 logger,只有定义 logger 并引入的 appender,appender 才会生效-->
    <!--root:用于指定项目的根日志,如果没有单独指定 Logger,则会使用 root 作为
    默认的日志输出-->
    <loggers>
        <root level="info">
            <appender-ref ref="Console"/>
        </root>
    </loggers>
</configuration>      

继续阅读