SpringBoot常用注解


1、@SpringBootApplication

@SpringBootApplication注解是SpringBoot最核心的注解,用于SpringBoot的主类,标识这是一个 SpringBoot 应用,用来开启 Spring Boot 的各项能力。其中包含了@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan这三个注解。

(1)、@Configuration:指示这个类是一个配置类,它定义了一个或多个@Bean方法,用于创建和配置Spring应用程序上下文中的Bean。

(2)、@EnableAutoConfiguration:启用Spring Boot的自动配置机制,它会自动添加所需的依赖项和配置,以使应用程序能够运行。

(3)、@ComponentScan:指示Spring Boot扫描当前包及其子包中的所有@Component、@Service、@Repository和@Controller注解的类,并将它们注册为Spring Bean。

@SpringBootApplication注解是在主方法上使用,为启动注解

package com.springboot.userlogin.springbootdemo;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@MapperScan("com.springboot.userlogin.springbootdemo.dao")
@SpringBootApplication
public class SpringBootDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootDemoApplication.class, args);
    }

}

2、@RestController

@RestController 是一个复合注解,包含@ResponseBody注解和@Controller注解。主要用于Controller接口上。

(1)、@Controller注解:控制器,处理http请求。
(2)、@ResponseBody注解:效果是将方法返回的对象直接在浏览器上展示成json格式。

package com.springboot.userlogin.springbootdemo.controller;

import com.springboot.userlogin.springbootdemo.bean.User;
import com.springboot.userlogin.springbootdemo.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class LoginController {
    @Autowired
    UserDao userDao;

    @PostMapping("/api/getUserPassword") // @RequestMapping注解创建接口
    public String userLogin(@RequestBody User user) { // @RequestBody注解方便找到user实体
        System.out.println(user);
        User user1 = new User();
        System.out.println(user);
        System.out.println("user:" + user);
        User user2 = new User();

        System.out.println("User : " + user);
        String str = "error";
        int count = userDao.getUserByMassage(user.getEmail(), user.getPassword());
        if (count > 0) {
            str = "ok";
        }
        return str;
    }
}

3、@RequestMapping

@RequestMapping注解:注解是一个用来处理请求地址映射的注解,可用于映射一个请求或一个方法,可以用在类或方法上。

@RequestMapping("/testRequest")
public String testRequest(){
    return "success";
}

设置value值:

@Controller
public class RequestMappingController {

    @RequestMapping(value = {"/testRequest","/test"})
    public String testRequest(){
        return "success";
    }
}

设置请求方式为get:

@Controller
public class RequestMappingController {

    @RequestMapping(value = "/testRequest",method = RequestMethod.GET)
    public String testRequest(){
        return "success";
    }
}

4、@GetMapping

@GetMapping和@PostMapping是@RequestMappin的组合注解
@GetMapping注解用于映射HTTP GET请求。

@GetMapping("/adminList")
    public Result adminList(@RequestParam(defaultValue = "1", value = "current") Integer current,
                            @RequestParam(defaultValue = "8", value = "size") Integer size) {


        Page<User> page = new Page<>(current, size);
        IPage<User> list = userService.userListAdmin(page);
        return Result.success(list);
    }

5、@PostMapping

@GetMapping和@PostMapping是@RequestMappin的组合注解
@GetMapping注解用于映射HTTP POST请求。

@PostMapping("/rz")
    public Result rz (@RequestBody User user) {
        user.setSfrz(MapUtil.YRZ);
        // 管理员日志
        recordAdminService.xr("认证用户:" + user.getUserName() + "为机家号");
        userService.updateById(user);
        return Result.success("已认证");
    }

6、@PutMapping

@PutMapping注解用于映射HTTP PUT请求。

@RestController
@RequestMapping("/users")
public class UserController {

    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User user) {
        // Update the user with the given ID
        return ResponseEntity.ok(user);
    }
}

7、@DeleteMapping

@DeleteMapping注解用于映射HTTP DELETE请求。

@DeleteMapping("/{orderId}")
@ResponseStatus(code=HttpStatus.NO_CONTENT)
public void deleteOrder(@PathVariable("orderId") Long orderId){
    try{
        repo.deleteById(orderId);
    }catch(EmptyResultDataAccessException e){}
}

8、@RequestParam

@RequestParam注解用于获取请求参数的值。

@RequestMapping("/list1")
public String test1(int userId) {
  return "list";
}
@RequestMapping("/list2")
public String test2(@RequestParam int userId) {
  return "list";
}

(1)不加@RequestParam前端的参数名需要和后端控制器的变量名保持一致才能生效

(2)不加@RequestParam参数为非必传,加@RequestParam写法参数为必传。但@RequestParam可以通过@RequestParam(required = false)设置为非必传。

(3)@RequestParam可以通过@RequestParam(“userId”)或者@RequestParam(value = “userId”)指定传入的参数名。(最主要的作用)

(4)@RequestParam可以通过@RequestParam(defaultValue = “0”)指定参数默认值

(5)如果接口除了前端调用还有后端RPC调用,则不能省略@RequestParam,否则RPC会找不到参数报错

(6)Get方式请求,参数放在url中时:

不加@RequestParam注解:url可带参数也可不带参数,输入 localhost:8080/list1 以及 localhost:8080/list1?userId=xxx 方法都能执行
加@RequestParam注解:url必须带有参数。也就是说你直接输入localhost:8080/list2 会报错,不会执行方法。只能输入localhost:8080/list2?userId=xxx 才能执行相应的方法

9、@PathVariable

@PathVariable 注解:可以将 URL 中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过@PathVariable(“xxx“) 绑定到操作方法的入参中。

//@PathVariable可以用来映射URL中的占位符到目标方法的参数中
@RequestMapping("/testPathVariable/{id}")
   public String testPathVariable(@PathVariable("id") Integer id)
   {
       System.out.println("testPathVariable:"+id);
       return SUCCESS;
   }

10、@RequestBody

注解@RequestBody接收的参数是来自requestBody中,即请求体。一般用于处理非 Content-Type: application/x-www-form-urlencoded编码格式的数据,比如:application/json、application/xml等类型的数据。

就application/json类型的数据而言,使用注解@RequestBody可以将body里面所有的json数据传到后端,后端再进行解析。

@PostMapping("/saveBatch")
public String saveBatch(@RequestBody @Validated List<User> list){
   list.forEach(System.out::println);
   return "saveBatch success";
}
@PostMapping("/listMap")
public String saveMap(@RequestBody List<Map<String, String>> listMap){
   for (Map<String, String> map : listMap) {
       System.out.println(map);
   }
   return "listMap success";
}

11、@ResponseBody

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

@ResponseBody
@RequestMapping(value = "/loginIn", produces = "application/json;charset=UTF-8")
public Object login(UserBean user) {
   result = userService.loginIn(user.getUsername(), user.getPassword());
   if(result!=null){
       return "success";
   }else {
       return "error";
   }
}

12、@Autowired

@Autowired注解用于自动装配Spring容器中的Bean。

@RestController
public class LoginController {
   @Autowired
   UserDao userDao;

   @PostMapping("/api/getUserPassword") // @RequestMapping注解创建接口
   public String userLogin(@RequestBody User user) { // @RequestBody注解方便找到user实体
       System.out.println(user);
       User user1 = new User();
       System.out.println(user);
       System.out.println("user:" + user);
       User user2 = new User();

       System.out.println("User : " + user);
       String str = "error";
       int count = userDao.getUserByMassage(user.getEmail(), user.getPassword());
       if (count > 0) {
           str = "ok";
       }
       return str;
   }
}

13、@Component

@Component注解用于标识一个类是Spring容器中的组件。@Component是Spring框架中的一个通用注解,用于标注一个类作为Spring Bean。

@Component
public class UserServiceImpl implements UserService {

   // 实现UserService接口中的方法
}

14、@Service

@Service 注解可以将一个类声明为业务逻辑组件,并将其对象存入 Spring 容器中。在控制器类中,通过注入该组件的实例,即可调用其中的方法。

@Service
public class OrderServiceImpl implements OrderService {

   @Override
   public Order createOrder(Order order) {
       // 在这里执行创建订单的业务逻辑
       return order;
   }

   @Override
   public Order getOrderDetails(String orderId) {
       // 在这里执行查询订单详情的业务逻辑
       return new Order();
   }
}
}

15、@Mapper和@Repository的区别

1.相同点
@Mapper和@Repository都是作用在dao层接口,使得其生成代理对象bean,交给spring 容器管理,对于mybatis来说,都可以不用写mapper.xml文件

2.不同点
@Repository需要在Spring中配置扫描地址,然后生成Dao层的Bean才能被注入到Service层中:如下,在启动类中配置扫描地址:

@SpringBootApplication(scanBasePackages = "com.example.demo")
//@EnableAutoConfiguration(exclude ={ DataSourceAutoConfiguration.class})//排除自动配置
@MapperScan("")
public class DemoApplication {
   public static void main(String[] args) {
       SpringApplication.run(DemoApplication.class, args);
   }

}

@Mapper不需要配置扫描地址,通过xml里面的namespace里面的接口地址,生成了Bean后注入到Service层中
也就是@Repository多了一个配置扫描地址的步骤;

16、@Configuration

@Configuration注解的作用:声明一个类为配置类,用于取代bean.xml配置文件注册bean对象。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {

   @AliasFor(annotation = Component.class)
   String value() default "";

   boolean proxyBeanMethods() default true;
}

17、@Value

通过@Value将外部的值动态注入到Bean中

@Value("normal")
   private String normal; // 注入普通字符串

   @Value("#{systemProperties['os.name']}")
   private String systemPropertiesName; // 注入操作系统属性

   @Value("#{ T(java.lang.Math).random() * 100.0 }")
   private double randomNumber; //注入表达式结果

   @Value("#{beanInject.another}")
   private String fromAnotherBean; // 注入其他Bean属性:注入beanInject对象的属性another,类具体定义见下面

   @Value("classpath:com/hry/spring/configinject/config.txt")
   private Resource resourceFile; // 注入文件资源

   @Value("http://www.baidu.com")
   private Resource testUrl; // 注入URL资源

18、@Bean

该注释的属性的名称和语义类似于Spring XML模式中bean的元素的名称和语义。@Bean指示方法产生一个由Spring容器管理的bean。

@Configuration
public class DataBaseConfig {
   @Bean("dataSource")
   public DataSource getDataSource(){
       DataSource dataSource = new DataSource();
       dataSource.setUserId("jingsi");
       dataSource.setPassword("123456");
       dataSource.setUrl("www");
       return dataSource;
   }

}

19、@Import

@Import注解提供了三种用法

1、@Import一个普通类 spring会将该类加载到spring容器中

2、@Import一个类,该类实现了ImportBeanDefinitionRegistrar接口,在重写的registerBeanDefinitions方法里面,能拿到BeanDefinitionRegistry bd的注册器,能手工往beanDefinitionMap中注册 beanDefinition

3、@Import一个类 该类实现了ImportSelector 重写selectImports方法该方法返回了String[]数组的对象,数组里面的类都会注入到spring容器当中

(1)、import普通类:


public class MyClass {
   
   public void test() {
   	System.out.println("test方法");
   }
}

写一个importConfig类 import这个myClass类


@Import(MyClass.class)
public class ImportConfig {
   
}

(2)、创建一个普通类MyClassRegistry


public class MyClassRegistry {
   
   public void test() {
   	System.out.println("MyClassRegistry test方法");
   }
}

创建MyImportRegistry 实现ImportBeanDefinitionRegistrar接口 注册我们定义的普通类MyClassRegistry


public class MyImportRegistry implements ImportBeanDefinitionRegistrar{
   @Override
   public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
   	RootBeanDefinition bd = new RootBeanDefinition();
   	bd.setBeanClass(MyClassRegistry.class);
   	registry.registerBeanDefinition("myClassRegistry", bd);
   }
}

import该类


@Import(MyImportRegistry.class)
public class ImportConfig {
   
}

(3)、创建一个普通类MyClassImport


public class MyClassImport {
   
   public void test() {
   	System.out.println("MyClassImport test方法");
   }
}

创建MyImportSelector实现ImportSelector接口 注册我们定义的普通类MyClassImport



public class MyImportSelector implements ImportSelector {

   @Override
   public String[] selectImports(AnnotationMetadata importingClassMetadata) {
   	return new String[] {MyClassImport.class.getName()};
   }

import该类


@Import(MyImportSelector.class)
public class ImportConfig {
   
}

20、@Conditional

@Conditional注解用于根据条件判断是否创建Bean或执行配置。

@Configuration
public class AppConfig {

   @Bean
   @Conditional(DatabaseTypeCondition.class)
   public UserRepository userRepository() {
       return new UserRepositoryImpl();
   }
}

21、@Profile

@Profile:
Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能;

开发环境develop、测试环境test、生产环境master
数据源:(/dev) (/test) (/master)

@Profile:指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件

package com.spring.config;

import java.beans.PropertyVetoException;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.util.StringValueResolver;

import com.mchange.v2.c3p0.ComboPooledDataSource;

/**
* Profile:
* 		Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能;
* 
* 开发环境develop、测试环境test、生产环境master
* 数据源:(/dev) (/test) (/master)
*
* @Profile:指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件
* 
* 1) 加了环境标识的bean,只有这个环境被激活的时候才能注册到容器中。默认是default环境
* 2) 写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效
* 
*/
@PropertySource("classpath:/dbconfig.properties")
@Configuration
public class MainConfigOfProfile implements EmbeddedValueResolverAware{
   
   @Value("${db.user}")
   private String user;
   
   private String driverClass;
   
   @Profile("default")
   @Bean("test")
   public DataSource testDataSource(@Value("${db.password}")String password) throws PropertyVetoException {
   	ComboPooledDataSource dataSource = new ComboPooledDataSource();
   	dataSource.setUser(user);
   	dataSource.setPassword(password);
   	dataSource.setDriverClass(driverClass);
   	return dataSource;
   }
   
   @Profile("dev")
   @Bean("dev")
   public DataSource devDataSource(@Value("${db.password}")String password) throws PropertyVetoException {
   	ComboPooledDataSource dataSource = new ComboPooledDataSource();
   	dataSource.setUser(user);
   	dataSource.setPassword(password);
   	dataSource.setDriverClass(driverClass);
   	return dataSource;
   }
   
   @Profile("master")
   @Bean("master")
   public DataSource masterDataSource(@Value("${db.password}")String password) throws PropertyVetoException {
   	ComboPooledDataSource dataSource = new ComboPooledDataSource();
   	dataSource.setUser(user);
   	dataSource.setPassword(password);
   	dataSource.setDriverClass(driverClass);
   	return dataSource;
   }

   public void setEmbeddedValueResolver(StringValueResolver resolver) {
   	String driverClass = resolver.resolveStringValue("${db.driverClass}");
   	this.driverClass = driverClass;
   }

}

22、@PropertySource

用于指定配置文件的位置。@PropertySource是Spring框架中的一个注解,用于指定一组属性文件的位置,从而可以在Spring应用程序中使用这些属性。

@Configuration
@PropertySource("classpath:application.properties")
public class AppConfig {

   @Autowired
   private Environment environment;

   @Bean
   public UserService userService() {
       return new UserServiceImpl(environment.getProperty("userService.name"));
   }

   // 其他方法
}
这个类使用@Configuration注解标注,表示这个类是一个配置类,用于配置应用程序的Bean对象。

在类级别上,使用@PropertySource注解可以指定一个属性文件的位置。在这个例子中,使用@PropertySource注解指定了一个名为application.properties的属性文件,它位于classpath下。

在方法级别上,使用@Bean注解标注方法,表示这个方法返回一个Bean对象。在这个例子中,使用Environment对象从属性文件中读取属性值,并将这些属性值传递给UserService实例的构造方法。

@PropertySource注解用于指定一组属性文件的位置,使得开发者可以在Spring应用程序中使用这些属性。同时,使用Environment对象可以方便地读取属性文件中的属性值,并将这些属性值传递给Bean对象的构造方法或属性。

@PropertySource注解是Spring框架中比较常用的注解之一,可以让开发者更加灵活地管理和配置Spring Bean。

23、@Qualifier

@Qualifier用于指定注入的Bean的名称。

@Component
public class UserServiceImpl implements UserService {

   @Autowired
   @Qualifier("userRepositoryImpl")
   private UserRepository userRepository;

   // 其他方法
}

24、@ExceptionHandler

@ExceptionHandler注解我们一般是用来自定义异常的。
可以认为它是一个异常拦截器(处理器)。

package com.example.exceptionhandlerdemo;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class GlobalExceptionHandler {

   private final Logger logger = LogManager.getLogger(GlobalExceptionHandler.class);

   @ExceptionHandler({Exception.class})    //申明捕获那个异常类
   public String ExceptionDemo(Exception e) {
       logger.error(e.getMessage(), e);
       return "自定义异常返回";
   }

}

25、@ResponseStatus

可以通过@ResponseStatus注解和自定义异常来配合使用返回自定义响应状态码和自定义错误信息给客户端。

@Controller
@RequestMapping("/responsestatus")
public class ResponseStatusController {
   @ResponseStatus(reason = "这是在方法上通过@ResponseStatus注解定义的信息", value = HttpStatus.NOT_FOUND)
   @RequestMapping("/testResponseStatusExceptionResolverOnMethod")
   public String testResponseStatusExceptionResolverOnMethod(@RequestParam("i") int i){
   	return "success";
   }
}

26、@ControllerAdvice

@ControllerAdvice最常见的使用场景就是全局异常处理。比如文件上传大小限制的配置,如果用户上传的文件超过了限制大小,就会抛出异常,此时可以通过@ControllerAdvice结合@ExceptionHandler定义全局异常捕获机制

@ControllerAdvice
public class CustomExceptionHandler {
   @ExceptionHandler(MaxUploadSizeExceededException.class)
   public void uploadException(MaxUploadSizeExceededException e, HttpServletResponse resp) throws IOException {
       resp.setContentType("text/html;charset=utf-8");
       System.out.println(1111);
       PrintWriter out = resp.getWriter();
       out.write("上传文件大小超出限制!");
       out.flush();
       out.close();
   }
}

27、@CrossOrigin

用于解决跨域问题。
@CrossOrigin是Spring框架中的一个注解,用于解决跨域资源共享(CORS)问题。

跨域资源共享是浏览器安全策略的一部分,它限制了浏览器在不同域名之间发送和接收HTTP请求。使用@CrossOrigin注解可以指定允许跨域访问的域名和HTTP方法。

@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "http://localhost:8080", methods = {RequestMethod.GET, RequestMethod.POST})
public class ApiController {

   @GetMapping("/users")
   public List<User> getUsers() {
       // 查询用户信息
       List<User> users = userService.getUsers();
       return users;
   }
}

这个类使用@RestController注解标注,表示这个类是一个RESTful风格的控制器。在类级别上,使用@RequestMapping注解指定控制器处理的请求路径为/api。同时,使用@CrossOrigin注解可以指定允许跨域访问的域名和HTTP方法。

在这个例子中,使用@CrossOrigin注解指定允许来自http://localhost:8080域名的GETPOST请求访问该控制器中的方法。这意味着,在http://localhost:8080域名下的网页可以通过XMLHttpRequest对象发送GETPOST请求,访问该控制器中的方法。

@CrossOrigin注解用于解决跨域资源共享(CORS)问题,使得开发者可以更加灵活地控制允许跨域访问的域名和HTTP方法。它是一种简单但非常有效的解决方案,可以使得前端开发者更加轻松地开发跨域应用程序。

@CrossOrigin注解是Spring框架中比较常用的注解之一,可以让开发者更加灵活地解决跨域资源共享(CORS)问题。

28、@Async

用于将方法标记为异步执行。

在Spring框架中,如果一个方法需要执行一些比较耗时的操作,如果这个方法是在主线程中执行,就会导致主线程被阻塞,用户界面无法响应用户的操作。使用@Async注解可以将这个方法的执行异步化,让主线程继续执行其他任务,提高应用程序的响应性能。

@Service
public class UserService {

   @Async
   public CompletableFuture<UserDetails> getUserDetailsAsync(Long id) {
       // 查询用户信息
       UserDetails userDetails = userRepository.getUserDetails(id);
       return CompletableFuture.completedFuture(userDetails);
   }
}

这个类使用@Service注解标注,表示这个类是一个服务。在方法级别上,使用@Async注解标注方法,表示这个方法需要异步执行。

在这个例子中,getUserDetailsAsync方法使用@Async注解标注,表示这个方法需要异步执行。查询用户信息的操作在异步线程中执行,不会阻塞主线程。同时,这个方法返回一个CompletableFuture对象,表示异步执行的结果。

@Async注解用于异步执行方法,可以提高应用程序的响应性能。它是一种简单但非常有效的解决方案,可以使得开发者更加轻松地编写并发应用程序。

@Async注解是Spring框架中比较常用的注解之一,可以让开发者更加灵活地异步执行方法。需要注意的是,异步执行的方法必须在一个独立的线程中执行,因此需要使用线程池来管理异步线程的执行。

29、@Cacheable

用于缓存方法的返回值。

在Spring框架中,如果一个方法的返回结果是固定的,而且这个方法的执行比较耗时,我们可以使用@Cacheable注解将这个方法的返回结果缓存起来,下次执行这个方法时直接从缓存中获取结果,避免重复执行。

@Service
public class UserService {

   @Cacheable("userCache")
   public User getUser(Long id) {
       // 查询用户信息
       User user = userRepository.getUser(id);
       return user;
   }
}

这个类使用@Service注解标注,表示这个类是一个服务。在方法级别上,使用@Cacheable注解标注方法,表示这个方法返回的结果可以被缓存起来。

在这个例子中,getUser方法使用@Cacheable注解标注,表示这个方法的返回结果可以被缓存起来。查询用户信息的操作在第一次执行时会被执行,返回结果会被缓存到名为"userCache"的缓存中。下次执行getUser方法时,如果缓存中已经存在这个结果,就直接从缓存中获取结果,不需要再次执行查询操作。

@Cacheable注解用于缓存方法的返回结果,可以提高应用程序的执行效率。它是一种简单但非常有效的解决方案,可以使得开发者更加灵活地使用缓存来优化应用程序的性能。

@Cacheable注解是Spring框架中比较常用的注解之一,可以让开发者更加轻松地使用缓存来提高应用程序的性能。需要注意的是,使用缓存需要考虑缓存的生命周期和缓存的一致性,必要时需要使用缓存失效机制和缓存更新机制来维护缓存的一致性。

30、@CacheEvict

用于清除缓存。

@CacheEvict是Spring框架中的一个注解,用于清空缓存中的数据。

在Spring框架中,如果一个方法的执行会导致缓存数据的失效,我们可以使用@CacheEvict注解将这个方法的缓存数据清空,这样下次执行这个方法时就会重新查询数据并缓存起来。

@Service
public class UserService {

   @Cacheable("userCache")
   public User getUser(Long id) {
       // 查询用户信息
       User user = userRepository.getUser(id);
       return user;
   }
   
   @CacheEvict("userCache")
   public void clearCache() {
       // 清空缓存
   }
}

这个类使用@Service注解标注,表示这个类是一个服务。在方法级别上,使用@Cacheable注解标注getUser方法,表示这个方法的返回结果可以被缓存起来。同时,使用@CacheEvict注解标注clearCache方法,表示这个方法会清空名为"userCache"的缓存。

在这个例子中,getUser方法使用@Cacheable注解标注,表示这个方法的返回结果可以被缓存起来。查询用户信息的操作在第一次执行时会被执行,返回结果会被缓存到名为"userCache"的缓存中。下次执行getUser方法时,如果缓存中已经存在这个结果,就直接从缓存中获取结果,不需要再次执行查询操作。

当调用clearCache方法时,@CacheEvict注解会清空名为"userCache"的缓存,下次执行getUser方法时,就需要重新查询数据并缓存起来。

@CacheEvict注解用于清空缓存中的数据,可以使得开发者更加灵活地控制缓存的生命周期和缓存的一致性。它是一种简单但非常有效的解决方案,可以使得开发者更加轻松地使用缓存来提高应用程序的性能。

@CacheEvict注解是Spring框架中比较常用的注解之一,可以让开发者更加灵活地控制缓存的生命周期和缓存的一致性。需要注意的是,清空缓存需要谨慎操作,必要时需要考虑缓存的失效机制和缓存更新机制来维护缓存的一致性。

31、@CachePut

用于更新缓存中的数据。

@CachePut是Spring框架中的一个注解,用于更新或添加缓存中的数据。

在Spring框架中,如果一个方法的执行会导致缓存数据的更新或添加,我们可以使用@CachePut注解将这个方法的返回结果更新或添加到缓存中。

@Service
public class UserService {

   @Cacheable("userCache")
   public User getUser(Long id) {
       // 查询用户信息
       User user = userRepository.getUser(id);
       return user;
   }
   
   @CachePut("userCache")
   public User updateUser(Long id, User user) {
       // 更新用户信息
       User updatedUser = userRepository.updateUser(id, user);
       return updatedUser;
   }
}

这个类使用@Service注解标注,表示这个类是一个服务。在方法级别上,使用@Cacheable注解标注getUser方法,表示这个方法的返回结果可以被缓存起来。同时,使用@CachePut注解标注updateUser方法,表示这个方法会更新或添加名为"userCache"的缓存。

在这个例子中,getUser方法使用@Cacheable注解标注,表示这个方法的返回结果可以被缓存起来。查询用户信息的操作在第一次执行时会被执行,返回结果会被缓存到名为"userCache"的缓存中。下次执行getUser方法时,如果缓存中已经存在这个结果,就直接从缓存中获取结果,不需要再次执行查询操作。

当调用updateUser方法时,@CachePut注解会更新或添加名为"userCache"的缓存,下次执行getUser方法时,就可以从缓存中获取更新后的用户信息。

@CachePut注解用于更新或添加缓存中的数据,可以使得开发者更加灵活地控制缓存的生命周期和缓存的一致性。它是一种简单但非常有效的解决方案,可以使得开发者更加轻松地使用缓存来提高应用程序的性能。

@CachePut注解是Spring框架中比较常用的注解之一,可以让开发者更加灵活地控制缓存的生命周期和缓存的一致性。需要注意的是,更新或添加缓存需要谨慎操作,必要时需要考虑缓存的失效机制和缓存更新机制来维护缓存的一致性。

32、@Transactional

@Transactional注解是Spring框架提供的一个用于声明式事务管理的注解。它可以应用在方法或类上,用于标识需要进行事务管理的方法或类。通过使用@Transactional注解,我们可以更加方便地管理事务,保障数据的一致性和可靠性

  @Transactional(rollbackFor = Exception.class)
   private void executeInsertSQL(String tableName,String columnName,String placeholderOfColumnName,List<String> fieldNameList,List<Object> valuesOfField ) throws SQLException {
       TransactionStatus transactionStatus=null;
       PlatformTransactionManager transactionManager=null;
       try{
           String sql = "insert into "+tableName+"  (" + columnName + ") values(" + placeholderOfColumnName + ")";
           //获取EntityManager对象
           EntityManager entityManager = Actor.applicationContext.getBean(EntityManager.class);
           transactionManager = Actor.applicationContext.getBean(PlatformTransactionManager.class);

           //手动开启事务
           transactionStatus= transactionManager.getTransaction(new DefaultTransactionDefinition());
           // 使用EntityManager执行JPA操作
           Query nativeQuery = entityManager.createNativeQuery(sql);
           for (int i=0;i<valuesOfField.size();i++){
               nativeQuery.setParameter(fieldNameList.get(i), valuesOfField.get(i));
           }

           nativeQuery.executeUpdate();
           //手动提交事务
           transactionManager.commit(transactionStatus);
       }catch (Exception e){
           if(transactionStatus!=null ){
               //回滚事务
               transactionManager.rollback(transactionStatus);
           }
           e.printStackTrace();

       }
   }

33、@EnableTransactionManagement

用于启用事务管理功能。

@Transactional是Spring框架中的一个注解,用于标识一个方法或类需要使用事务进行操作。

在Spring框架中,如果一个方法需要对数据库进行操作,我们可以使用@Transactional注解来确保这个操作在一个事务中进行,从而保证操作的原子性、一致性、隔离性和持久性。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
// 通过@Import导入TransactionManagementConfigurationSelector组件
@Import(TransactionManagementConfigurationSelector.class) 
public @interface EnableTransactionManagement {

   boolean proxyTargetClass() default false;

   AdviceMode mode() default AdviceMode.PROXY;
   
   int order() default Ordered.LOWEST_PRECEDENCE;
}

34、@EnableAspectJAutoProxy

用于启用AOP功能。

@EnableAspectJAutoProxy是Spring框架中的一个注解,用于启用自动代理功能,以便使用AOP(面向切面编程)进行编程。

在Spring框架中,如果需要使用AOP来实现某些功能,我们可以使用@EnableAspectJAutoProxy注解来启用自动代理功能,从而在运行时自动为我们生成代理对象,以便进行切面编程。

@Configuration
@EnableAspectJAutoProxy
public class AppConfig {

   @Bean
   public MyAspect myAspect() {
       return new MyAspect();
   }
   
   @Bean
   public UserService userService() {
       return new UserService();
   }
}

这个类使用@Configuration注解标注,表示这个类是一个配置类。同时,在类级别上使用@EnableAspectJAutoProxy注解标注,表示这个配置类需要启用自动代理功能。

在这个例子中,我们定义了一个MyAspect类来实现某些功能的切面编程。为了让Spring框架能够自动为我们生成代理对象,我们需要将MyAspect类加入到Spring容器中,并且使用@Bean注解标注。另外,我们还定义了一个UserService类来实现某些业务功能。

@EnableAspectJAutoProxy注解用于启用自动代理功能,可以使得开发者更加方便地使用AOP来实现某些功能。它是一种简单但非常有效的解决方案,可以让开发者更加轻松地使用切面编程来提高应用程序的性能和可维护性。

@EnableAspectJAutoProxy注解是Spring框架中比较常用的注解之一,可以让开发者更加方便地使用AOP来实现某些功能。需要注意的是,AOP的使用需要谨慎操作,必要时需要考虑AOP的切面逻辑、切入点和通知类型等来维护应用程序的性能和可维护性。

35、@Aspect

用于定义切面。

@Aspect是Spring框架中的一个注解,用于标识一个类为切面类,从而可以在该类中定义切面逻辑以实现AOP(面向切面编程)。

在Spring框架中,如果需要使用AOP来实现某些功能,我们可以使用@Aspect注解来标识一个类为切面类。在切面类中,我们可以定义切面逻辑,包括切入点、通知类型和切面顺序等,从而实现AOP编程的功能。

@Aspect
@Component
public class MyAspect {

   @Before("execution(* com.example.UserService.*(..))")
   public void beforeAdvice() {
       System.out.println("Before advice is executed.");
   }
   
   @After("execution(* com.example.UserService.*(..))")
   public void afterAdvice() {
       System.out.println("After advice is executed.");
   }
}

这个类使用@Aspect注解标识,表示这个类是一个切面类。同时,我们还使用@Component注解标识这个类,以便Spring框架能够自动将它加入到Spring容器中。

在这个例子中,我们定义了一个MyAspect类来实现某些功能的切面编程。在这个类中,我们定义了两个通知类型,即@Before和@After,分别表示在目标方法执行前和执行后执行某些操作。这些通知类型的执行条件是通过切入点表达式来定义的。

@Aspect注解用于标识一个类为切面类,可以使得开发者更加方便地使用AOP来实现某些功能。它是一种简单但非常有效的解决方案,可以让开发者更加轻松地使用切面编程来提高应用程序的性能和可维护性。

@Aspect注解是Spring框架中比较常用的注解之一,用于标识一个类为切面类。需要注意的是,AOP的使用需要谨慎操作,必要时需要考虑切入点、通知类型和切面顺序等来维护应用程序的性能和可维护性。

36、@Pointcut

用于定义切点。

@Pointcut是Spring框架中的一个注解,用于定义一个切入点,从而可以在该切入点上定义通知类型以实现AOP(面向切面编程)。

在Spring框架中,如果需要使用AOP来实现某些功能,我们可以使用@Pointcut注解来定义一个切入点。在切入点上,我们可以定义切面逻辑,包括通知类型和切面顺序等,从而实现AOP编程的功能。

@Aspect
@Component
public class MyAspect {

   @Pointcut("execution(* com.example.UserService.*(..))")
   public void userServicePointcut() {}
   
   @Before("userServicePointcut()")
   public void beforeAdvice() {
       System.out.println("Before advice is executed.");
   }
   
   @After("userServicePointcut()")
   public void afterAdvice() {
       System.out.println("After advice is executed.");
   }
}

这个类使用@Aspect注解标识,表示这个类是一个切面类。同时,我们还使用@Component注解标识这个类,以便Spring框架能够自动将它加入到Spring容器中。

在这个例子中,我们定义了一个MyAspect类来实现某些功能的切面编程。在这个类中,我们使用@Pointcut注解定义了一个切入点,即userServicePointcut()方法。在这个切入点上,我们定义了两个通知类型,即@Before和@After,分别表示在目标方法执行前和执行后执行某些操作。

@Pointcut注解用于定义一个切入点,可以使得开发者更加方便地使用AOP来实现某些功能。它是一种简单但非常有效的解决方案,可以让开发者更加轻松地使用切面编程来提高应用程序的性能和可维护性。

@Pointcut注解是Spring框架中比较常用的注解之一,用于定义一个切入点。需要注意的是,AOP的使用需要谨慎操作,必要时需要考虑切入点、通知类型和切面顺序等来维护应用程序的性能和可维护性。

37、@Before

用于在方法执行前执行通知。

@Before是Spring框架中的一个注解,用于定义在目标方法执行前执行的通知类型,以实现AOP(面向切面编程)。

在Spring框架中,如果需要在目标方法执行前执行某些操作,我们可以使用@Before注解来定义一个通知类型。在这个通知类型中,我们可以编写自己的逻辑代码,从而实现AOP编程的功能。

@Aspect
@Component
public class MyAspect {

   @Before("execution(* com.example.UserService.*(..))")
   public void beforeAdvice() {
       System.out.println("Before advice is executed.");
   }
}


38、@After

用于在方法执行后执行通知。

@After是Spring框架中的一个注解,用于定义在目标方法执行后执行的通知类型,以实现AOP(面向切面编程)。

在Spring框架中,如果需要在目标方法执行后执行某些操作,我们可以使用@After注解来定义一个通知类型。在这个通知类型中,我们可以编写自己的逻辑代码,从而实现AOP编程的功能。

@Aspect
@Component
public class MyAspect {

   @After("execution(* com.example.UserService.*(..))")
   public void afterAdvice() {
       System.out.println("After advice is executed.");
   }
}

39、@Around

用于在方法执行前后执行通知。

@Around是Spring框架中的一个注解,用于定义在目标方法执行前后执行的通知类型,以实现AOP(面向切面编程)。

在Spring框架中,如果需要在目标方法执行前后执行某些操作,我们可以使用@Around注解来定义一个通知类型。在这个通知类型中,我们可以编写自己的逻辑代码,从而实现AOP编程的功能。

@Aspect
@Component
public class MyAspect {

   @Around("execution(* com.example.UserService.*(..))")
   public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
       System.out.println("Before advice is executed.");
       Object result = joinPoint.proceed();
       System.out.println("After advice is executed.");
       return result;
   }
}

40、@AfterReturning

用于在方法返回结果后执行通知。

@AfterReturning是Spring框架中的一个注解,用于定义在目标方法返回结果后执行的通知类型,以实现AOP(面向切面编程)。

在Spring框架中,如果需要在目标方法返回结果后执行某些操作,我们可以使用@AfterReturning注解来定义一个通知类型。在这个通知类型中,我们可以编写自己的逻辑代码,从而实现AOP编程的功能。

@Aspect
@Component
public class MyAspect {

   @AfterReturning(pointcut = "execution(* com.example.UserService.*(..))", returning = "result")
   public void afterReturningAdvice(Object result) {
       System.out.println("After returning advice is executed. Result is " + result);
   }
}

41、@AfterThrowing

用于在方法抛出异常后执行通知。

@AfterThrowing是Spring框架中的一个注解,用于定义在目标方法抛出异常后执行的通知类型,以实现AOP(面向切面编程)。

在Spring框架中,如果需要在目标方法抛出异常后执行某些操作,我们可以使用@AfterThrowing注解来定义一个通知类型。在这个通知类型中,我们可以编写自己的逻辑代码,从而实现AOP编程的功能。

@Aspect
@Component
public class MyAspect {

   @AfterThrowing(pointcut = "execution(* com.example.UserService.*(..))", throwing = "ex")
   public void afterThrowingAdvice(Exception ex) {
       System.out.println("After throwing advice is executed. Exception is " + ex);
   }
}

42、@Order

用于指定切面的执行顺序。

@Order是Spring框架中的一个注解,用于定义切面的执行顺序。

在Spring框架中,如果有多个切面类需要对同一个方法进行切面处理,那么这些切面类的执行顺序可能会影响到最终的结果。为了控制这些切面类的执行顺序,我们可以使用@Order注解来定义它们的执行顺序。

@Order注解可以应用在切面类上,用于指定切面执行的顺序。它的参数为一个整数,数值越小表示优先级越高,数值相同时按照类名的自然顺序进行排序。

@Aspect
@Component
@Order(1)
public class MyAspect1 {

   @Before("execution(* com.example.UserService.*(..))")
   public void beforeAdvice() {
       System.out.println("Before advice from MyAspect1 is executed.");
   }
}

@Aspect
@Component
@Order(2)
public class MyAspect2 {

   @Before("execution(* com.example.UserService.*(..))")
   public void beforeAdvice() {
       System.out.println("Before advice from MyAspect2 is executed.");
   }
}

43、@Slf4j

用于简化日志记录。

@Slf4j是Lombok框架中的一个注解,用于在Java类中自动生成日志记录器。

在Java开发中,日志记录是非常重要的一环,可以帮助我们更好地了解程序的运行情况,从而更好地进行调试和优化。通常情况下,我们需要手动引入日志框架(如Log4j、SLF4J等)并编写相应的日志记录代码。这些代码可能会比较繁琐,而且容易出现错误。为了简化这个过程,Lombok框架提供了一个@Slf4j注解,可以在Java类中自动生成日志记录器。

使用@Slf4j注解非常简单,只需要在Java类中添加这个注解即可。在使用时,我们可以直接使用log变量来记录日志,而不需要再引入其他的日志框架

@Slf4j
public class MyService {

   public void doSomething() {
       log.debug("This is a debug message.");
       log.info("This is an info message.");
       log.error("This is an error message.");
   }
}

在这个例子中,我们定义了一个MyService类,并使用@Slf4j注解来自动生成日志记录器。然后,在doSomething()方法中,我们直接使用log变量来记录日志,而不需要再引入其他的日志框架。

需要注意的是,使用@Slf4j注解需要在编译器中安装Lombok插件,否则可能会出现编译错误。另外,虽然@Slf4j注解非常方便,但在实际应用中,我们还需要根据实际情况选择合适的日志框架,并编写相应的日志记录代码。

总之,@Slf4j是Lombok框架中的一个注解,可以在Java类中自动生成日志记录器,从而简化日志记录的过程。它是一种极为方便的解决方案,可以提高应用程序的可维护性和可读性。

44、@Data

用于自动生成JavaBean的getters、setters、toString、hashCode和equals方法。

@Data是Lombok框架中的一个注解,可以自动生成Java类的getter、setter、equals、hashCode和toString等方法。

在Java开发中,我们经常需要编写一些POJO类来表示数据结构。这些类通常包含一些成员变量,并且需要编写相应的getter、setter、equals、hashCode和toString等方法。这些方法通常是相似的,而且比较繁琐。为了简化这个过程,Lombok框架提供了一个@Data注解,可以自动生成这些方法。

使用@Data注解非常简单,只需要在Java类上添加这个注解即可。在使用时,我们可以直接访问类的成员变量,并且可以自动生成相应的getter、setter、equals、hashCode和toString等方法。

@Data
public class User {
   private Long id;
   private String name;
   private Integer age;
}

45、@NoArgsConstructor

用于生成无参构造函数。

@NoArgsConstructor是Lombok框架中的一个注解,用于自动生成一个无参构造方法。

在Java开发中,我们经常需要编写一些POJO类来表示数据结构。这些类通常包含一些成员变量,并且需要编写相应的构造方法。在某些情况下,我们可能需要编写一个无参构造方法,用于创建一个对象的实例。这个构造方法通常是简单的、无需参数的。为了简化这个过程,Lombok框架提供了一个@NoArgsConstructor注解,可以自动生成一个无参构造方法。

使用@NoArgsConstructor注解非常简单,只需要在Java类上添加这个注解即可。在使用时,我们可以直接创建对象的实例,而不需要手动编写无参构造方法。

@NoArgsConstructor
public class User {
   private Long id;
   private String name;
   private Integer age;
}

在这个例子中,我们定义了一个User类,并使用@NoArgsConstructor注解来自动生成一个无参构造方法。然后,在其他的Java类中,我们可以直接创建User对象的实例,而不需要手动编写无参构造方法。

需要注意的是,使用@NoArgsConstructor注解需要在编译器中安装Lombok插件,否则可能会出现编译错误。另外,虽然@NoArgsConstructor注解非常方便,但在实际应用中,我们还需要根据实际情况选择合适的构造方法,并编写相应的代码。

总之,@NoArgsConstructor是Lombok框架中的一个注解,用于自动生成一个无参构造方法,从而简化Java开发的过程。它是一种极为方便的解决方案,可以提高应用程序的可维护性和可读性。

46、@AllArgsConstructor

用于生成全参构造函数。

@AllArgsConstructor是Lombok框架中的一个注解,用于自动生成一个全参构造方法。

在Java开发中,我们经常需要编写一些POJO类来表示数据结构。这些类通常包含一些成员变量,并且需要编写相应的构造方法。在某些情况下,我们可能需要编写一个全参构造方法,用于初始化所有成员变量。这个构造方法通常包含所有成员变量作为参数。为了简化这个过程,Lombok框架提供了一个@AllArgsConstructor注解,可以自动生成一个全参构造方法。

使用@AllArgsConstructor注解非常简单,只需要在Java类上添加这个注解即可。在使用时,我们可以直接创建对象的实例,并传入相应的参数,而不需要手动编写全参构造方法。

@AllArgsConstructor
public class User {
   private Long id;
   private String name;
   private Integer age;
}

在这个例子中,我们定义了一个User类,并使用@AllArgsConstructor注解来自动生成一个全参构造方法。然后,在其他的Java类中,我们可以直接创建User对象的实例,并传入相应的参数,而不需要手动编写全参构造方法。

需要注意的是,使用@AllArgsConstructor注解需要在编译器中安装Lombok插件,否则可能会出现编译错误。另外,虽然@AllArgsConstructor注解非常方便,但在实际应用中,我们还需要根据实际情况选择合适的构造方法,并编写相应的代码。

总之,@AllArgsConstructor是Lombok框架中的一个注解,用于自动生成一个全参构造方法,从而简化Java开发的过程。它是一种极为方便的解决方案,可以提高应用程序的可维护性和可读性。

}
```# 18、@Bean
该注释的属性的名称和语义类似于Spring XML模式中bean的元素的名称和语义。@Bean指示方法产生一个由Spring容器管理的bean。

```javascript
@Configuration
public class DataBaseConfig {
   @Bean("dataSource")
   public DataSource getDataSource(){
       DataSource dataSource = new DataSource();
       dataSource.setUserId("jingsi");
       dataSource.setPassword("123456");
       dataSource.setUrl("www");
       return dataSource;
   }

}

47、@Builder

用于生成Builder模式的构造函数。

@Builder是Lombok框架中的一个注解,用于自动生成一个Builder模式的构造器。

在Java开发中,我们经常需要编写一些POJO类来表示数据结构。这些类通常包含一些成员变量,并且需要编写相应的构造方法。在某些情况下,我们可能需要编写一个Builder模式的构造器,用于方便地创建对象实例。Builder模式是一种创建对象的设计模式,它可以通过链式调用的方式设置对象的属性,并最终创建一个不可变的对象。为了简化这个过程,Lombok框架提供了一个@Builder注解,可以自动生成一个Builder模式的构造器。

使用@Builder注解非常简单,只需要在Java类上添加这个注解即可。在使用时,我们可以使用链式调用的方式设置对象的属性,并最终创建一个不可变的对象。

@Builder
public class User {
   private Long id;
   private String name;
   private Integer age;
}
在这个例子中,我们定义了一个User类,并使用@Builder注解来自动生成一个Builder模式的构造器。然后,在其他的Java类中,我们可以使用链式调用的方式设置User对象的属性,并最终创建一个不可变的对象。

需要注意的是,使用@Builder注解需要在编译器中安装Lombok插件,否则可能会出现编译错误。另外,虽然@Builder注解非常方便,但在实际应用中,我们还需要根据实际情况选择合适的构造方法,并编写相应的代码。

总之,@Builder是Lombok框架中的一个注解,用于自动生成一个Builder模式的构造器,从而简化Java开发的过程。它是一种极为方便的解决方案,可以提高应用程序的可维护性和可读性。

48、@EqualsAndHashCode

用于生成hashCode和equals方法。

@EqualsAndHashCode是Lombok框架中的一个注解,用于自动生成equals()和hashCode()方法。

在Java开发中,我们经常需要比较两个对象是否相等,并且需要根据对象的属性生成一个hashCode值。为了简化这个过程,Lombok框架提供了一个@EqualsAndHashCode注解,可以自动生成equals()和hashCode()方法。

使用@EqualsAndHashCode注解非常简单,只需要在Java类上添加这个注解即可。在使用时,Lombok会根据类的属性自动生成equals()和hashCode()方法。如果两个对象的所有属性都相等,那么它们的equals()方法返回true,并且它们的hashCode()方法返回相同的值。

@EqualsAndHashCode
public class User {
   private Long id;
   private String name;
   private Integer age;
}

49、@ToString

用于生成toString方法。

@ToString是Lombok框架中的一个注解,用于自动生成toString()方法。

在Java开发中,我们经常需要将对象转换为字符串,以便于输出或日志记录。为了简化这个过程,Lombok框架提供了一个@ToString注解,可以自动生成toString()方法。

使用@ToString注解非常简单,只需要在Java类上添加这个注解即可。在使用时,Lombok会根据类的属性自动生成toString()方法,这个方法将输出类的名称和所有属性的名称和值。如果需要排除某些属性,可以使用exclude属性来指定排除的属性。

@ToString(exclude = "password")
public class User {
   private Long id;
   private String name;
   private String password;
}

50、@Getter

用于生成getters方法。

@Getter是Lombok框架中的一个注解,用于自动生成getter方法。

在Java开发中,我们经常需要为类的属性编写getter和setter方法。为了简化这个过程,Lombok框架提供了一个@Getter注解,可以自动生成getter方法。

使用@Getter注解非常简单,只需要在Java类上添加这个注解即可。在使用时,Lombok会根据类的属性自动生成对应的getter方法。如果需要生成setter方法,可以使用@Setter注解。

@Getter
public class User {
   private Long id;
   private String name;
   private Integer age;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

smileAgain-lg

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值