SpringBoot入门

配置文件

在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, 接口名>的形式,将这些实现类都注入进来。其中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。

@EnableConfigurationProperties

@EnableConfigurationProperties 注解使ConfigurationProperties注解生效

也可以指定Bean生效 @EnableConfigurationProperties({ConfigBean.class})

除了上述方式之外,还可以在@ConfigurationProperties注解的类上加@Component注解,使@ConfigurationProperties生效。

注:@Component注解表明一个类会作为组件类,然后spring会为该类创建bean。

  @Bean注解告诉Spring这个方法将会返回一个对象,这个对象要注册为Spring应用上下文中的bean。

类上添加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)
// 给swagger看的
@ApiResponse({@ApiResponse(code = 404, message = "所请求的页面不存在"),
@ApiResponse(code = 500, message = "其他异常")})
@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会自动转换

全局异常处理

<!-- Spring Boot Web 依赖 核心 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot Test 依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</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);
    }
}

 @Valid & @Validated

1、@Validated写在类上,只能作用于类中方法参数,且参数只能是java的原生类型及其对应的引用类,如Integer、String、int等。无法作用到参数类型之内。

@Validated
@RestController
@Slf4j
@RequestMapping("/api/controller")
public class TestController {
    @RequestMapping(path = "/id", method = RequestMethod.POST)
    public void method(@NotBlank(message = "id不能为空") String id){
    }
}

2、@Valid和@Validate,都可以直接写在Dto之前,对Dto内部的参数进行校验。

@RestController
@Slf4j
@RequestMapping("/api/controller")
public class TestController {
    @RequestMapping(path = "/id", method = RequestMethod.POST)
    public void method(@Valid/@Validated Dto dto){
    }
}

3、对与Dto内部的另外一个Dto内部的参数校验,即嵌套校验,需要在Dto内部的这个参数前加@Valid。

@Data
public class FirstDto {
  @NotBlank(message = "username不能为空")
  private String username;
  @Valid //检验secondDto内部
@NotNull(message = "secondDto不能为null")//单检验secondDto本身
private SecondDto secondDto; @Valid //检验每个ThirdDto内部
@NotEmpty(message = "thirdDtos不能为空")//单检验thirdDtos本身
private List<ThirdDto> thirdDtos; }

4、@Validated 分组校验

//定义接口作为分组
public interface Select {
}
public interface Insert {
}
//定义校验顺序,如果Select组失败,则Update组不会再校验
@GroupSequence({Select.class, Update.class})
public interface group {
{
//数据层 @Data public class Person { @NotNull(message = "id不能为空",groups = Select.class) private Integer id; @NotEmpty(message = "name不能为空",groups = Insert.class) private String name; } //Controller层 @GetMapping("/select") public void select(@Validated({Select.class}) Person person) { return person; } @GetMapping("/insert") public void insert(@Validated(Insert.class) Person person) { return person; }

@Transactional

Spring Aop事务管理,在进入方法前开启事务,方法结束后视执行情况提交或者回滚事务。

非运行时异常是RuntimeException以外的异常,类型上都属于Exception类及其子类。如IOException、SQLException等以及用户自定义的Exception异常。对于这种异常,JAVA编译器强制要求我们必需对出现的这些异常进行catch并处理,否则程序就不能编译通过。

当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。

@Transactional(readOnly = true, rollbackFor = Exception.class, transactionManager = "mysqlTransactionManager")

readOnly 只读事务 不允许写操作。

rollbackFor 遇见某个异常就回滚,这里注意有些异常是throwable类型的,无法回滚

transactionManager 指定事务管理器

@Transactional(propagation=Propagation.REQUIRED) 
//如果有事务, 那么加入事务, 没有的话新建一个(默认)
@Transactional(propagation=Propagation.REQUIRES_NEW) 
//不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务

当调用者存在@Transactional,被调用者也存在@Transactional,且处于共同事务时,被调用者回滚后,调用者提交事务会报错异常

Transaction rolledback because it has been marked as rollback-only

根本原因是被调用方法抛出异常后该共同事务TransactionStatus被RollbackOnly设置为true,表示该事务只能被回滚,不能够提交。

因此,一般来说,被调用者不需要添加事务,直接使用调用者的事务即可。

spring事务的7种传播行为
MySQL中事务详解
posted @ 2022-04-16 16:09  云轻YK  阅读(57)  评论(0)    收藏  举报