springboot常使用的注解

一、使用在类上常用注解

1、@RestController

使用处:类

说明:代表这个类是REST风格的控制器,返回JSON/XML类型的数据,不能返回HTML页面,作用相当于@Controller(作用类上)+@ResponseBody(作用类或方法上)

2、@Controller

使用处:类

说明:代表这个类是mvc模式的控制器(主要用于构建MVC模式的程序),返回的字符串是视图(view)的位置和名称,比如下面的例子,视图位于example文件夹下,视图文件为hello.html:

3、@Service

使用处:类

说明:用于声明一个业务处理类(用作类,而不是接口),标记其是一个服务层,处理业务逻辑

4、@Repository

使用处:类

说明:标记其是一个数据访问层

5、@Component

使用处:类

说明:把普通POJO纳入Spring容器,当类不属于控制器层、服务层、数据访问层的角色时,就可以使用@Component注解,这个注解可以配合CommandLineRunner使用:再程序启动后执行一些基础任务。

6、@Configuration

使用处:类

说明:用于标注这是一个配置类,从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。

注意:@Configuration注解的配置类有如下要求:

  • @Configuration不可以是final类型;
  • @Configuration不可以是匿名类;
  • 嵌套的configuration必须是静态类

7、@Resource

使用处:类、属性  或  setter方法上  或者  构造函数参数

说明:Spring不但支持自己定义的@Autowired注解,还支持JSR-250规范定义的几个注解。如:@Resource、@PostConstruct及@PreDestroy

1. @Autowired

由spring提供,只按照byType注入

2. @Resource

由J2EE提供(java自己的注解),默认是按照byName自动注入

@Resource有两个重要的属性,name和type:

Spring将@Resource注解的name属性解析为bean的名字,type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略;而使用type属性则使用byType自动注入策略;如果既不指定name也不指定type属性,这时通过反射机制使用byName自动注入策略。

@Resource装配的顺序:

  • 如果同时指定了name和type属性,则从spring上下问中找到唯一匹配的bean进行装配,如果没有找到,则会抛出异常。
  • 如果指定了name属性,则从spring上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。
  • 如果指定type属性,则从spring上下文中找到类型匹配的唯一bean进行装配,找不到或者是找到多个,则抛出异常。
  • 如果既没有指定name属性,也没有指定type属性,则默认是按照byName的方式进行装配;如果没有匹配,则返回一个原始的类型进行装配,如果匹配则自动装配。

@Resource的作用是相当于@Autowired,只不过@Autowired是按照byType进行装配。

3. 使用区别

  • @Resource和@Autowired都可以用来装配bean,都可以写在属性上或者是写在setter方法上。
  • @Autowired默认是按照byType进行装配的,所以默认情况下是必须依赖的对象存在,如果要允许为空,可以设置它的required属性为false,如果想使用byName进行装配,可以结合@Qualifier注解进行使用。
  • @Resource默认是按照byName进行装配的,名称可以通过name属性进行制定,如果没有指定name属性,注解写在字段上时,默认是取字段名作为名称进行查找。如果注解写在setter方法上则默认是取属性的名称进行装配,当找不到与名称匹配的bean时才按照类型进行装配。但是值得注意的是,一旦指定了name属性,就会按照名称进行装配。

推荐使用@Resource注解在字段上,这样就不需要写setter方法了,并且这个属性是属于J2EE的,从而可以减少对spring的耦合

如果@Resource或者是@Autowired注解写在setter方法之上,则程序会走set方法内部,如果是写在filed上,则不糊走set方法内部。

场景代码示例参考下面这篇博客:

https://blog.csdn.net/magi1201/article/details/82590106?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.compare&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.compare

8、@Autowired

使用处:类、属性  或  setter方法上  或  构造函数参数

说明:它表示被修饰的类需要注入对象,spring会扫描所有被@Autowired标注的类,然后根据类型在IOC容器中找到匹配的类进行注入。

9、@RequestMapping("/hello")

使用处:类  或  方法上

说明:配置访问URL和controller类或方法之间进行映射,同时注释在类和方法上时,叠加生效,比如:

访问URL为:http://localhost:8080/hello1/hello2

该注解有6个属性:

其他:应该尽量使用@GetMapping、@PostMapping、@PutMapping

10、@Transactional

使用处:接口、接口方法、类、类方法,通常在Service层使用

说明:声明方法是事务的,但是是否真正支持事务,需要看数据库是否支持,详见我的另一篇博文《01.两小时学会springboot-入门》,spring不建议在接口、接口方法上使用该注解,因为这样使用只有基于接口的代理才会生效,基于类的代理不会生效;还有就是使用时要注意:比如使用这个注解修饰了某个方法,如果方法内部对异常进行了捕获,则事务不会回滚,如果想让事务回滚,则必须再往外抛出异常。

11、@Qualifier

使用处:类、属性

说明:用于标注哪一个实现类才是需要注入的。

需要注意的是:@Qualifier的参数名称为被注入的类中的注解@Service标注的名称。也就是@Qualifier的参数对应必须是@Service注解类的@Service("xxxx")参数xxxx

@Qualifier常与@Autowired一起使用:

而@Resource不需要与@Qualifier一起使用,因为@Resource自带name属性。

二、使用在方法上常用注解

注解使用位置说明
@PathVariable方法参数前将URL路径某一级映射到方法参数上

@RequestBody

Controller的方法参数前

注解@RequestBody接收的参数是来自requestBody中,即请求体。一般用于处理非 Content-Type: application/x-www-form-urlencoded编码格式的数据,比如:application/jsonapplication/xml等类型的数据。通常用于接收POST、DELETE等类型的请求数据,GET类型也可以适用,postman中调用如下图所示:

@RequestBody常用来处理application/json、application/xml等数据,这意味着HTTP消息是JSON/XML格式,需要将其转换为指定类型参数。

通过@RequestBody注解,可以将请求体中的JSON/XML字符串绑定到相应的Bean上,也可以将其绑定到Map上,也可以将其分别绑定到对应的字符串上

@RequestParamController的方法参数前

@RequestParam用来处理:

1、通过Params传值

2、通过body的x-www-form-urlencoded传值

所以在postman中,要选择body的类型为 x-www-form-urlencoded,这样在headers中就自动变为了 Content-Type : application/x-www-form-urlencoded 编码格式。如下图所示:

3、@RequestParam也可用于其它类型的请求,例如:POST、DELETE等请求。

@BeanConfiguration的方法上声明该方法的返回结果是一个由Spring容器管理的Bean,,通常在JavaConfig类中使用(用@Configuration注解修饰的类)
@ResponseBodyController的方法上

Spring会将控制器中方法返回的对象(可以是字符串或者其他对象)通过对应的HttpMessageConverter转换为指定格式(JSON/XML)后,写入Response对象的body数据区:

这个注解也使用在Controller的方法上,代表对返回的对象需要进行转换处理(转换成JSON/XML)

 

三、其他注解

  • 上图中@Aspec应该是@Aspect

@ExceptionHandler

@ControllerAdvice

三种使用场景

1、全局异常处理

使用 @ControllerAdvice 实现全局异常处理,只需要定义类,添加该注解即可定义方式如下

在该类中,可以定义多个方法,不同的方法处理不同的异常,例如专门处理空指针的方法、专门处理数组越界的方法...,也可以直接向上面代码一样,在一个方法中处理所有的异常信息。

@ExceptionHandler 注解用来指明异常的处理类型,即如果这里指定为 NullpointerException,则数组越界异常就不会进到这个方法中来。

package com.mzj.springboot.actionpai.exceptionhandler;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

import java.util.HashMap;
import java.util.Map;

@ControllerAdvice
public class MyGlobalExceptionHandler {
    //    @ExceptionHandler(Exception.class)
//    public ModelAndView customException(Exception e) {
//        ModelAndView mv = new ModelAndView();
//        mv.addObject("message123", e.getMessage());
//        mv.setViewName("myerror123");
//        return mv;
//    }
    @ExceptionHandler(Exception.class)
    public Map<String, Object> exceptionHandler(Exception e) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("code", "1002");
        map.put("message", e.getMessage());
        //发生异常进行日志记录,此处省略
        return map;
    }
}

疑问1??:这里统一异常处理了,怎么返回给前台指定结构,比如map,目前上面代码是无法返回给前台这个map的

答:

疑问2??:正常业务处理结束后怎么能返回前台对象,比如map?GET、POST请求类型不同有区别吗?

答:下图的方式,其中ServerResponse就是普通的Java对象

2、全局数据绑定

全局数据绑定功能可以用来做一些初始化的数据操作,我们可以将一些公共的数据定义在添加了 @ControllerAdvice 注解的类中,这样,在每一个 Controller 的接口中,就都能够访问导致这些数据。全局数据绑定功能可以用来做一些初始化的数据操作,我们可以将一些公共的数据定义在添加了 @ControllerAdvice 注解的类中,这样,在每一个 Controller 的接口中,就都能够访问导致这些数据。

使用步骤,首先定义全局数据,如下:

@ControllerAdvice
public class MyGlobalExceptionHandler {
    @ModelAttribute(name = "md")
    public Map<String,Object> mydata() {
        HashMap<String, Object> map = new HashMap<>();
        map.put("age", 99);
        map.put("gender", "男");
        return map;
    }
}

使用 @ModelAttribute 注解标记该方法的返回数据是一个全局数据,默认情况下,这个全局数据的 key 就是返回的变量名,value 就是方法返回值,当然开发者可以通过 @ModelAttribute 注解的 name 属性去重新指定 key。

定义完成后,在任何一个Controller中,都可以获取到这里定义的数据:

@RestController
public class HelloController {
    @GetMapping("/hello")
    public String hello(Model model) {
        Map<String, Object> map = model.asMap();
        System.out.println(map);
        return "hello controller advice";
    }
}

注意:上面的GetMapping方法,如果想返回这个Map给前台,直接返回这个全局的map对象是不可以的,需要创建另一个map对象返回才行

3、全局数据预处理

考虑我有两个实体类,Book 和 Author,分别定义如下:

public class Book {
    private String name;
    private Long price;
    //getter/setter
}
public class Author {
    private String name;
    private Integer age;
    //getter/setter
}

此时,如果我定义一个数据添加接口,如下

@PostMapping("/book")
public void addBook(Book book, Author author) {
    System.out.println(book);
    System.out.println(author);
}

这个时候,添加操作就会有问题,因为两个实体类都有一个 name 属性,从前端传递时 ,无法区分。此时,通过 @ControllerAdvice 的全局数据预处理可以解决这个问题

解决步骤如下:

1.给接口中的变量取别名

@PostMapping("/book")
public void addBook(@ModelAttribute("b") Book book, @ModelAttribute("a") Author author) {
    System.out.println(book);
    System.out.println(author);
}

2.进行请求数据预处理
在 @ControllerAdvice 标记的类中添加如下代码:

 

@InitBinder("b")
public void b(WebDataBinder binder) {
    binder.setFieldDefaultPrefix("b.");
}
@InitBinder("a")
public void a(WebDataBinder binder) {
    binder.setFieldDefaultPrefix("a.");
}

@InitBinder("b") 注解表示该方法用来处理和Book和相关的参数,在方法中,给参数添加一个 b 前缀,即请求参数要有b前缀.

3.发送请求

请求发送时,通过给不同对象的参数添加不同的前缀,可以实现参数的区分.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值