SpringBoot基础知识

目录

创建SpringBoot项目

测试Controller

单元测试

读取配置

获取默认配置文件中的内容

修改配置文件

不同环境使用不同配置文件

自动装配

事件监听

SpringBoot JDBC

SpringBoot AOP

SpringBoot Redis

SpringBoot监控和度量

SpringBoot整合Mybatis


工具:Intellij

版本:2.1.10

创建SpringBoot项目

项目创建成功后,目录如下:

相关配置如端口号等可以写在application.properties中,SpringBoot项目默认端口号8080,因为这个端口号容易冲突,所以我们改为9999。

测试Controller

在Controller层可能会用到的注解:@RestController、@RequestMapping、@GetController、@PostController、@PutController、@DeleteController、@RequestBody,@RequestParam、@Autowired。

新建web目录,创建测试Controller类如下

@RestController("/builder")
public class BuilderController {
    @GetMapping("/test")
    public String test() {
        return "OK";
    }
}

运行启动类,控制台输入如下内容,说明项目启动成功。

从浏览器中输入http://localhost:9999/builder/test进行访问,返回OK说明接口调用成功。

单元测试

选中上一步创建的BuilderController类,按下右键 -> go to -> Test创建单元测试类,也可在待测试的类内部按下 alt + insert 键,在弹窗中选中Test来创建测试类。在测试类上使用注解@RunWith(SpringRunner.class) 和@SpringBootTest,使得测试类可单独运行。使用@Autowired注解自动注入待测试的类,在测试方法上使用@Test注解,然后在测试方法中调用被测试的方法即可。

@RunWith(SpringRunner.class)
@SpringBootTest
public class BuilderControllerTest {
    @Autowired
    private BuilderController controller;
    @Test
    public void test1() {
        System.out.println(controller.test());
    }
}

点击运行test1方法,运行过程中没有报错,且运行结果正确,说明单元测试通过。如果在测试之前需要提前加载一些资源如配置等,可在测试类中使用@Beafore注解来实现。

@RunWith(SpringRunner.class)
@SpringBootTest
public class BuilderControllerTest {

    private String name;

    @Autowired
    private TestConfig testConfig;

    /**
     * 使用该注解加载测试需要的资源
     */
    @Before
    public void init() {
        name = testConfig.getServerName();
    }

    @Autowired
    private BuilderController controller;
    @Test
    public void test1() {
        System.out.println(name);
        System.out.println(controller.test());
    }
}

读取配置

获取默认配置文件中的内容

Springboot默认配置文件名为application.properties,也可将properties改为yml,默认配置文件路径为classpath根目录,也可将其配置在classpath:/config、file:/或者file:/config目录下。

读取配置以及加载配置类可能用到的注解:@Value、@Configuration、@Component、@PropertySources、@PropertySource、@ConfigurationProperties等。

@Component
public class TestConfig {
    /**
     * 使用该注解获取配置
     */
    @Value("${server.name}")
    private String serverName;

    /**
     * 注入环境配置类,可以从配置类中获取属性
     */
    @Autowired
    private Environment environment;

    public String getServerName() {
        return serverName;
    }

    public void print() {
        System.out.println(serverName + ", " + environment.getProperty("server.host"));
    }
}

修改配置文件

加载单个配置文件

在classpath下创建db/db.properties配置,如果想读取到该配置文件的内容,就需要先加载该配置文件。

@Configuration
@PropertySource("classpath:db/db.properties")
public class DbConfiguration {
    @Value("${db.name}")
    private String dbName;
    @Value("${db.username}")
    private String dbUsername;
    @Value("${db.password}")
    private String dbPassword;

    public String print() {
        return "DbConfiguration{" +
                "dbName='" + dbName + '\'' +
                ", dbUsername='" + dbUsername + '\'' +
                ", dbPassword='" + dbPassword + '\'' +
                '}';
    }
}

一次加载多个配置文件

按照上述方法创建db1.properties和db2.properties文件,在配置类中加载这两个文件并获取属性值。

@Configuration
@PropertySources({
        @PropertySource("classpath:db/db1.properties"),
        @PropertySource("classpath:db/db2.properties")
})
public class DbConfiguration1 {
    @Value("${db1.name}")
    private String dbName1;
    @Value("${db1.username}")
    private String dbUsername1;
    @Value("${db1.password}")
    private String dbPassword1;
    @Value("${db2.name}")
    private String dbName2;
    @Value("${db2.username}")
    private String dbUsername2;
    @Value("${db2.password}")
    private String dbPassword2;

}

注入集合

在配置文件中添加配置数组

@PropertySource("classpath:db/db.properties")
@Configuration
@ConfigurationProperties("ds")
public class DbConfiguration2 {
    /**
     * 集合名必须与配置文件中的数组名一致,且必须有get和set方法
     */
    private List<DbCollection> db;

    /**
     * Map名称必须与配置文件中的一致
     */
    private Map<String, String> ds1;

    private Map<String, String> ds2;

    public List<DbCollection> getDb() {
        return db;
    }

    public void setDb(List<DbCollection> db) {
        this.db = db;
    }

    public Map<String, String> getDs1() {
        return ds1;
    }

    public void setDs1(Map<String, String> ds1) {
        this.ds1 = ds1;
    }

    public Map<String, String> getDs2() {
        return ds2;
    }

    public void setDs2(Map<String, String> ds2) {
        this.ds2 = ds2;
    }
}

public class DbCollection {
    private String username;
    private String password;
    private String host;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getHosts() {
        return host;
    }

    public void setHosts(String host) {
        this.host = host;
    }

}

不同环境使用不同配置文件

新建配置文件application-dev.properties,在默认配置文件中新增配置spring.profiles.active=dev,即可将配置文件切换为-dev文件。

@Component
public class EnvConfiguration {
    /**
     * 从-dev配置文件中获取app.name
     */
    @Value("${app.name}")
    private String address;

    public String getAddress() {
        return address;
    }
}

自动装配

非自动装配体

public interface OssService {
}
public class AliOssService implements OssService {
}
public class HuaweiOssService implements OssService {
}
@Configuration
public class OssConfiguration {

    @Bean
    public OssService createAliOssService() {
        return new AliOssService();
    }

    @Bean
    public OssService createHuaweiOssService() {
        return new HuaweiOssService();
    }

}

按条件自动装配

使用@Conditional注解

public class AliOssCondition implements Condition {
    /**
     * 返回true,则装配AliOssService
     */
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        String oss = System.getProperty("oss.type");
        return null != oss && oss.equals("ali");
    }
}

public class HuaweiOssCondition implements Condition {
    /**
     * 返回true,则装配HuaweiOssService
     */
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        String oss = System.getProperty("oss.type");
        return null != oss && oss.equals("huawei");
    }
}

@SpringBootConfiguration
public class OssConfiguration {

    @Bean
    @Conditional(AliOssCondition.class)
    public OssService createAliOssService() {
        return new AliOssService();
    }

    @Bean
    @Conditional(HuaweiOssCondition.class)
    public OssService createHuaweiOssService() {
        return new HuaweiOssService();
    }

}

@Conditional注解可以作用在方法上,也可以作用在类上。作用于方法时,值对方法返回的对象按条件装配体,作用在类上时,对类中所有方法返回的对象都按条件装配。

public class OssCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        String oss = System.getProperty("file.server.type");
        return null != oss && oss.equals("oss");
    }
}

@SpringBootConfiguration
@Conditional(OssCondition.class)
public class OssConfiguration {

    @Bean
//    @Conditional(AliOssCondition.class)
    public OssService createAliOssService() {
        return new AliOssService();
    }

    @Bean
//    @Conditional(HuaweiOssCondition.class)
    public OssService createHuaweiOssService() {
        return new HuaweiOssService();
    }

}

@Conditional可接收一个数组,一次可传入多个Condition,当传入的Condition中的matches都返回true时,对类中所有方法返回的对象都进行装配。

@SpringBootConfiguration
@Conditional({AliOssCondition.class, HuaweiOssCondition.class})
public class OssConfiguration {

    @Bean
//    @Conditional(AliOssCondition.class)
    public OssService createAliOssService() {
        return new AliOssService();
    }

    @Bean
//    @Conditional(HuaweiOssCondition.class)
    public OssService createHuaweiOssService() {
        return new HuaweiOssService();
    }

}

还可使用org.springframework.boot.autoconfigure.cloud包下的@ConditionalOnProperty、@ConditionalOnClass、@ConditionalOnBean等注解进行装配。

@SpringBootConfiguration
public class OssConfiguration {

    /**
     * 当已加载的配置文件中存在oss.type且值为ali时装配该对象
     */
    @Bean
    @ConditionalOnProperty(name = "oss.type", havingValue = "ali")
    public OssService createAliOssService() {
        return new AliOssService();
    }

    /**
     * 当已加载的配置文件中不存在oss.type时装配
     */
    @Bean
    @ConditionalOnProperty(name = "oss.type", havingValue = "ali", matchIfMissing = true)
    public OssService createHuaweiOssService() {
        return new HuaweiOssService();
    }

    /**
     * 当存在HuaweiOssCondition时装配
     */
    @Bean
    @ConditionalOnClass(HuaweiOssCondition.class)
    public OssService createHuaweiOssService1() {
        return new HuaweiOssService();
    }

    /**
     * 当存在huaweiCondition的bean时装配
     */
    @Bean
    @ConditionalOnBean(name = "huaweiCondition")
    public OssService createHuaweiOssService2() {
        return new HuaweiOssService();
    }

    /**
     * 当存在HuaweiOssCondition类型的bean时装配
     */
    @Bean
    @ConditionalOnBean(HuaweiOssCondition.class)
    public OssService createHuaweiOssService3() {
        return new HuaweiOssService();
    }

}

装配没有加注解的bean

事件监听

流程:

  • 自定义事件,一般是继承ApplicationEvent抽象类;
  • 定义事件监听器,有多种实现方式,并且对同一个事件可创建多个监听器;
  • 发布事件。

实现方式1:通过ConfigurableApplicationContext对象添加并发布事件。

/**
 * 定义一个事件
 */
public class MyEvent extends ApplicationEvent implements Serializable {

    private static final long serialVersionUID = 1L;

    public MyEvent(Object source) {
        super(source);
    }
}

/**
 * 定义一个监听器
 */
public class MyEventListener implements ApplicationListener<MyEvent> {
    @Override
    public void onApplicationEvent(MyEvent myEvent) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("接收到事件【" + myEvent.getClass().getName() + "】,实现相关业务逻辑。");
    }
}

@SpringBootApplication
public class ManagementApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(ManagementApplication.class, args);
        // 添加监听器
        context.addApplicationListener(new MyEventListener());
        // 发布事件
        context.publishEvent(new MyEvent(new Object()));
    }
}

实现方式2:直接将监听器托管给Spring,再使用ConfigurableApplicationContext对象发布事件。

/**
 * 定义一个监听器
 */
@Component
public class MyEventListener implements ApplicationListener<MyEvent> {
    @Override
    public void onApplicationEvent(MyEvent myEvent) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("接收到事件【" + myEvent.getClass().getName() + "】,实现相关业务逻辑。");
    }
}

@SpringBootApplication
public class ManagementApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(ManagementApplication.class, args);
        // 发布事件
        context.publishEvent(new MyEvent(new Object()));
    }
}

实现方式3:使用@EventListener注解而不实现ApplicationListener接口,然后使用ConfigurableApplicationContext对象发布事件。

/**
 * 定义一个监听器
 */
@Component
public class MyEventListener {
    @EventListener
    public void onApplicationEvent(MyEvent myEvent) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("接收到事件【" + myEvent.getClass().getName() + "】,实现相关业务逻辑。");
    }
}

@SpringBootApplication
public class ManagementApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(ManagementApplication.class, args);
        // 发布事件
        context.publishEvent(new MyEvent(new Object()));
    }
}

实例:用户注册成功后发送邮件通知。

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    @PostMapping("/register")
    public User register(@RequestBody User user) {
        return userService.register(user);
    }
}

@Service
public class UserService {
    @Autowired
    private ConfigurableApplicationContext context;

    public User register(User user) {
        System.out.println("将数据【" + user.toString() + "】添加到数据库。");
        context.publishEvent(new UserRegisterEvent<User>(user));
        return user;
    }
}

public class UserRegisterEvent<User> extends ApplicationEvent {
    public UserRegisterEvent(User source) {
        super(source);
    }
}

@Component
public class UserRegisterListener {
    @EventListener
    public void sendEmail(UserRegisterEvent<User> event) {
        User user = (User) event.getSource();
        System.out.println("用户【" + user.getUsername() + "】注册成功,发送邮件【" + user.getEmail() + "】");
    }
}

SpringBoot JDBC

引入jar包

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
    <version>RELEASE</version>
    <scope>compile</scope>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>6.0.6</version>
</dependency>

配置

/**
 * 加载数据库配置,也可获取到配置文件属性后,在该类中再进行详细配置
 */
@Configuration
@PropertySource("classpath:config/database.properties")
public class DBConfig {
}

使用

@Repository
public class UserDao {
    /**
     * 直接注入jdbcTemplate,使用该对象进行数据库操作
     */
    @Autowired
    private JdbcTemplate jdbcTemplate;

    public User queryByUsername(String username) {
        // 查询示例
        RowMapper<User> rowMapper = BeanPropertyRowMapper.newInstance(User.class);
        return jdbcTemplate.query("select * from user where username = '" + username + "'", rowMapper).get(0);
    }
}

SpringBoot AOP

Aop用途:日志记录、权限处理、性能统计、监控、事务处理、异常处理等。

可能使用的注解:@Aspect、@Pointcut、@Before、@After、@AfterReturning、@AfterThrowing等。

添加依赖

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

定义切面和通知

@Component
@Aspect
public class LogAspect {
    /**
     * 定义切面,..*.*(..)表示对management包以及子包下的任何类中任何方法都有效
     */
    @Pointcut("execution(* com.builder.management..*.*(..))")
    public void log() {
    }

    /**
     * 前置通知
     */
    @Before("log()")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("before class: " + joinPoint.getTarget() + "...method: " + joinPoint.getSignature().getName());
    }

    /**
     * 后置通知
     */
    @After("log()")
    public void logAfter(JoinPoint joinPoint) {
        System.out.println("after class: " + joinPoint.getTarget() + "...method: " + joinPoint.getSignature().getName());
    }

    @AfterReturning(returning = "ret", pointcut = "log()")
    public void afterReturning(Object ret) {
        System.out.println("returning: " + ret);
    }

    @AfterThrowing("log()")
    public void logAfterThrowing(JoinPoint joinPoint) {
        System.out.println("throwing: " + joinPoint.getSignature().getName());
    }

}

使用

/**
 * 该类在management包下,所以切面对该类有效
 */
@Repository
public class UserDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 在执行该方法前、后以及返回后进行相关的通知
     */
    public User queryByUsername(String username) {
        RowMapper<User> rowMapper = BeanPropertyRowMapper.newInstance(User.class);
        return jdbcTemplate.query("select * from user where username = '" + username + "'", rowMapper).get(0);
    }
}

SpringBoot Redis

添加依赖

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

添加配置

@Configuration
@PropertySource("classpath:config/redis.properties")
public class RedisConfiguration {
    /**
     * 对redisTemplate做一个简单的配置
     */
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        StringRedisSerializer keySerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(keySerializer);
        redisTemplate.setHashKeySerializer(keySerializer);
        GenericJackson2JsonRedisSerializer valueSerializer = new GenericJackson2JsonRedisSerializer();
        redisTemplate.setValueSerializer(valueSerializer);
        redisTemplate.setHashValueSerializer(valueSerializer);
        return redisTemplate;
    }
}

使用

@Service
public class RedisService {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 做一个基本的String类型数据的查询
     */
    public String get() {
        return redisTemplate.opsForValue().get("mykey");
    }
}

SpringBoot监控和度量

添加依赖

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

添加配置

启动程序,访问检测的url,测试结果如下

SpringBoot整合Mybatis

添加依赖

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

添加配置

# mapper文件所在路径
mybatis.mapper-locations=classpath:mapper/*.xml
# 实体类如User所在路径
mybatis.type-aliases-package=com.builder.management.user

spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/crud?useSSL=false&useJDBCCompliantTimezoneShift=true&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root

实现Mapper接口

package com.builder.management.user;

import org.apache.ibatis.annotations.Param;

public interface UserMapper {
    User find(@Param("username") String username);
}

<?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.builder.management.user.UserMapper">

    <!--结果集映射-->
    <resultMap id="userMap" type="com.builder.management.user.User">
        <result column="username" property="username" jdbcType="VARCHAR"/>
        <result column="email" property="email" jdbcType="VARCHAR"/>
    </resultMap>

    <select id="find" resultMap="userMap">
        select * from user where username = #{username};
    </select>

</mapper>

扫描Mapper接口

/**
 * @MapperScan 用于扫描mapper接口,如果用该注解,则无需对mapper接口做任何处理
 * 若不使用该接口,则需要在每个mapper接口类上添加@Mapper注解
 */
@SpringBootApplication
@MapperScan("com.builder.management.user")
public class ManagementApplication {
    public static void main(String[] args) {
        SpringApplication.run(ManagementApplication.class, args);
    }
}

测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {
    @Autowired
    private UserMapper userMapper;

    @Test
    public void find() {
        System.out.println(userMapper.find("liuqian").toString());
    }

}

测试结果如下

 

温馨提示:如果你使用的是Intellij来编写Java代码的话,添加Free MyBatis Plugin插件,能够自动帮你检测mapper接口与mapper文件的映射关系,如果找不到映射关系,mapper接口或者mapper.xml文件中就会报错,推荐使用。

效果如下

 

以上Spring Boot基础知识写的比较粗略,希望能对正在看这篇文章的你有所帮助,文章中有什么不足之处,大家可以留言指出来哦。

 

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值