Loading

Spring常用注解

HTTP相关注解

url请求参数:

@RequestBody :

  • @RequestBody主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的);GET方式无请求体,所以使用@RequestBody接收数据时,前端不能使用GET方式提交数据,而是用POST方式进行提交。

@RequestParam:

  • 值得注意的属性:value 、 required
  • 1、可以对传入参数指定参数名
1 @RequestParam String inputStr  
2 // 下面的对传入参数指定为aa,如果前端不传aa参数名,会报错  
3 @RequestParam(value="aa") String inputStr 
  • 2、可以通过required=false或者true(默认)来要求@RequestParam配置的前端参数是否一定要传

    // required=false表示不传的话,会给参数赋值为null,required=true就是必须要有  
    2 @RequestMapping("testRequestParam")    
    3     public String filesUpload(@RequestParam(value="aa", required=true) String inputStr, HttpServletRequest request) 
    
  • 3、如果@requestParam注解的参数是int类型,并且required=false,此时如果不传参数的话,会报错。原因是,required=false时,不传参数的话,会给参数赋值null,这样就会把null赋值给了int,因此会报错。

    1 // required=false表示不传的话,会给参数赋值为null,required=true就是必须要有  
    2 @RequestMapping("testRequestParam")    
    3 public String filesUpload(@RequestParam(value="aa", required=false) int inputStr, HttpServletRequest request) 
    4 若是前端页面不传参的话,此处就会报错。当然可以用Integer代替int
    

    所以接口的入参最好用包装类!!

  • 4、可以用Map 来接受key-value参数,用@RequestParam 来注解,如

    @RequestParam Map<String, ?> param

@RequestHeader

@ModelAttribute

public String test1(@ModelAttribute("user") UserModel user)

@Validated

public String save(@Validated @RequestBody ValidList<Su> listSu, BindingResult bindingResult)

@Validated 校验ValidList 里的Su类,其中Su类中需要校验的属性会在属性上添加相应的校验注解.

常用的校验注解:注意,不要错用了异常类型,比如在int上不可用@size

@AssertFalse 校验false
@AssertTrue 校验true
@DecimalMax(value=,inclusive=) 小于等于value,
inclusive=true,是小于等于
@DecimalMin(value=,inclusive=) 与上类似
@Max(value=) 小于等于value
@Min(value=) 大于等于value
@NotNull  检查Null
@Past  检查日期
@Pattern(regex=,flag=)  正则
@Size(min=, max=)  字符串,集合,map限制大小
@Validate 对po实体类进行校验

而后,当输入不能满足条件是,就会抛出异常,而后统一由异常中心处理
也可以用BindingResult,但是用了这个后就必须手动处理异常,侵入了正常的逻辑过程,并不推荐.

// 校验参数是否为空
if (bindingResult.hasErrors()) {    
   return "error";
}

http请求:

@RequestMapping

  • @RequestMapping不仅支持标准的URL,还支持Ant风格和带{xxx}占位符的URL,下面的URL都是合法的:

    •/user/*/login:匹配/user/aaa/login,/user/任意字符/login等
    •/user//login:匹配/user/login,/user/aaa/bbb/login 等
    •/user/login??:匹配/user/loginAA,/user/loginbb 等
    •/user/{userId}:匹配/user/123,/user/234 等
    •/user/
    /{userId}:匹配/user/aaa/bbb/123,/user/aaa/234等

    这些占位符需要用pathvariable绑定后使用

容器组件注册

@Scope

配置Bean的作用域

  • ConfigurableBeanFactory#SCOPE_PROTOTYPE -->多实例,需要创建时加载
  • ConfigurableBeanFactory#SCOPE_SINGLETON -->单实例,容器启动时加载(默认)

@Lazy

针对单实例的Bean懒加载,容器启动的时候不加载Bean,只有在向容器获取单实例Bean的时候才向容器注册一个单实例Bean,然后被使用

@Conditional

@Conditional,按照一定的条件进行判断,满足条件给容器注册Bean.

用法:可用于类或者方法上 @Conditional({WindowsCondition.class})

@Conditional({WindowsCondition.class})
@Bean("bill")
public Person person01() {
    return new Person("Bill Gates", 60);
}
public class WindowsCondition implements Condition {
    /**
     *
     * @param context 判断条件能使用的上下文
     * @param metadata 注释信息
     * @return
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        String osName = environment.getProperty("os.name");
        return "Windows".equalsIgnoreCase(osName);
    }
}

容器注册组件的方式

包扫描@ComponentScan+组件标注@Controller,@Service,@Repository,@Component

@Bean[导入的第三方包的组件]

@Import[组件]

  1. @Import(要导入到容器中的组件,容器就会自动注册一个id默认未全限定类名的实例)
  2. ImportSelector:返回需要导入的组件的全类名数组,解决的问题是批量导入组件,且更便于分组管理。用的较多。
  3. ImportBeanDefinitionRegistrar:手动注册Bean到容器中
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    /**
     * @param importingClassMetadata 当前类的注解信息
     * @param registry               BeanDefinition注册类,把所有添加到容器中的bean,
     *                               调用BeanDefinitionRegistry.registerBeanDefinition手动注册
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        RootBeanDefinition rainBow = new RootBeanDefinition(Rainbow.class);
        registry.registerBeanDefinition("rainBow", rainBow);
    }
}

使用Spring提供的FactoryBean

和其他框架做整合时用得较多

  1. 默认获取到的是工厂bean调用getObject返回的对象
/**
* 工厂Bean在容器中注册的是工厂创建的对象实例
* 这里返回的虽然是{@see ColorFactory},但实际再容器中注册的是{@see Color},
* 注册到容器中会调用ColorFactory.getObject方法
*/
@Bean
public ColorFactory color() {
    return new ColorFactory();
}
public class ColorFactory implements FactoryBean<Color> {
    // 返回Color对象,这个对象会添加到容器中
    @Override
    public Color getObject() throws Exception {
        System.out.println("getObject...");
        return new Color();
    }
    // 返回对象的类型
    @Override
    public Class<?> getObjectType() {
        return Color.class;
    }
    // true:单实例;false:多实例
    @Override
    public boolean isSingleton() {
        return true;
    }
}
  1. 要获取工厂bean本身,要在id前面加一个&
@Test
@DisplayName("测试FactoryBean的用法来注册Bean到容器")
public void testFactoryBean() {
    Object color1 = context.getBean("&color");
    System.out.println("color的类型:" + color1.getClass());
}

输出:

color的类型:class com.test_space.ColorFactory

组件生命周期

Bean的生命周期

  • bean创建--初始化--销毁的过程

容器管理bean的生命周期

我们可以自定义初始化和销毁方法;容器会在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法

  • 构造(对象创建):
    • 单实例:再容器启动的时候创建
    • 多实例:每次获取实例的时候创建
  • 初始化:
    • 对象创建完成,并赋值好,调用初始化方法
      • 单实例:容器启动之后初始化
      • 多实例:每次获取实例的时候初始化
  • 销毁:
    • 单实例:容器关闭的时候
    • 多实例:容器不管理多实例的bean,容器不会调用销毁方法,需要手动销毁

1.制定初始化和销毁方法

​ 通过@Bean指定init-method和destroy-method

2.通过让Bean实现InitializingBean,DisposableBean接口来初始化和销毁

3.使用JSR250:[推荐使用]

@PostConstruct:再Bean创建完成并赋值结束之后,执行初始化方法

@PreDestroy:容器销毁bean之前通知清理

4.BeanPostProcessor:Bean后置处理器

在bean初始化前后进行一些处理工作:

  • postProcessBeforeInitialization:在初始化之前工作postProcessAfterInitialization:在初始化之后工作

顺序:construct->postProcessBeforeInitialization->init->postProcessAfterInitialization

事务:

@Transactional:

###
-
-
@Transactional 注解也可以添加到类级别上。当把@Transactional 注解放在类级别时,表示所有该类的公共方法都配置相同的事务属性信息。当类级别配置了@Transactional,方法级别也配置了@Transactional,应用程序会以方法级别的事务属性信息来管理事务,换言之,方法级别的事务属性信息会覆盖类级别的相关配置信息
posted @ 2021-03-31 17:44  非凡岁月  阅读(55)  评论(0编辑  收藏  举报