Spring常用注解

警告
本文最后更新于 2023-05-23,文中内容可能已过时,请谨慎使用。

@SpringBootApplication=@Configuration+@EnableAutoConfiguration+@ComponentScan,其中扫描包的范围为启动类所在包和子包,不包括第三方的 jar 包

标注在某个类上说明这个类是 SpringBoot 的启动类,SpringBoot 运行这个类的 main 方法来启动 SpringBoot 应用。

作用:在接口类上添加了@Mapper,在编译之后会生成相应的接口实现类

添加位置:接口类上面

@Mapper
public interface UserMapper extends BaseMapper<User> {
}

如果想要每个接口都要变成实现类,那么需要在每个接口类上加上@Mapper 注解,比较麻烦,解决这个问题可以用@MapperScan

作用:指定要变成实现类的接口所在的包,然后包下面的所有接口在编译之后都会生成相应的实现类,不必给所有的 Mapper 类单独加上@Mapper注解了

添加位置:是在 Springboot 启动类上面添加

在 SpringMVC 中提供了一个非常简便的定义 Controller 的方法,你无需继承特定的类或实现特定的接口,只需使用@Controller 标记一个类是 Controller ,然后使用@RequestMapping 和@RequestParam 等一些注解用以定义 URL 请求和 Controller 方法之间的映射,这样的 Controller 就能被外界访问到。

可以使用@RequestMapping 来映射URL到控制器类,或者是到Controller的处理方法上

参数介绍:

  • value:定义处理方法的请求的 URL 地址
  • method:定义处理方法的 http method 类型,如 GET、POST 等,缺省时可以处理任何形式的 http 请求
  • params:定义请求的 URL 中必须包含的参数。或者不包含某些参数
  • headers:定义请求中 Request Headers 必须包含的参数。或者不包含某些参数

@RequestMapping有两种标注方式,一种是标注在类级别上,一种是标注在方法级别上。

  • 标注在方法上时,value 表示访问该方法的 URL 地址。
  • 标注在类上时,value 相当于一个命名空间,即访问该 Controller 下的任意方法都需要带上这个命名空间。

更多示例请参考:Spring MVC @RequestMapping 注解详解)

示例: @Controller+@RequestMapping

调用localhost:8080/index/返回static目录下的index.html

@Controller
public class TestController {
    @RequestMapping("index")
    public String getSomething() {
        return "index";
    }
}

application.properties配置

spring.mvc.view.prefix=/
spring.mvc.view.suffix=.html

调用地址: http://localhost:8080/test/data/

@Controller
@RequestMapping(value ="/test/")
public class TestController {
    public static final String PAGE_1="view"; // staic文件夹下的view.html

    @RequestMapping("/data/")
    public ModelAndView data() {
        ModelAndView view = new ModelAndView(PAGE_1);
        view.addObject("str1","数据1");
        view.addObject("str2","数据2");
        return view;
    }
}

view.html

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<title>我的页面</title>
	</head>
	<body>
		<h1>渲染数据</h1>
		<h2>${str1}</h2>
		<hr />
		<h2>${str1}</h2>
		<hr />
	</body>
</html>

application.properties配置

spring.freemarker.suffix=.html
spring.freemarker.template-loader-path=classpath:/static/

@RequestParam 注解用于绑定请求参数值,在处理方法入参处使用@RequestParam 注解可以把请求参数传递给请求方法。

调用地址: http://localhost:8080/params/?id=100

@Controller
@RequestMapping("/params")
public class ParamController {
    public static final String PAGE = "param";
    @RequestMapping
    public ModelAndView testParams(@RequestParam(value = "id",defaultValue = "1000") Integer id,
                                   @RequestParam(value = "type",required = false) String type){
        if (null != type && type.equals("ok")) { // 注意type.equals("ok")放前面会抛出空指针异常
            System.out.println("ok");
        }
        ModelAndView view = new ModelAndView(PAGE);
        view.addObject("id",id);
        return view;
    }
}

@PathVariable 映射 URL 绑定的占位符,通过@PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中

调用地址: http://localhost:8080/params/path/100/

@Controller
@RequestMapping("/params")
public class ParamController {
    public static final String PAGE = "param";

    @RequestMapping("/path/{id}")
    public ModelAndView testPath(@PathVariable Integer id){
        ModelAndView view = new ModelAndView(PAGE);
        view.addObject("id",id);
        return view;
    }
}

@RestController 相当于@Controller+@ResponseBody,返回 json 或者 xml 格式数据。

@ResponseBody 注解的作用是将 Controller 的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到 HTTP 响应(Response)对象的 body 中,通常用来返回 JSON 或者 XML 数据。

注解用于处理 HTTP GET 请求,并将请求映射到具体的处理方法中,相当于@RequestMapping(method=RequestMethod.GET)

注解用于处理 HTTP DELETE 请求,并将请求映射到具体的处理方法中,相当于@RequestMapping(method=RequestMethod.DELETE)

注解用于处理 HTTP PUT 请求,并将请求映射到具体的处理方法中,相当于@RequestMapping(method=RequestMethod.PUT)

注解用于处理 HTTP POST 请求,并将请求映射到具体的处理方法中,相当于@RequestMapping(method=RequestMethod.POST)

@Component 注解用于标注一个普通的组件类,它没有明确的业务范围,只是通知 Spring 被此注解的类需要被纳入到 Spring Bean 容器中并进行管理。一般用于重复使用的封装类。

@Service注解是@Component的一个特例,它用于标注业务逻辑类。与@Component注解一样,被此注解标注的类,会自动被 Spring 所管理。

@Autowired 注解用于标记 Spring 将要解析和注入的依赖项。因此可用于获取 Bean。此注解可以作用在构造函数、字段和 setter 方法上。

作用于构造函数中

@RestController
public class UserController {
    private UserService userService;
    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }
}

作用于字段上

@RestController
public class UserController {
    @Autowired
    private UserService userService;
}

作用于 setter 方法上

@RestController
public class UserController {
    private UserService userService;
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
}

@Resource = @Autowired+@Qualifier。功能上和@Autowired 类似,具体区别如下:

  • 如果接口实现只有一个,那么用@Autowired 就可以了,也不需要指定名字。
  • 如果接口有多个实现,那么,用@Resource,并指定实现类的名字,注意 value 的首字母要小写
  • 或者使用@Autowired+@Qualifier,@Qualifier 中指定对应的实现类名字,注意 value 的首字母小写

将未使用@Service注解的两个Service接口实现类改为手动注入 Bean。

@Configuration
public class myBeans {
    @Bean
    // 实现类是AdminServiceImpl,现在没有使用@Service注解,该为手动注入
    public UserService adminServiceImpl() {
        return new AdminServiceImpl();
    }

    @Bean
    // 实现类是UserServiceImpl
    public UserService userServiceImpl() {
        return new UserServiceImpl();
    }

}

用于读取配置文件中的自定义字段值

下面是一些在application.properties中自定义字段

my.page=1
local.username=admin
local.password=admin123

读取字段值,返回对应的json数据

@RestController
public class UserController {

    @Value("${local.username}")
    private String username;

    @Value("${local.password}")
    private String password;

    @Value("${my.page}")
    private Integer page;

    @GetMapping("/values/")
    public JSONObject getInfo() {
        JSONObject object = new JSONObject();
        object.put("page",page);
        object.put("username",username);
        object.put("password",password);
        return object;
    }
}

绑定属性,根据前缀(prefix)批量导入配置文件中的值

application.properties定义如下字段:

person.name=admin
person.password=123123
person.sex=男
person.age=18

配合@ConfigurationProperties(prefix = "person")Person类属性自动赋值

@Component
@ConfigurationProperties(prefix = "person")
public class Person {
    // 字段名称必须一一对应
    private String name;
    private String password;
    private String  sex;
    private Integer age;


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}
注意
如果上面的类不加@Component, 那就需要在启动类上添加注解@EnableConfigurationProperties({Person.class})来启用配置。

调用http://localhost:8080/person/返回读取配置文件后的person对象的数据

@RestController
public class PersonController {
    @Autowired
    private Person person;

    @GetMapping("/person/")
    public Person getPerson() {
        return person;
    }
}

注意: 不能有多个类指定相同的前缀

可能发生中文乱码问题

  • properties文件中文乱码:修改application.properties的编码类型
/images/all/image-20230303224245838.png
  • 接口返回中文乱码:properties文件中配置字符编码格式

    # 编码设置为UTF-8
    server.servlet.encoding.force=true
    server.servlet.encoding.charset=UTF-8
    

如果不想使用默认的配置文件,可以使用@PropertySource读取自定义配置文件

注意:如果在 application.properties 中也定义了配置,会覆盖自定义配置文件中的字段值(白配置了!)

@PropertySource(value = {"classpath:static/person.properties"})

虽然SpringBoot并不推荐我们继续使用 xml 配置,但如果出现不得不使用 xml 配置的情况,SpringBoot允许我们在入口类里通过注解@ImportResource({"classpath:beans.xml"})来引入xml配置文件。

当然,相比之下SpringBoot更推荐的依赖注入方式还是使用@Configuration+@Bean

@ImportResource(locations = {"classpath:beans.xml"})
// 导入Spring的配置文件让其生效
  • @Data: 注在类上,提供类的 get、set、equals、hashCode、canEqual、toString 方法
  • @AllArgsConstructor: 注在类上,提供类的全参构造,参数顺序和属性在类中的顺序一致
  • @NoArgsConstructor: 注在类上,提供类的无参构造
  • @Setter: 注在属性上,为属性提供 set 方法;注在类上,为所有属性提供 set 方法
  • @Getter: 注在属性上,提供 get 方法;注在类上,为所有属性提供 get 方法
  • @EqualsAndHashCode:注在类上,提供对应的 equals、hashCode 和 canEqual 方法
  • @Log4j/@Log4j2/@Slf4j: 注在类上,提供对应的 Logger 对象,变量名为 log

不使用该注解前打印日志需要获取Logger对象

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class UserController{

    private static final Logger log = LoggerFactory.getLogger(UserController.class);

    pubulic void getLog() {
        log.info("xxx");
    }
}

使用注解后

@Slf4j
public class UserController{

    pubulic void getLog() {
        log.info("xxx");
    }
}

对配置文件的数据字段进行校验

pom.xml中导入依赖

<!--1.导入JSR303规范-->
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
</dependency>
<!--使用hibernate框架提供的校验器做实现-->
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
</dependency>

配置Bean

import org.hibernate.validator.HibernateValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

@Configuration
public class ValidatorConfig {
    @Bean
    public Validator validator() {
        ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
                .configure()
                // 快速失败模式
                .failFast(true)
                // .addProperty( "hibernate.validator.fail_fast", "true" )
                .buildValidatorFactory();
        return validatorFactory.getValidator();
    }

}

配置文件application.properties内容如下:

student.id = 1
student.name = admin
student.age = 5

Student实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
@ConfigurationProperties(prefix = "student")
@Validated
public class Student {
    private int id;
    private String name;
    @Max(value = 40,message = "最大值不能超过40")
    @Min(value = 10,message = "最小值不能小于10")
    private int age;
}

运行后age校验失败:

/images/all/image-20230523152018206.png

相关文章