常用注解
常見的注解解析方法有兩種:
- 編譯期直接掃描:編譯器在編譯 Java 代碼的時候掃描對應的注解并處理,比如某個方法使用@Override 注解,編譯器在編譯的時候就會檢測當前的方法是否重寫了父類對應的方法。
- 運行期通過反射處理:像框架中自帶的注解(比如 Spring 框架的 @Value、@Component)都是通過反射來進行處理的
這個博客對常用注解講的很詳細且有例子 SpringBoot常用的50個注解
以下是根據蒼穹外賣來整理的注解和使用實例。
1.@ResponseBody
的作用其實是將java對象轉為json格式的數據,然后直接寫入HTTP response 的body中;
@RequestMapping后,返回值通常解析為跳轉路徑,但是加上 @ResponseBody 后返回結果不會被解析為跳轉路徑,而是直接寫入 HTTP response body 中。
2.@RestController
=@ReponseBody
+@Controller
在類上用@RestController,其內的所有方法都會默認加上@ResponseBody,也就是默認返回JSON格式。將控制器方法的返回值轉換為JSON格式,并以HTTP響應的方式返回給客戶端。
@RestController和@Controller
的共同點是都用來表示Spring某個類是否可以接收HTTP請求,二者區別: @RestController無法返回指定頁面,而@Controller可以;前者可以直接返回數據,后者需要@ResponseBody輔助。
在@RestController
中指定Bean的名稱。
@RestController("adminShopController")//為了避免兩個Bean都叫shopController的沖突,所以用為了區分他倆
@RequestMapping("/admin/shop")
@Slf4j
@Api(tags = "店鋪相關接口")
public class ShopController {
}
@RestController("UserShopController")
@RequestMapping("/user/shop")
@Api(tags = "店鋪相關接口")
@Slf4j
public class ShopController {
}
3.@RequestBody
是作用在形參列表上,用于將前臺發送過來固定格式的數據【xml格式 或者 json等】封裝為對應的 JavaBean 對象,封裝時使用到的一個對象是系統默認配置的 HttpMessageConverter進行解析,然后封裝到形參上。
就是將JSON格式的數據封裝到實體類中
4.@Transactional
是Spring框架中用于聲明式事務管理的關鍵注解。通過使用@Transactional注解,我們可以更加方便地管理事務,保障數據的一致性和可靠性。用于聲明式事務管理**,保證方法或類中的操作在同一個事務中執行**。
5.@RequestMapping
映射請求URL和處理方法。跳轉路徑
6.@GetMapping
用于映射HTTP GET請求。
7.@PostMapping
用于映射HTTP POST請求。
8. @RequestParam
用于獲取請求參數的值。
@DeleteMapping
@ApiOperation("菜品批量刪除")
public Result delete(@RequestParam List<Long> ids){//注解@RequestParam,可以將地址欄中多個數字參數提取出來然后變成List集合。 log.info("菜品批量刪除:{}",ids);dishService.deleteBatch(ids);return Result.success();
}
9. @ConfigurationProperties
注解代表當前類是一個配置屬性類,作用是:封裝配置文件中的一些配置項。
原理就是:通過配置屬性類,將配置文件中的配置項,封裝成一個類,然后通過@Autowired注解注入到要使用的地方。
10.取的是路徑參數,加注解@PathVariable
,如果和路徑參數不同名,就要加括號雙引號指明取的是哪個路徑參數@PathVariable("status")
;如果同名,就不用加。
@PostMapping("/status/{status}")@ApiOperation("啟用禁用員工賬號")public Result startOrStop(@PathVariable Integer status,Long id){log.info("啟用禁用員工賬號:{},{}",status,id);employeeService.startOrStop(status,id);return Result.success();
}
- AOP相關注解
切入點:@Pointcut
里面寫的是對哪些方法進行攔截,要滿足2點:
①必須是mapper下的所有類的方法,
②還要有AutoFill這個注解。
在對切面的定義中共使用@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
這里指定使用的包范圍和在有注解標注的方法上。
mapper中使用的示例:
@AutoFill(OperationType.UPDATE)
void update(Employee employee);
(1)創建自定義注解
annotation.AutoFill.java 注解類
@Target(ElementType.METHOD)/
/指定注解只能加載方法上,@Retention(RetentionPolicy.RUNTIME)
運行時
Target注解指定加上什么上面,Retention注解指定什么時候用,
@Target(ElementType.METHOD)//指定注解只能加載方法上
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {//通過枚舉-指定當前屬性OperationType//數據庫操作類型OperationType:就兩種 Update 和 InsertOperationType value();
}
(2)切面類 aspect.AutoFillAspect.java 自動填充的切片類
@Aspect
@Component
@Slf4j
public class AutoFillAspect {//這個包里的類和方法和加上@AutoFill注解的@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")public void autoFillPointCut() {}//前置通知,在sql執行前加上即(公共字段賦值)@Before("autoFillPointCut()")//當匹配上切點表達式的執行這個public void autoFill(JoinPoint joinPoint) {//插入鏈接點的參數值//1.獲取到當前被欄截的方法上的數據庫操作類型//2.獲取到當前被攔截的方法的參數--實體對象//3.準備賦值的數據//4.根據當前不同的操作類型,為對應的屬性通過反射來賦值}
}
12.Swagger使用注解
@Api(tags = “員工相關接口”)
@RestController
@RequestMapping("/admin/employee")
@Slf4j
@Api(tags = "員工相關接口")//tags用來描述類的作用
public class EmployeeController {
@ApiOperation(“員工登錄”)
@PostMapping("/login")@ApiOperation("員工登錄")public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO employeeLoginDTO) {
@ApiModel(description = “員工登錄時傳遞的數據模型”)
@ApiModelProperty(“用戶名”)
@Data
@ApiModel(description = "員工登錄時傳遞的數據模型")
public class EmployeeLoginDTO implements Serializable {@ApiModelProperty("用戶名")private String username;@ApiModelProperty("密碼")private String password;}
13.@Bean
//項目啟動時就會調用方法創建對象
@ConditionalOnMissingBean/
/保證Spring容器里只有一個Util對象,條件對象當沒Bean時再創建
注意要return的是這個新創建的對象,不然后面自動注入會失敗,這里的主要目的就是創建Bean對象
@Bean //項目啟動時就會調用方法創建對象@ConditionalOnMissingBean//保證Spring容器里只有一個Util對象,條件對象當沒Bean時再創建public AliOssUtil aliOssUtil(AliOssProperties aliOssProperties) {return new AliOssUtil(aliOssProperties.getEndpoint(),aliOssProperties.getAccessKeyId(),aliOssProperties.getAccessKeySecret(),aliOssProperties.getBucketName());}
因為涉及到多個表,所以添加@Transactional
的注解
(需要在啟動類上添加@EnableTransactionManagement
注解):開啟注解方式的事務管理
@Transactional//涉及幾多個數據表,需要保證數據一致性,需要事務注解--保證原子性,全成功或全失敗
@Override
public void saveWithFlavor(DishDTO dishDTO) {
//開始新增菜品
}
15.Spring Cache框架,實現了基于注解的緩存功能。
都是在Controller層:
(1)@CachePut
這個注釋將方法的返回結果,user對象保存到Redis中,同時生成動態的key,userCache::user.id
@CachePut(cacheNames="userCache",key="abs")//Spring Cache緩存數據,key的生成:userCache:abc
@CachePut(cacheNames="userCache",key="#user.id")//與形參保持一致,或者
@CachePut(cacheNames="userCache",key="#result.id")//返回值result,或者
@CachePut(cacheNames="userCache",key="#p0.id")//獲得當前方法的第一個參數user,或者
@CachePut(cacheNames="userCache",key="#a0.id")//獲得當前方法的第一個參數user,或者
@CachePut(cacheNames="userCache",key="#root.args[0].id")//獲得當前方法的第一個參數user
public User save(@RequestBody User user){userMapper.insert(user);return result;
}
插入完數據后,數據庫生成的主鍵值會自動賦給user對象
Redis可以形成樹形結構
(2)@Cacheable
注解
@Cacheable(cahceNames="userCache"),key="#id")//key的生成,userCache::10
public User getById(Long id){User user = userMapper.getById(id);return user;
}
(3)@CacheEvict
一次清理一條數據
@CacheEvict(cahceNames="userCache"),key="#id")//key的生成,userCache::10
public void deleteById(Long id){userMapper.deleteById(id);
}
清除所有數據
@CacheEvict(cahceNames="userCache"),allEntries=true)//userCache下的所有鍵值對
public void deleteAlld(){userMapper.deleteAll();
}
動態sql
insert 返回生成的主鍵值
<insert id="insert" useGeneratedKeys="true" keyProperty="id"><!-- 產生的主鍵值會賦給id屬性-->insert into dish (name, category_id, price, image, description, create_time, update_time, create_user, update_user, status)values (#{name}, #{categoryId}, #{price}, #{image}, #{description}, #{createTime}, #{updateTime}, #{createUser}, #{updateUser}, #{status})</insert>
mapper:
不用注解,動態sql使用映射文件
在resource文件夾里都是xml文件
select
<select>
標簽的id是mapper中的對應方法名,resultType是返回的參數類型。
<select id="selectByPage" resultType="com.sky.entity.Employee">select * from employee<where><if test="name!=null and name !='' ">and name like concat('%',#{name},'%') <!--模糊查詢 like --></if></where>order by create_time desc <!--創建時間降序-->
</select>
稍復雜一點的select
動態sql
sql語句:左外鏈接:將左邊的表的所有項與右邊的表作連接
將菜和種類兩個表按照種類id鏈接起來,以此獲得種類名稱
select d.*,c.name as categoryName from dish d left outer join category c on d.category_id=c.id
由于種類名稱查出來也叫name,所以給字段起別名
<select id="pageQuery" resultType="com.sky.vo.DishVO">select d.*,c.name categoryName from dish d left join category c on d.category_id = c.id<where><!--畢竟動態sql。給它用where動態拼上DTO的3個屬性 --><if test="categoryId! =null">d.category_id=#{categoryId}</if><if test="status!=null">d.status=#{status}</if><if test="name!=null">d.name like concat('%',#{name},'%')</if></where>order by d.create_time desc<!--根據創建時間降序 --></select>
delete
(1)sql
按照菜id查全部信息,以此得到是否在售賣
@Select("select * from dish where id=#{id}")Dish getById(Long id);
(2)sql
是否有套餐關聯
// select setmeal id from setmeal dish where dish_id in (1,2,3,4)
List queryUnsale(List ids);傳入菜品List列表,用動態sql查每個菜品是否有套餐
SetMealDishMapper.xml
<select id="getSetmealIdsByDishIds" resultType="java.lang.Long">select setmeal_id from setmeal_dish where dish_id in<foreach collection="dishIds" separator="," item="id" open="(" close=")">#{id}</foreach></select>
foreach循環,collection是集合,item是一個個項,separator是分割符號,open是開始符號,close是結束符號。每個元素用逗號分割,然后用大括號括起來。
(3)刪除菜—傳入為列表
<delete id="deleteBatch">delete from dish where id in<foreach collection="ids" item="id" separator="," open="(" close=")">#{id}</foreach></delete>
(4)刪除口味—傳入為列表
<delete id="deleteBatchByDishIds">delete from dish_flavor where dish_id in<foreach collection="ids" item="id" open="(" close=")" separator=",">#{id}</foreach></delete>
update
<update id="update">update dish<set><if test="name!=null">name=#{name},</if><if test="categoryId!=null">category_id=#{categoryId},</if><if test="price!=null">price=#{price},</if><if test="image!=null">image=#{image},</if><if test="description!=null">description=#{description},</if><if test="status!=null">status=#{status},</if><if test="updateTime!=null">update_time=#{updateTime},</if><if test="updateUser!=null">update_user=#{updateUser},</if></set>where id=#{id}</update>