SpringBoot slighting matters


配置文件

在Spring Boot中多环境配置文件名需要满足application-{profile}.properties的格式,其中{profile}对应你的环境标识,比如:
application-dev.properties:开发环境
application-test.properties:测试环境
application-prod.properties:生产环境
具体加载的配置文件,需要在通用配置application.properties中设置spring.profiles.active属性来设置,其值对应{profile}值。

也可通过在启动类中设置

SpringApplication app = new SpringApplication(Application.class);
//使开发环境的配置文件生效
app.setAdditionalProfiles("dev");
//使测试环境的配置文件生效
//app.setAdditionalProfiles("test");
ConfigurableApplicationContext context = app.run(args);

通过@Profile注解可控制bean在哪个配置文件生效的时候被装载。比如@Profile("dev")就是application-dev.properties生效时加载注解下的bean。

@Autowired

当一个Interface有多个实现类时,可通过@Service("名称")给这个实现类bean命名。不进行命名时,名称默认为首字母小写的类名。

@Autowired这个接口时,可通过Map的形式,将这些实现类都注入进来。其中String就是你自己给这个实现类取的名字。通过Map根据key获取你所需要的实现类即可。

(这里可以构造一个工厂,就是用一个Context类把上面所说的封装起来,这个工厂专门用于传入key获取实现类)

当然你也可以不用Map,使用List<接口名>,但这样获取具体实现类时会比较麻烦。

当然你也可以使用@Qualifier("名称")指定自己所需要装载的实现类。

当然你也可以在实现类上加上@Primary告诉SpringBoot默认装载哪个实现类。

@ConditionalOnProperty

这个注解可用于有选择性地装载bean,比如

@ConditionalOnProperty(prefix "sms",name "provider",havingValue "tencent")

就是当配置文件中 sms.provider这个属性值为tencent时才装载下面的注解下的bean

@ConfigurationProperties

这个注解可用于自动给需要装载的bean配置属性,它会调用bean中的set方法。比如:

public class TencentConfig {
    private String key1;
    private String key2;

    public String getKey1() {
        return key1;
    }

    public String getKey2() {
        return key2;
    }

    public void setKey1(String key1) {
        this.key1 = key1;
    }

    public void setKey2(String key2) {
        this.key2 = key2;
    }
}

配置文件中

sms.tencent.key1 = 1
sms.tencent.key2 = 2

那么

@Bean
@ConditionalOnProperty(name = "sms.provider",havingValue = "tencent")
@ConfigurationProperties(prefix = "sms.tencent")
public TencentConfig tencentConfig(){
    return new TencentConfig();
}

返回的TencentConfig这个bean中,属性key1值被设为1,属性key2值被设为2。

类上添加Java Doc

具体方法可以百度一下

这里给个我自己用的模板,创建类的时候自动就生成了。

/**
  *TODO
* *@author ${USER} *@date ${DATE} ${TIME} *@version 1.0 */

author的${USER}可在vmoptions中修改,加一行

-Duser.name=要修改的名字

方法上添加Java Doc直接在写完方法后小键盘依次按 / * * 回车

@RequestBody @RequestParam

@RequestBody 用于接收body中的 json 数据,映射到实体类中。它调用的是实体类的无参构造方法构造对象,然后通过set方法给属性赋值。

当 json 中有某个属性而实体类中无时,不会报错

当 json 中无某个属性值而实体类中有时,实体类中该属性如果是对象类型则值为null,基本类型值为0

实体类可配合使用JSR303校验

@RequestParam 用于接收key-value数据,该注解的属性 required 的值默认为true,即必须传这个字段,即使没有值。修改为false可不传这个字段。

其实不加@RequestParam也可以,加了只是可以实现更多定制化操作。

接口参数为一个实体类对象,前不加@RequestBody注解,接受的也是key-value数据

@Controller

@Api(tags = "Controller名")
@RestController
@Slf4j
@RequestMapping("/api/controller")
public class TestController {
    @ApiOperation(value = "调用方法", notes = "调用方法", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @RequestMapping(path = "/{methodId}", method = RequestMethod.POST)
    public void method(@ApiParam("请求参数") @RequestBody @Valid InfoDO info,  //body里json
                       @ApiParam("额外参数") @RequestParam("extra") String extra,  //url
                       @ApiParam("方法id") @PathVariable Integer methodId) {  //url
    }
}

Date & TimeStamp

Date 对应 mysql 中的 date 类型,默认存储格式是 yyyy-MM-dd

TimeStamp 对应 mysql 中的 datetime 类型,默认存储格式是 yyyy-MM-dd HH:mm:ss

实际上 Date 也可以存入 datetime 中,因为 Date 本身含有时分秒

String 可以直接存入 date 中,需要格式正确,mysql会自动转换

@Param

在 Mapper 接口文件中

1、参数为单一属性,且只有一个,可以不用@Param,但 sql 中参数只能用 #{};用 @Param, #{} 或 ${} 都可以;

2、参数为JavaBean,且只有一个,可以不用@Param,sql 中参数为JavaBean的属性。

3、参数为有多个,必须用@Param,其中JavaBean的参数,sql 中参数为JavaBean.属性名的形式。同时JavaBean的属性和外面的单一属性名称不要相同,不然会产生覆盖现象。

全局异常处理


<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-webartifactId>
dependency>

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-testartifactId>
    <scope>testscope>
dependency>

@ControllerAdvice

使用该注解可捕获全局异常 该注解标注在类上,在该类的方法上标注@ExceptionHandler表示对每一种异常的处理

与@Controller相同,@ControllerAdvice也有Rest风格:@RestControllerAdvice,自己定义一下返回dto

@ExceptionHandler({BindException.class})
public ResponseMsg handleException(BindException e) {
    try {
        log.warn("参数绑定错误", e);
        FieldError fieldError = e.getBindingResult().getFieldError();
        return ResponseMsg.createError(fieldError.getDefaultMessage());
    } catch (Exception ex) {
        log.error("系统错误", ex);
        return ResponseMsg.createError(MyException.SYSTEM_EXCEPTION);
    }
}