学习JavaWeb(包含SpringBoot框架)所用到的注解

一. 简化开发

1.@Slf4j

@Slf4j是用作日志输出的,一般会在项目每个类的开头加入该注解。

@Slf4j
@RestController
public class LoginController {
    @Autowired
    private EmpService empService;
    @PostMapping("/login")
    public Result login(@RequestBody Emp emp){
        log.info("员工登录:{}",emp);
        Emp e= empService.login(emp);

效果等同于:

private final Logger logger = LoggerFactory.getLogger(当前类名.class);
2、几个常用的 lombok 注解:

[ Lombok(https://so.csdn.net/so/search?q=Lombok&spm=1001.2101.3001.7020)是一个实用的Java类库,能通过注解的形式自动生成构造器、getter/setter、equals、hashcode、toString 等方法,并可以自动化生成日志变量,简化java开发、提高效率。

package com.itheima.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DeptLog {
    private Integer id;
    private LocalDateTime createTime;
    private String description;
}

二. Spring Bean相关

1.@Autowired

@Autowired可以标注在构造器、方法、参数、字段以及派生注解上,所以注入时机非常多,可以准确的控制在何时、何处注入以及如何注入。@Autowired注解是Spring框架提供的注解,它根据类型进行[自动装配。

使用SpringBoot框架中的IOC容器与DI注入(分层解耦),从bean中获取要使用的对象,使用@Autowired注入。

@Slf4j
@RequestMapping("/depts")
@RestController
public class DeptController {
    @Autowired
    private DeptService deptService;
2.@Resource

@Resource注解是JavaEE提供的注解,也可以用于依赖注入。它提供了更灵活的方式进行依赖对象的查找,可以按照名称或类型进行注入。

@Component
public class UserService {
    @Autowired
    private User user;
}

在上述示例中,使用@Resource注解将User对象注入到UserService类的中,@Resource注解默认按照字段名进行依赖对象的查找和匹配,也可以通过name属性指定依赖对象的名称

@Autowired & @Resource的区别 1.@Autowired注解是Spring提供的,用于自动装配Bean依赖。它可以通过类型匹配来自动注入依赖对象,但如果存在多个符合条件的候选对象时,默认使用byType的方式进行自动装配。

2.@Resource注解是JavaEE提供的,也可以用于自动装配依赖对象。它可以通过名称匹配来自动注入依赖对象,默认使用byName的方式进行自动装配。

3.@RestController

现在都是前后端分离,一般都不用@Controller注解,而是使用@RestController注解。@RestController注解是@Controller和@ResponseBody的合集,表示这是个控制器 bean,并且是将函数的返回值直 接填入 HTTP 响应体中,是 REST 风格的控制器。

@RestController的优点:

1.@RestController为开发提供了方便,在提供json接口时需要的配置操作再也不需要自己配置了。 2.@RestController注解相当于@ResponseBody和@Controller的结合 3.@RestController注解时,返回的是内容实例

@RestController
public class DeptController {
    @Autowired
    private DeptService deptService;
3.1@ResponseBody

用于将方法的返回值直接作为响应体返回给客户端,通常用于返回JSON或XML格式的响应数据。

3.2@Controller(一般不常用,开发中多用@RestController)

@Controller是一种特殊化的@Component类,该注解标记一个类作为Spring MVC控制器,在实际操作中@Controller用来处理HTTP请求和响应,她通常与@ResponseBody绑定使用,二者即为@RestController

适用场景:在使用Spring MVC进行Web开发时,需要使用@Controller注解来标记Controller层,让Spring识别。

@Controller
@ResponseBody
public @interface RestController {
    @AliasFor(
        annotation = Controller.class
    )
    String value() default "";
}
4.@Service

该注解标记一个类作为Spring的业务逻辑组件--Service层

适用场景:在使用Spring进行业务逻辑开发时,需要使用@Service注解来标记服务类,让Spring识别。

且@Service注解在service层接口的实现类中定义,在service接口中不使用。

5.@Mapper && @Repository

@Mapper 和 @Repository都是在开发中用来管理bean容器中Mapper对象的注解。

  • @Repository是Spring框架提供的注解,用于标识一个类为DAO组件,并将其注册为Spring容器的bean。通常,使用@Repository的类需要配合@EnableJpaRepositories或@MapperScan注解,在Spring配置中进行组件扫描,以便Spring能够识别并管理这些bean。

    @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是MyBatis框架的注解,用于标记接口作为数据库操作的映射器。MyBatis在运行时会根据这个注解自动生成代理对象,实现数据库操作的方法。使用@Mapper时,不需要在Spring配置中额外配置组件扫描,因为它可以通过映射器接口的namespace属性找到对应的mapper文件。

总结来说,@Repository需要配合Spring的组件扫描机制使用,而@Mapper则可以单独使用,不需要Spring的额外配置。@Repository多了一个配置扫描地址的步骤。

6@Component

----@Controller、@Service和@Mapper则是@Component更具体的角色注解

1.把普通POJO(Plain Ordinary Java Object简单的java对象)实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>,表示这个类会被Spring进行管理 2.泛指组件,当组件不好归类的时候,可以使用@Component注解进行标注

实例化对象当 Spring 容器启动时,会扫描配置文件或基于注解的配置类,并创建被 @Component 注解标记的类的实例。对象的创建工作由 Spring 容器完成。
组件扫描@Component 注解是基于组件扫描的机制实现的。Spring 容器会扫描指定的包路径,查找所有被 @Component 注解标记的类,并将其实例化为 Spring 管理的组件。
依赖注入@Component 注解标记的类可以通过 Spring 的依赖注入机制获取其他组件的实例。使用 @Autowired 或其他注解来注入依赖的组件。
AOP 支持@Component 注解是实现面向切面编程(AOP)的基础。通过在组件类上添加 @Aspect 注解,将其标记为切面类,实现对方法的增强、日志记录、事务管理等功能。

注:Controller层:@RestController(@Controller+@ResponseBody)**

Service层:@ServiceImpl

Mapper层:@Mapper

三. 处理常见的HTTP请求类型

@RequestMapping和@ResponseBody是Spring MVC中用于处理HTTP请求和响应的注解

1 @RequestMapping

由于使用@RequsetMapping还需指定method = RequestMethod.GET,在实际开发中操作复杂不精炼,可以在@Controller层每个方法中根据目标确定请求类型。而当响应路径有统一的前缀时,在@Controller类前加上@RequsetMapping("/emps")可以简化开发。

@Slf4j
@RequestMapping("/depts")
@RestController
public class DeptController {
    @Autowired
    private DeptService deptService;
    //@RequestMapping(value = "/depts",method = RequestMethod.GET) //指定请求方式为GET
    @GetMapping
    public Result list(){
        log.info("查询全部部门数据");
        //调用service查询部门数据
        List<Dept> deptList =  deptService.list();
        return Result.success(deptList);
    }
}

5种常见的请求类型:

GET :请求从服务器获取特定资源。例如:GET /emps

POST :在服务器上创建一个新的资源。例如:POST /emps

PUT :更新服务器上的资源(客户端提供更新后的整个资源)。例如:PUT /emps/1

DELETE :从服务器删除特定的资源。例如:DELETE /emps/1

PATCH :更新服务器上的资源(客户端提供更改的属性,可以看做作是部分更新),使用的比较少,这里就不举例子了。

1.1Get请求-@GetMapping

@GetMapping("users") 等价于@RequestMapping(value="/users",method=RequestMethod.GET)

 @PostMapping
    public Result add(@RequestBody Dept dept){
        log.info("新增部门,dept: {}" , dept);
        //调用service新增部门
        deptService.add(dept);
        return Result.success();
    }
1.2Post请求-@PostMapping

@PutMapping("/users/{userId}") 等价于@RequestMapping(value="/users/{userId}",method=RequestMethod.PUT)

   @PostMapping
    public Result add(@RequestBody Dept dept){
        log.info("新增部门,dept: {}" , dept);
        //调用service新增部门
        deptService.add(dept);
        return Result.success();
    }
1.3Put请求-@PutMapping

@PutMapping("/users/{userId}") 等价于@RequestMapping(value="/users/{userId}",method=RequestMethod.PUT)

 @PutMapping
    public Result update(@RequestBody Dept dept){
        log.info("更新部门,dept: {}" , dept);
        deptService.update(dept);
        return Result.success();
    }
1.4Delete请求-@DeleteMapping

@DeleteMapping("/users/{userId}")等价于@RequestMapping(value="/users/{userId}",method=RequestMethod.DELETE)

 @DeleteMapping("/{id}")
    public Result delete(@PathVariable Integer id) throws Exception {
        log.info("根据id删除部门:{}",id);
        //调用service删除部门
        deptService.delete(id);
        return Result.success();
    }
2 @ResponseBody

@ResponseBody注解用于指示方法返回的结果要作为响应体直接返回,而不是视图名称。当使用@ResponseBody注解时,返回的数据会直接序列化为JSON或其他格式的响应体返回给客户端。

@Controller
@RequestMapping("/users")
public class UserController {
    @GetMapping("/{id}")
    @ResponseBody
    public User getUserById(@PathVariable Long id) {
        // 根据ID查询用户信息并返回
        User user = userService.getUserById(id);
        return user;
    }
}

四. 前后端传值

@PathVariable和@RequestParam

@PathVariable用于获取路径参数,@RequestParam用于获取查询参数

get请求的参数接收一般依赖这两个注解,但是处于 url 有长度限制和代码的可维护性,超过 5 个参数尽量用实体来传参;

1.@PathVariable

@PathVariable注解用于从请求的URL路径中获取参数值。它将URL中的占位符与方法参数进行绑定。

 @GetMapping("/{id}")
    public Result selectID(@PathVariable Integer id){
        log.info("根据ID查询部门数据,id: {}" , id);
        Dept dept= deptService.selectId(id);
        return Result.success(dept);
    }

如果方法参数名称和需要绑定的url中变量名称不一致时,写成:

 @GetMapping("/{id}")
    public Result selectID(@PathVariable(id) Integer Id){
        log.info("根据ID查询部门数据,Id: {}" , Id);
        Dept dept= deptService.selectId(Id);
        return Result.success(dept);
    }
2.@RequestBody

用于读取 Request 请求的 body 部分,并且Content-Type 为 application/json 格式的数据,接收到数据之后会自动将数据绑定到 Java 对象上去。系统会使用HttpMessageConverter或者自定义的HttpMessageConverter将请求的 body 中的 json 字符串转换为 java 对象

需要注意的是:一个请求方法只可以有一个@RequestBody,但是可以有多个@RequestParam和@PathVariable。如果你的方法必须要用两个 @RequestBody来接受数据的话,大概率是你的数据库设计或者系统设计出问题了!

@PutMapping
    public Result update(@RequestBody Dept dept){
        log.info("更新部门,dept: {}" , dept);
        deptService.update(dept);
        return Result.success();
    }
   @PostMapping
    public Result add(@RequestBody Dept dept){
        log.info("新增部门,dept: {}" , dept);
        //调用service新增部门
        deptService.add(dept);
        return Result.success();
    }

post和put 请求的参数推荐使用 @RequestBody 请求体参数。

3.@RequestParam

用于将指定的请求参数赋值给方法中的形参。

语法:@RequestParam(value=”参数名”,required=”true/false”,defaultValue=””)

有三个属性:

(1)value:请求参数名(必须配置)

(2)required:是否必需,默认为 true,即 请求中必须包含该参数,如果没有包含,将会抛出异常(可选配置)

(3)defaultValue:默认值,如果设置了该值,required 将自动设为 false,无论你是否配置了required,配置了什么值,都是 false(可选配置)

 @GetMapping
    public Result page(@RequestParam(defaultValue = "1") Integer page,
                       @RequestParam(defaultValue = "10") Integer pageSize,
                       String name, Short gender,
                       @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
                       @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){
        log.info("分页查询, 参数: {},{},{},{},{},{}",page,pageSize,name,gender,begin,end);
        //调用service分页查询
        PageBean pageBean = empService.page(page,pageSize,name,gender,begin,end);
        return Result.success(pageBean);
    }

在Spring MVC中,使用@RequestParam注解可以将请求参数绑定到控制器方法的形参上。如果你的GET请求中有多个参数,你可以为每个参数使用一个@RequestParam注解,这样可以清晰地表明每个参数的意图和用途。

五. 读取配置信息

1.@Configuration

说明:该注解标记一个类为Spring的配置类,通常会包含@Bean和@Value等注解

适用场景:在使用Spring进行配置时,可以使用@Configuration注解定义配置类,定义Bean以及读取属性文件或环境变量等。

@Configuration
public class AppConfig {
    @Bean
    public User user() {
        ...
    }
​
    @Value("${app.name}")
    private String appName;
}
2. @Bean

说明:该注解用于将方法返回的对象注入到Spring容器中。

适用场景:在使用Java代码配置Bean时,需要使用@Bean注解将方法返回的对象注册到Spring容器中。

@Configuration
public class AppConfig {
    @Bean
    public User user() {
        ...
    }
}
3.@value(常用)

该注解用于从属性文件或环境变量中读取值注入到字段或方法参数中

适用场景:在使用Java代码配置属性时,使用@Value注解可以方便地读取配置文件或环境变量的值。

@Configuration
public class AppConfig {
    @Value("${app.name}")
    private String appName;
}
4.@Conditional

说明:该注解根据指定条件决定是否创建bean。

适用场景:当Bean的创建条件比较复杂时,可以使用@Conditional注解来定义判断条件。

@Bean
@Conditional(DevEnvironmentCondition.class)
public UserService userService() {
    ...
}
5.@Profile

说明:该注解标记一个bean为某个环境(如dev、test、prod)下使用的bean

适用场景:在开发环境、测试环境和生产环境下需要使用不同的配置,可以使用@Profile注解定义不同环境下的Bean。

6.@ConfigurationProperties

只要在 Bean 上添加上了这个注解,指定好配置文件的前缀,那么对应的配置文件数据就会自动填充到 Bean 中来获取到配置文件数据

@Data
@Component
@ConfigurationProperties(prefix = "aliyun.oss")//该属性可以批量的将外部的属性配置注入到bean对象的属性中
public class AliOSSProperties {
    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;
}

六.异常处理

1.@RestControllerAdvice

用于定义全局异常处理器类,可以捕获应用中抛出的异常,它可以用于捕获应用中抛出的异常,并统一处理这些异常,提供自定义的异常处理逻辑。

2.@ExceptionHandler

用于标记方法,指定该方法处理特定异常类型以及捕获所有异常进行处理。

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(Exception.class)//捕获所有异常
    public Result handleException(Exception ex){
        ex.printStackTrace();
        return Result.error("对不起,操作失败,请联系管理员");
    }
}

@RestControllerAdvice= @RestController + @ControllerAdvice 的功能

1.@RestControllerAdvice 注解标记了 GlobalExceptionHandler 类,表示它是一个全局异常处理器类,并且可以返回响应体。

2.定义了一个异常处理方法 handleException,它使用@ExceptionHandler(Exception.class) 注解标记,表示该方法用于处理 Exception 类型的异常---所有可能的异常。

注!!!:只需要单独new一个包,下面有GlobalExceptionHandler 类定义handleException方法进行异常处理,程序开发中产生异常直接自动识别进行处理。

七.面向切面编程----AOP

这些注解(@Aspect & @Pointcut & @Before @After & @Around & @AfterReturning & @AfterThrowing & @Transactional)的组合可以用于实现面向切面编程(AOP)的功能。通过定义切面类并结合这些注解,可以在特定的连接点上执行增强操作,例如日志记录、事务管理、性能监控等

@Aspect切面,标记一个类为切面类,其中定义了切面的逻辑和通知的行为
@Pointcut切点,用于定义切入点表达式,指定在哪些连接点上应用切面逻辑。
@Before前置通知,指定在目标方法执行之前执行的逻辑。
@After后置通知,指定在目标方法执行之后执行的逻辑,无论方法是否发生异常都会执行。
@AfterReturning返回通知,指定在目标方法正常返回后执行的逻辑。
@AfterThrowing异常通知,指定在目标方法抛出异常后执行的逻辑。
@Around环绕通知,指定包围目标方法的逻辑,在方法执行前后都可以执行自定义的操作。
@Transactional指示 Spring 在方法执行时开启一个事务,并在方法执行结束时根据执行结果进行事务的提交或回滚
1.在anno类中自定义注解@Log
package com.itheima.anno;
​
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Log {
​
}
2.修改业务实现类,在增删改业务方法上添加@Log注解
package com.itheima.controller;
​
import com.itheima.anno.Log;
import com.itheima.pojo.Dept;
import com.itheima.pojo.Emp;
import com.itheima.pojo.Result;
import com.itheima.service.DeptService;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Select;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
​
import java.util.List;
​
/**
 * 部门管理Controller
 */
@Slf4j
@RequestMapping("/depts")
@RestController
public class DeptController {
​
    //private static Logger log = LoggerFactory.getLogger(DeptController.class);
    @Autowired
    private DeptService deptService;
​
    /**
     * 查询部门数据
     * @return
     */
    //@RequestMapping(value = "/depts",method = RequestMethod.GET) //指定请求方式为GET
    @GetMapping
    public Result list(){
        log.info("查询全部部门数据");
        //调用service查询部门数据
        List<Dept> deptList =  deptService.list();
        return Result.success(deptList);
    }
​
​
    /**
     * 删除部门
     * @return
     */
    @Log
    @DeleteMapping("/{id}")
    public Result delete(@PathVariable Integer id) throws Exception {
        log.info("根据id删除部门:{}",id);
        //调用service删除部门
        deptService.delete(id);
        return Result.success();
    }
​
​
    /**
     * 新增部门
     * @return
     */
    @Log
    @PostMapping
    public Result add(@RequestBody Dept dept){
        log.info("新增部门,dept: {}" , dept);
        //调用service新增部门
        deptService.add(dept);
        return Result.success();
    }
​
    /*
     *根据ID查询部门数据
     */
    @GetMapping("/{id}")
    public Result selectID(@PathVariable Integer id){
        log.info("根据ID查询部门数据,id: {}" , id);
        Dept dept= deptService.selectId(id);
        return Result.success(dept);
    }
​
    /*
     *更新部门
     */
    @Log
    @PutMapping
    public Result update(@RequestBody Dept dept){
        log.info("更新部门,dept: {}" , dept);
        deptService.update(dept);
        return Result.success();
    }
}
3.定义切面类,完成记录操作日志的逻辑
package com.itheima.aop;
​
import com.alibaba.fastjson.JSONObject;
import com.itheima.mapper.OperateLogMapper;
import com.itheima.pojo.OperateLog;
import com.itheima.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
​
import java.time.LocalDateTime;
import java.util.Arrays;
​
@Component
@Aspect   //切面类
@Slf4j
public class LogAspect {
​
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private OperateLogMapper operateLogMapper;
​
    @Around("@annotation(com.itheima.anno.Log)")
    public Object recording(ProceedingJoinPoint joinPoint) throws Throwable {
        //获取对象信息
        //操作人ID - 当前登录员工ID
        //获取请求头中的jwt令牌, 解析令牌
        String jwt= request.getHeader("token");
        Claims claims = JwtUtils.parseJWT(jwt);
        Integer operateUser =(Integer) claims.get("id");
​
        //操作时间
        LocalDateTime operateTime = LocalDateTime.now();
​
        //操作类名
        String className = joinPoint.getTarget().getClass().getName();
​
        //操作方法名
        String methodName = joinPoint.getSignature().getName();
​
        //操作方法参数
        Object[] args=joinPoint.getArgs();
        String methodParams = Arrays.toString(args);
​
        //记录开始时间
        Long begin=System.currentTimeMillis();
​
        //调用原始目标方法
        Object result = joinPoint.proceed();
​
        //记录结束时间
        Long end=System.currentTimeMillis();
​
        //方法返回值
        String returnValue = JSONObject.toJSONString(result);
​
​
​
        //操作耗时
        long costTime=end-begin;
​
        //2.记录操作日志
        OperateLog operateLog=new OperateLog(null,operateUser,operateTime,className,methodName,methodParams,returnValue,costTime);
        operateLogMapper.insert(operateLog);
​
        log.info("AOP记录操作日志:{}",operateLog);
​
        return result;
    }
}
4.@EnableAspectJAutoProxy

说明:该注解启用AspectJ注解驱动的自动代理功能,实现AOP的功能

适用场景:在使用AOP开发时需要使用@EnableAspectJAutoProxy启用AspectJ注解驱动的自动代理功能。

八.@Transactional

1.@Transactional

说明:该注解标记一个方法或类需要事务支持,实现了基于注解的声明式事务管理。

适用场景:在开发中需要使用事务进行多个操作的原子性保证,使用@Transactional注解可以简单地实现事务的控制。

​
@Service
public class DeptLogServiceImpl implements DeptLogService {
​
    @Autowired
    private DeptLogMapper deptLogMapper;
​
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Override
    public void insert(DeptLog deptLog) {
​
        deptLogMapper.insert(deptLog);
    }
}
2.@EnableTransactionManagement

说明:该注解启用事务管理功能,实现声明式事务的功能。

适用场景:在开发中需要使用事务进行多个操作的原子性保证,可以使用@EnableTransactionManagement注解启用事务管理功能。

  • 35
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值