天天看點

常用注解粗陋看法

常用注解粗陋看法

    • @Service("userService")
    • @Value注解使用自定義參數
    • @ConfigurationProperties配置參數空間注解
    • @Autowired與@Resource的差別
      • @Autowired
      • @Resource
      • @ComponentScan
        • @Component
    • @Aspect 面向切面程式設計相關
      • @Pointcut
      • @Before
      • @After
      • @AfterReturning
      • @AfterThrowing
      • @Around
    • @[email protected] 內建定時任務
      • @EnableScheduling
    • @Lazy懶加載注解
    • @RequestBody 請求體注解
    • @JsonFormat對象轉json時變量轉換規則
    • @DateTimeFormat json字元串轉對象時變量轉換規則
    • @SpringBootTest
    • @ActiveProfiles("native")

@Service(“userService”)

spring産生一個service層bean示例,就是相當于把

這一步給自動化管理了。你要用的話直接引入就可以了

@Service("userService")
public class UserServiceImpl implements UserService {
    @Resource
    private UserMapper userMapper;
    @Override
    public User getUserById(String id) {
        return userMapper.getUserById(id);
    }
}
           

@Value注解使用自定義參數

springboot application.yml 配置

server:
  port: 80
  servlet:
    context-path:
#自定義參數配置
custom:
  value1: 測試參數1
  map: "{ds: '發送失敗',ds3: '未發送,ds4: 發送成功'}"
  list: "test,test32"
           

自定義參數配置類

// 标明這是一個配置類
@Configuration
// lombok 實體注解
@Data
public class CustomVariableConfig {
    //從 application 配置檔案中擷取 custom.value1 的值 “測試參數1” 注入到 customValue1。
    @Value("${custom.value1:defaultValue}")//設定預設值defaultValue,如果value1沒有值則使用defaultValue
    private String customValue1;
    //${}隻能擷取到字元串,二次加工需要搭配#{}使用
    @Value("#{${custom.map}}")
    private Map<String,String> map;
    @Value("#{'${custom.list}'.split(',')}")
    private List<String> list;
}
           

@ConfigurationProperties配置參數空間注解

java類

@Component
// lombok 實體注解
@Data
//自定義參數空間,會自動掃描 custom 下的所有配置參數(預設支援駝峰轉換)并嘗試注入到該實體類的同名屬性中。
@ConfigurationProperties("custom")
public class CustomVariableConfig {
    /*
    @Value("#{${custom.map}}")
    private Map<String,String> map;
    類使用ConfigurationProperties注解時失效,項目啟動出錯,但是該文法放入controller類下可以直接使用。
     */

    /**
     * 由于 已使用ConfigurationProperties注解,該 Value 注解可以忽略。
     * 而且,在ConfigurationProperties配置類下,Value注解的支援非常不友好,隻支援基礎類型注入,
     * 不建議混用。
     */
    @Value("${custom.customValue1}")
    private String customValue1;

    /**
     * 參數名預設駝峰轉換 simple-view-controllers——>simpleViewControllers
     */
    private List<Map<String,String>> simpleViewControllers;

}
           

yml檔案配置

#自定義參數配置
custom:
  customValue1: 測試參數1
  # value注解 map案例,外面的雙引号可用可不用
  map: "{ds: '發送失敗',ds3: '未發送,ds4: 發送成功'}"
  # value注解 list使用案例,外面的雙引号可用可不用
  list1: "test,test32"
  # ConfigurationProperties注解 搭配使用案例
  #配置簡單請求路徑,需要搭建自己的處理器,該配置方式必須有使用 ConfigurationProperties注解 的參數配置類引入,好像不可以使用 value注解 解析
  simple-view-controllers:
    - urlParame: index
      templatePath: index
    - urlParame: forgetPsd
      templatePath: user/ordinary
    - urlParame: iregister
      templatePath: user/admin
    - urlParame: boss
      templatePath: user/boss
           

@Autowired與@Resource的差別

@Autowired

1、本身無name屬性,如果想通過名稱比對注入則需要配合**@Qualifier**注解一起使用。

@Autowired()
@Qualifier("userService")
UserService userService;
           

2、預設required為true,即叫這個名字的bean執行個體必須要有,不然報錯。可手動設定為false,此時代碼會有警告。媽蛋上傳不了圖檔。就是下面的Qualifier注解屬性會變成大紅色。

@Autowired(required = false)
    @Qualifier("userService")
    UserService userService;
           

3、由spring提供

@Resource

1、name屬性值設定則通過name比對,

@Resource(name = "userService")
    UserService userService;
    //上面這段代碼必須有對應的userService,如果下面的這個實作類沒有指定service名字為userService則會報錯
    @Service("userService")
	public class UserServiceImpl implements UserService {}
           

2、name屬性值未設定則先按照名字後通過類型比對

@Resource()
    UserService userService;
    //下面這裡無論是否指定service名字都不會報錯
    @Service("userService")
	public class UserServiceImpl implements UserService {}
           

3、由jdk1.6開始提供

4、預設可為空

@ComponentScan

設定 spring 掃描包路徑

//單個掃描
@ComponentScan(basePackages = {"com.jdw.springboot.entity"})
//多個掃描
@ComponentScan(basePackages = {"com.jdw.springboot.*","com.jdw.springboot2.*"})
           

用于告訴spring去哪裡擷取bean。spring不會再掃描所有注解的bean,而隻會掃描指定的包下面的。而且這個太深了也不行。

//正常
@ComponentScan(basePackages = {"com.jdw.springboot.*"})
//出錯
@ComponentScan(basePackages = {"com.*"})
           

注意

‘.*’ 不能掃到下面所有,最好還是寫清楚。

//奇葩異常一:Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required
@ComponentScan(basePackages = {"com.*"})
@MapperScan("com.jdw.springboot.mapper")
           
//正常
@ComponentScan(basePackages = {"com.jdw.*"})
@MapperScan("com.jdw.springboot.mapper")
           

@Component

直接寫在類上面,标明這個類要被 spring 管理(相當于舉手,并不一定被管理。)

@Component
public class TimedTask {
    //标明這個方法是個定時任務
    @Scheduled(fixedRate = 2000)
    private void task1() throws Exception{
        System.out.println("2秒執行一遍定時任務");
    }
}
           

@Aspect 面向切面程式設計相關

直接寫在類上面,标明這個類是個切面類,即:

AOP (Aspect Oriented Programming)中的 Aspect

//标明這是一個切面類
@Aspect
//标明這個類由 spring 自動管理
@Component
public class ControllerAspect {
	@Pointcut(value = " execution(public * com.jdw.sys.controller..*.*(..))")
    public void webLog() {
    }
    /**
     * 退出執行,final增強,不管是抛出異常或者正常退出都會執行
     */
    @After("webLog()")
    public void doAfter() {
        log.info("After");
    }
}
           

@Pointcut

//  掃描controller下的所有類
//  @Pointcut(value = "within(com.jdw.sys.controller.*)")
//  掃描使用了 GetMapping 注解的所有類
//  @Pointcut(value = "@annotation(org.springframework.web.bind.annotation.GetMapping)")
//  掃描 com.jdw.sys.controller 下的類及其下面子包内的類 的 通路修飾符為 public 方法(public可以不設定,則掃描所有)
//  修飾方法,聲明一個切面對象,切面名字是方法名 "webLog()" 具體切面是 value 值設定
    @Pointcut(value = " execution(public * com.jdw.sys.controller..*.*(..))")
    public void webLog() {
    }
           

2020.08.01補充:

spring 切面的思想是面向類切面,是以内部方法之間的調用時不會觸發切面的。

失敗案例:

@RestController
@RequestMapping("/demo")
public class DemoController {
    @GetMapping("/test")
    public String test(){
        return test1();
    }
    public String test1(){
        return "fdsdfs";
    }
}

           
@Aspect
//标明這個類由 spring 自動管理
@Component
//引用 lombok 的 log
@Slf4j
public class ControllerAspect {
    //設定切面
//    掃描類
//    @Pointcut(value = "within(com.jdw.sys.controller.*)")
//    掃描注解
//    @Pointcut(value = "@annotation(org.springframework.web.bind.annotation.GetMapping)")
//    掃描 com.jdw.sys.controller 下的類及其下面子包内的類 的 通路修飾符為 public 方法(public可以不設定,則掃描所有)
    @Pointcut(value = " execution(public * com.jdw.sys.controller..*.test1(..))")
    public void webLog() {
    }
           

@Before

//方法執行前執行
    @Before("webLog()")
    public void doBefor(JoinPoint joinPoint) {
        //接受請求,記錄請求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        //列印請求内容
        log.info("URL:" + request.getRequestURI());
        log.info("HTTP_METHOD:" + request.getMethod());
//        log.info("IP:"+request.getRemoteAddr());
//        log.info("HOST:"+request.getRemoteHost());
//        log.info("PORT:"+request.getRemotePort());
        Enumeration<String> parameterNames = request.getParameterNames();
        log.info("請求參數清單為:");
        while (parameterNames.hasMoreElements()) {
            String s = parameterNames.nextElement();
            log.info(s + ":" + request.getParameter(s));
        }
    }
           

@After

/**
     * 退出執行,final增強,不管是抛出異常或者正常退出都會執行
     */
    @After("webLog()")
    public void doAfter() {
        log.info("After");
    }
           

@AfterReturning

/**
     * 方法正常退出時執行,在 @After 後面執行
     */
    @AfterReturning(returning = "object", pointcut = "webLog()")
    public void doAfterReturning(Object object) {
        log.info("RESPONSE:" + object);
    }
           

@AfterThrowing

/**
     * 抛出異常執行,在 @After 後面執行
     */
    @AfterThrowing(value = "webLog()", throwing = "exception")
    public void doAfterThrowing(JoinPoint joinPoint, Exception exception) {
        log.info(joinPoint.getSignature().getName() + "抛出異常:" + exception.getMessage());
    }
           

@Around

2020.08。01補充:

ProceedingJoinPoint(程式連接配接點)類的幾個實用方法,

Object[] getArgs:傳回目标方法的參數

Signature getSignature:傳回目标方法的簽名

Object getTarget:傳回被織入增強處理的目标對象

Object getThis:傳回AOP架構為目标對象生成的代理對象
           
/**
     * 環繞通知:
     * 環繞通知非常強大,可以決定目标方法是否執行,什麼時候執行,執行時是否需要替換方法參數,執行完畢是否需要替換傳回值。
     * 環繞通知第一個參數必須是org.aspectj.lang.ProceedingJoinPoint類型
     * 如過環繞通知決定不執行目标方法,則其他切面注解定義的處理都不會執行.
     */
    @Around("webLog()")
    public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) {
        log.info("- - - - - 環繞通知 - - - -");
        log.info("環繞通知的目标方法名:" + proceedingJoinPoint.getSignature().getName());
        try {//obj之前可以寫目标方法執行前的邏輯
//            log.info("執行目标方法前執行");
            Object obj = proceedingJoinPoint.proceed();//調用執行目标方法
            return obj;//傳回目标方法傳回值
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        } finally {
            log.info("- - - - - 環繞通知 end - - - -");
        }
        return null;
    }
           

@[email protected] 內建定時任務

springboot的定時任務超簡單,兩個注解搞定。

@EnableScheduling

啟動類添加 @EnableScheduling 注解,開啟定時任務。

@SpringBootApplication
//springboot 設定 component 掃描路徑
@ComponentScan(basePackages = {"com.jdw.*.*"})
//springboot 設定 mapper 掃描路徑
@MapperScan("com.jdw.*.mapper")
//springboot 開啟定時任務
@EnableScheduling
public class SpringbootApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootApplication.class, args);
    }
}
           

bean類 方法上添加 @Scheduled 注解,标明這個方法是一個定時任務。

//交給 spring 管理
@Component
public class TimedTask {
    private static int t = 0;
//    标明這個方法是個定時任務,每兩秒建立一個等待上一個完成後執行。
//    上一個執行完畢,新的立即執行。
//    上一個未執行完畢,新的不會執行,如果上一個的執行時間超過了兩秒,則上一個執行完畢後,新的立即執行。
//    @Scheduled(fixedRate = 2000L)

//    标明這個方法是個定時任務,上一個定時任務完成後2秒建立定時任務開始執行。
//    @Scheduled(fixedDelay = 2000L)

//    标明這個方法是個定時任務,每四秒鐘判斷上一個是否已執行,上一個執行完畢則建立定時任務開始執行。未執行完畢則等待4秒後繼續判斷
    @Scheduled(cron = "0/4 * * * * ?")
    private void task1() throws Exception{
        t++;
        System.out.println("task"+t+":定時任務開始"+(new Date()).getTime());
        Thread.sleep(2000);
//        System.out.println("task1:定時任務休眠完成"+(new Date()).getTime());
    }
}

           

@Lazy懶加載注解

@Controller
@RequestMapping("/gcjs/bszn")
public class GcjsBsznController {
    @Autowired
    //當被調用時 spring 執行構造器構造對象。如果沒有該注解,則是當該類執行個體被建立時執行構造器構造對象。
    @Lazy
    private ICCfgTypeService cCfgTypeService;
    }
           

@RequestBody 請求體注解

//使用@RequestBody注解,自動将請求體轉對象時需注意。
//接收對象類型,要麼使用fast.Json接收,要麼使用自定義vo對象或bean對象接收。
//經測試,當我們需要将請求體轉為bean對象時,sf.json、hutool.json、jackson對于枚舉屬性的轉換很不友好。
@PostMapping("test")
@RequestBody
public object test(@RequestBody Object object){
	return object;
}
           

@JsonFormat對象轉json時變量轉換規則

//該案例代表,當将該對象以json傳回給前端時,時間會轉換為"yyyy-MM-dd HH:mm:ss"格式的字元串
   @JsonFormat(timezone = "GMT+8", pattern= "yyyy-MM-dd HH:mm:ss")
   private LocalDateTime updateTime;
           

@DateTimeFormat json字元串轉對象時變量轉換規則

//該案例代表,當直接以對象接收入參時,會将updateTime字元串值以"yyyy-MM-dd HH:mm:ss"格式轉換為LocalDateTime類型
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;
           

@SpringBootTest

@ActiveProfiles(“native”)

/**
 * @Author ListJiang
 * @Since 1.0.1
 * datetime 2021/7/1 13:30
 */
// 聲明這是一個springboot項目測試
@SpringBootTest
// 指定測試運作環境
@ActiveProfiles("native")
public class DemoWebTest {
    @Test
    void contextLoads() {
        String t = "[ tt ts]";
        String substring = t.substring(1, t.length() - 1);
        System.out.println(substring);
    }
}