最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring Boot自定義注解從入門到實戰(zhàn)指南

 更新時間:2025年12月27日 11:55:40   作者:海南java第二人  
本文介紹了SpringBoot中自定義注解的設(shè)計、實現(xiàn)與應(yīng)用技巧,涵蓋了注解基礎(chǔ)、創(chuàng)建自定義注解、注解處理器實現(xiàn)方案、高級注解特性、性能優(yōu)化與最佳實踐、實戰(zhàn)案例、測試策略、常見問題與解決方案以及總結(jié)與最佳實踐,感興趣的朋友跟隨小編一起看看吧

引言:為什么需要自定義注解?

在現(xiàn)代化Spring Boot應(yīng)用開發(fā)中,注解已經(jīng)成為不可或缺的編程元素。自定義注解不僅僅是語法糖,更是實現(xiàn)代碼解耦、增強可讀性、統(tǒng)一業(yè)務(wù)規(guī)范實現(xiàn)AOP編程的利器。通過本文,您將全面掌握Spring Boot自定義注解的設(shè)計、實現(xiàn)與應(yīng)用技巧。

一、注解基礎(chǔ):元注解深度剖析

1.1 什么是元注解?

元注解(Meta-Annotation)是用于定義其他注解的注解。Java提供了5個標(biāo)準元注解,它們是構(gòu)建自定義注解的基石。

1.2 核心元注解詳解

@Target:定義注解使用范圍

@Target(ElementType.METHOD)  // 僅可用于方法
@Target({ElementType.TYPE, ElementType.METHOD})  // 可用于類和方法

常用ElementType值:

  • TYPE:類、接口、枚舉
  • FIELD:字段
  • METHOD:方法
  • PARAMETER:參數(shù)
  • CONSTRUCTOR:構(gòu)造器

@Retention:定義注解生命周期

@Retention(RetentionPolicy.RUNTIME)  // 運行時保留,可通過反射獲取

三種保留策略對比:

策略編譯時類文件運行時典型用途
SOURCE???Lombok注解
CLASS???字節(jié)碼增強
RUNTIME???Spring注解

@Documented:包含在JavaDoc中

@Inherited:允許子類繼承

@Repeatable:可重復(fù)使用

二、創(chuàng)建自定義注解:從簡單到復(fù)雜

2.1 基礎(chǔ)注解創(chuàng)建

/**
 * 簡單日志注解示例
 * 用于標(biāo)記需要記錄日志的方法
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Loggable {
    // 無參數(shù)注解
}

2.2 帶參數(shù)的注解

/**
 * 緩存注解
 * 用于方法結(jié)果緩存
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Cacheable {
    // 必填參數(shù)
    String key();
    // 可選參數(shù)(帶默認值)
    long expire() default 300L;
    // 枚舉類型參數(shù)
    CacheType type() default CacheType.LOCAL;
    // 數(shù)組類型參數(shù)
    String[] excludeParams() default {};
    // 注解支持的數(shù)據(jù)類型:
    // 1. 基本類型(int, long, double, boolean等)
    // 2. String
    // 3. Class
    // 4. Enum
    // 5. Annotation
    // 6. 以上類型的數(shù)組
}

2.3 實戰(zhàn):創(chuàng)建業(yè)務(wù)注解

/**
 * 數(shù)據(jù)權(quán)限注解
 * 用于控制數(shù)據(jù)訪問權(quán)限
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataPermission {
    /**
     * 權(quán)限類型
     */
    DataScope scope() default DataScope.ALL;
    /**
     * 權(quán)限字段(數(shù)據(jù)庫字段名)
     */
    String field() default "create_user_id";
    /**
     * 自定義過濾條件(SpEL表達式)
     */
    String condition() default "";
    /**
     * 數(shù)據(jù)權(quán)限范圍枚舉
     */
    enum DataScope {
        ALL,        // 全部數(shù)據(jù)
        DEPARTMENT, // 本部門數(shù)據(jù)
        SELF,       // 本人數(shù)據(jù)
        CUSTOM      // 自定義
    }
}

三、注解處理器實現(xiàn)方案

3.1 AOP切面處理(最常用)

/**
 * 日志注解切面處理器
 */
@Aspect
@Component
@Slf4j
public class LogAspect {
    /**
     * 環(huán)繞通知:處理@Loggable注解
     */
    @Around("@annotation(com.example.annotation.Loggable)")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        String methodName = joinPoint.getSignature().getName();
        log.info("方法 {} 開始執(zhí)行,參數(shù): {}", methodName, joinPoint.getArgs());
        try {
            Object result = joinPoint.proceed();
            long endTime = System.currentTimeMillis();
            log.info("方法 {} 執(zhí)行成功,耗時: {}ms, 結(jié)果: {}", 
                    methodName, endTime - startTime, result);
            return result;
        } catch (Exception e) {
            log.error("方法 {} 執(zhí)行異常: {}", methodName, e.getMessage());
            throw e;
        }
    }
}

3.2 攔截器處理

/**
 * 權(quán)限注解攔截器
 */
@Component
public class PermissionInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, 
                           HttpServletResponse response, 
                           Object handler) throws Exception {
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        // 檢查方法上的@RequirePermission注解
        RequirePermission annotation = method.getAnnotation(RequirePermission.class);
        if (annotation != null) {
            return checkPermission(annotation.value(), request);
        }
        return true;
    }
}

3.3 BeanPostProcessor處理

/**
 * 字段驗證處理器
 * 使用BeanPostProcessor處理字段級注解
 */
@Component
public class ValidationBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        Class<?> clazz = bean.getClass();
        // 處理字段注解
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            processFieldAnnotations(field, bean);
        }
        // 處理方法注解
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            processMethodAnnotations(method, bean);
        }
        return bean;
    }
}

四、高級注解特性

4.1 組合注解(注解的注解)

/**
 * RESTful GET接口組合注解
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
@ApiOperation(value = "查詢接口")
@Loggable
public @interface RestGet {
    String value() default "";
    boolean requireAuth() default true;
}
// 使用示例
@RestGet("/users/{id}")
public User getUser(@PathVariable Long id) {
    // 方法自動擁有所有組合注解的功能
}

4.2 條件注解

/**
 * 環(huán)境條件注解
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Conditional(OnEnvironmentCondition.class)
public @interface ConditionalOnEnvironment {
    String[] profiles();
    Logical logical() default Logical.OR;
}
/**
 * 條件判斷實現(xiàn)
 */
public class OnEnvironmentCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, 
                          AnnotatedTypeMetadata metadata) {
        // 實現(xiàn)環(huán)境條件判斷邏輯
        return true;
    }
}

4.3 SpEL表達式支持

/**
 * 支持SpEL表達式的注解
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Lockable {
    /**
     * 鎖的key,支持SpEL表達式
     * 示例: #user.id, #args[0], #p0
     */
    String key();
    /**
     * 鎖的過期時間(秒)
     */
    long expire() default 30L;
}
/**
 * SpEL解析器工具類
 */
@Component
public class SpELParser {
    private final ExpressionParser parser = new SpelExpressionParser();
    public String parse(String expression, Method method, Object[] args) {
        StandardEvaluationContext context = new StandardEvaluationContext();
        // 設(shè)置參數(shù)
        String[] paramNames = getParameterNames(method);
        for (int i = 0; i < paramNames.length; i++) {
            context.setVariable(paramNames[i], args[i]);
        }
        // 設(shè)置特殊變量
        context.setVariable("args", args);
        return parser.parseExpression(expression)
                    .getValue(context, String.class);
    }
}

五、性能優(yōu)化與最佳實踐

5.1 反射性能優(yōu)化

/**
 * 注解緩存管理器
 * 避免重復(fù)反射調(diào)用,提升性能
 */
@Component
public class AnnotationCacheManager {
    private final Map<Method, Map<Class<?>, Annotation>> methodCache = 
            new ConcurrentHashMap<>();
    private final Map<Class<?>, Map<Class<?>, Annotation>> classCache = 
            new ConcurrentHashMap<>();
    /**
     * 獲取方法注解(帶緩存)
     */
    @SuppressWarnings("unchecked")
    public <T extends Annotation> T getMethodAnnotation(Method method, 
                                                       Class<T> annotationClass) {
        return (T) methodCache
                .computeIfAbsent(method, k -> new ConcurrentHashMap<>())
                .computeIfAbsent(annotationClass, 
                               k -> method.getAnnotation(annotationClass));
    }
    /**
     * 批量獲取注解信息
     */
    public AnnotationInfo getAnnotationInfo(Method method) {
        return AnnotationInfo.builder()
                .method(method)
                .annotations(Arrays.asList(method.getAnnotations()))
                .build();
    }
}

5.2 線程安全設(shè)計

/**
 * 線程安全的注解處理器
 */
@Component
public class ThreadSafeAnnotationProcessor {
    private final ThreadLocal<AnnotationContext> contextHolder = 
            new ThreadLocal<>();
    public void processWithContext(Runnable task, AnnotationContext context) {
        AnnotationContext oldContext = contextHolder.get();
        contextHolder.set(context);
        try {
            task.run();
        } finally {
            contextHolder.set(oldContext);
        }
    }
    /**
     * 注解上下文
     */
    @Data
    public static class AnnotationContext {
        private String currentUser;
        private Map<String, Object> attributes = new HashMap<>();
    }
}

5.3 錯誤處理與回退

/**
 * 容錯的注解處理器
 */
@Component
public class FaultTolerantAnnotationProcessor {
    @Slf4j
    public Object processWithFallback(ProceedingJoinPoint joinPoint, 
                                     Annotation annotation) {
        try {
            return processAnnotation(joinPoint, annotation);
        } catch (AnnotationProcessingException e) {
            log.warn("注解處理失敗,使用默認處理: {}", e.getMessage());
            return fallbackProcess(joinPoint);
        } catch (Exception e) {
            log.error("注解處理發(fā)生未知異常", e);
            throw e;
        }
    }
    private Object fallbackProcess(ProceedingJoinPoint joinPoint) 
            throws Throwable {
        // 默認處理邏輯
        return joinPoint.proceed();
    }
}

六、實戰(zhàn)案例:完整的權(quán)限控制注解系統(tǒng)

6.1 定義權(quán)限注解

/**
 * 權(quán)限控制注解體系
 */
// 角色要求注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequireRole {
    String[] value();
    Logical logical() default Logical.AND;
}
// 權(quán)限要求注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequirePermission {
    String value();
    String[] actions() default {"read", "write"};
}
// 數(shù)據(jù)權(quán)限注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataAuth {
    String type();
    String field() default "owner_id";
}

6.2 實現(xiàn)權(quán)限注解處理器

/**
 * 權(quán)限注解統(tǒng)一處理器
 */
@Aspect
@Component
@Order(1)  // 高優(yōu)先級
public class SecurityAspect {
    @Autowired
    private PermissionService permissionService;
    @Autowired
    private DataAuthService dataAuthService;
    /**
     * 權(quán)限檢查切入點
     */
    @Pointcut("@annotation(com.example.annotation.RequireRole) || " +
              "@annotation(com.example.annotation.RequirePermission)")
    public void securityPointcut() {}
    /**
     * 數(shù)據(jù)權(quán)限切入點
     */
    @Pointcut("@annotation(com.example.annotation.DataAuth)")
    public void dataAuthPointcut() {}
    /**
     * 權(quán)限前置檢查
     */
    @Before("securityPointcut()")
    public void checkSecurity(JoinPoint joinPoint) {
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        // 檢查角色權(quán)限
        checkRolePermission(method);
        // 檢查操作權(quán)限
        checkOperationPermission(method);
    }
    /**
     * 數(shù)據(jù)權(quán)限環(huán)繞處理
     */
    @Around("dataAuthPointcut()")
    public Object handleDataAuth(ProceedingJoinPoint joinPoint) throws Throwable {
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        DataAuth dataAuth = method.getAnnotation(DataAuth.class);
        // 設(shè)置數(shù)據(jù)權(quán)限上下文
        DataAuthContext context = DataAuthContext.builder()
                .type(dataAuth.type())
                .field(dataAuth.field())
                .build();
        DataAuthHolder.setContext(context);
        try {
            return joinPoint.proceed();
        } finally {
            DataAuthHolder.clear();
        }
    }
}

6.3 使用示例

@RestController
@RequestMapping("/api/users")
public class UserController {
    @GetMapping("/{id}")
    @RequireRole({"ADMIN", "MANAGER"})
    @RequirePermission("user:read")
    @DataAuth(type = "user", field = "id")
    public User getUser(@PathVariable Long id) {
        // 方法會自動受到權(quán)限控制
        return userService.getUserById(id);
    }
    @PostMapping
    @RequireRole("ADMIN")
    @RequirePermission(value = "user:write", actions = {"create"})
    @Loggable
    public User createUser(@RequestBody UserDTO userDTO) {
        // 同時具有日志和權(quán)限控制
        return userService.createUser(userDTO);
    }
}

七、測試策略

7.1 單元測試

@SpringBootTest
public class AnnotationTest {
    @Test
    public void testAnnotationPresence() {
        Method method = UserController.class.getMethod("getUser", Long.class);
        assertTrue(method.isAnnotationPresent(RequireRole.class));
        assertTrue(method.isAnnotationPresent(RequirePermission.class));
        RequireRole roleAnnotation = method.getAnnotation(RequireRole.class);
        assertArrayEquals(new String[]{"ADMIN", "MANAGER"}, roleAnnotation.value());
    }
    @Test
    public void testAnnotationProcessing() {
        // 測試注解處理邏輯
        UserController controller = new UserController();
        // 模擬AOP處理
        SecurityAspect aspect = new SecurityAspect();
        // ... 測試注解處理邏輯
    }
}

7.2 集成測試

@WebMvcTest(UserController.class)
@AutoConfigureMockMvc
public class AnnotationIntegrationTest {
    @Autowired
    private MockMvc mockMvc;
    @MockBean
    private UserService userService;
    @Test
    @WithMockUser(roles = "ADMIN")
    public void testAuthorizedAccess() throws Exception {
        when(userService.getUserById(1L)).thenReturn(new User());
        mockMvc.perform(get("/api/users/1"))
               .andExpect(status().isOk());
    }
    @Test
    @WithMockUser(roles = "USER")  // 權(quán)限不足
    public void testUnauthorizedAccess() throws Exception {
        mockMvc.perform(get("/api/users/1"))
               .andExpect(status().isForbidden());
    }
}

八、常見問題與解決方案

8.1 注解繼承問題

問題:默認情況下,注解不會被繼承

解決方案

// 方案1:使用@Inherited元注解
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface InheritedAnnotation {
    String value();
}
// 方案2:手動檢查繼承鏈
public static <A extends Annotation> A findAnnotationRecursively(
        Class<?> clazz, Class<A> annotationType) {
    // 檢查當(dāng)前類
    A annotation = clazz.getAnnotation(annotationType);
    if (annotation != null) return annotation;
    // 檢查接口
    for (Class<?> ifc : clazz.getInterfaces()) {
        annotation = findAnnotationRecursively(ifc, annotationType);
        if (annotation != null) return annotation;
    }
    // 檢查父類
    Class<?> superClass = clazz.getSuperclass();
    if (superClass != null && superClass != Object.class) {
        return findAnnotationRecursively(superClass, annotationType);
    }
    return null;
}

8.2 注解參數(shù)驗證

/**
 * 帶參數(shù)驗證的注解
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = RangeValidator.class)
public @interface ValidRange {
    String message() default "值超出有效范圍";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
    double min() default 0;
    double max() default Double.MAX_VALUE;
}
/**
 * 驗證器實現(xiàn)
 */
public class RangeValidator implements ConstraintValidator<ValidRange, Number> {
    private double min;
    private double max;
    @Override
    public void initialize(ValidRange constraintAnnotation) {
        this.min = constraintAnnotation.min();
        this.max = constraintAnnotation.max();
    }
    @Override
    public boolean isValid(Number value, ConstraintValidatorContext context) {
        if (value == null) return true;
        double doubleValue = value.doubleValue();
        return doubleValue >= min && doubleValue <= max;
    }
}

九、總結(jié)與最佳實踐

9.1 設(shè)計原則

  1. 單一職責(zé):每個注解應(yīng)只負責(zé)一個明確的功能
  2. 合理命名:注解名稱應(yīng)清晰表達其用途(名詞或形容詞)
  3. 完整文檔:使用JavaDoc詳細說明每個參數(shù)的含義
  4. 向后兼容:已發(fā)布的注解應(yīng)保持兼容性
  5. 適度使用:避免過度使用注解導(dǎo)致代碼難以理解

9.2 性能建議

  1. 緩存反射結(jié)果:避免重復(fù)的反射調(diào)用
  2. 懶加載:延遲初始化昂貴的資源
  3. 使用索引:Spring的類路徑索引加速注解掃描
  4. 異步處理:耗時操作使用異步處理

9.3 擴展建議

  1. 與Spring生態(tài)集成:充分利用Spring的擴展點
  2. 支持SpEL:提供靈活的配置能力
  3. 提供工具類:簡化注解的使用和測試
  4. 監(jiān)控與統(tǒng)計:記錄注解的使用情況

結(jié)語

Spring Boot自定義注解是框架強大擴展能力的體現(xiàn)。通過合理設(shè)計和實現(xiàn)自定義注解,可以顯著提升代碼質(zhì)量、降低維護成本、統(tǒng)一技術(shù)規(guī)范。本文從基礎(chǔ)到高級,從理論到實踐,全面介紹了自定義注解的各個方面,希望能為您的Spring Boot開發(fā)之旅提供有力支持。

記住,注解不是目的,而是手段。始終關(guān)注業(yè)務(wù)價值,合理運用技術(shù)手段,才是優(yōu)秀工程師的追求。

如需獲取更多關(guān)于Spring IoC容器深度解析、Bean生命周期管理、循環(huán)依賴解決方案、條件化配置等內(nèi)容,請持續(xù)關(guān)注本專欄《Spring核心技術(shù)深度剖析》系列文章。

到此這篇關(guān)于Spring Boot自定義注解從入門到實戰(zhàn)指南的文章就介紹到這了,更多相關(guān)Spring Boot自定義注解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java經(jīng)典面試題最全匯總208道(三)

    Java經(jīng)典面試題最全匯總208道(三)

    這篇文章主要介紹了Java經(jīng)典面試題最全匯總208道(三),本文章內(nèi)容詳細,該模塊分為了六個部分,本次為第三部分,需要的朋友可以參考下
    2023-01-01
  • SpringBoot監(jiān)控所有線程池的四種解決方案及代碼案例

    SpringBoot監(jiān)控所有線程池的四種解決方案及代碼案例

    這篇文章介紹了四種監(jiān)控Spring Boot中所有線程池的解決方案,并提供了代碼案例,推薦使用自動發(fā)現(xiàn)機制來監(jiān)控所有線程池,需要的朋友可以參考下
    2025-12-12
  • Java設(shè)計模式之命令模式

    Java設(shè)計模式之命令模式

    這篇文章介紹了Java設(shè)計模式之命令模式,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-10-10
  • Java解析XML文件開源庫DOM4J

    Java解析XML文件開源庫DOM4J

    dom4j是一個Java的XML API,是jdom的升級品,用來讀寫XML文件的。dom4j是一個十分優(yōu)秀的JavaXML API,具有性能優(yōu)異、功能強大和極其易使用的特點,它的性能超過sun公司官方的dom技術(shù),同時它也是一個開放源代碼的軟件
    2023-01-01
  • Java利用反射自動封裝成實體對象的方法

    Java利用反射自動封裝成實體對象的方法

    這篇文章主要介紹了Java利用反射自動封裝成實體對象的方法,可實現(xiàn)自動封裝成bean對象功能,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-01-01
  • Redis 訂閱發(fā)布_Jedis實現(xiàn)方法

    Redis 訂閱發(fā)布_Jedis實現(xiàn)方法

    下面小編就為大家?guī)硪黄猂edis 訂閱發(fā)布_Jedis實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • 使用Idea簡單快速搭建springcloud項目的圖文教程

    使用Idea簡單快速搭建springcloud項目的圖文教程

    這篇文章主要介紹了使用Idea簡單快速搭建springcloud項目,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-01-01
  • Spring boot整合Springfox生成restful的在線api文檔

    Spring boot整合Springfox生成restful的在線api文檔

    這篇文章主要為大家介紹了Spring boot整合Springfox生成restful在線api文檔,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2022-03-03
  • Java 1.8使用數(shù)組實現(xiàn)循環(huán)隊列

    Java 1.8使用數(shù)組實現(xiàn)循環(huán)隊列

    這篇文章主要為大家詳細介紹了Java 1.8使用數(shù)組實現(xiàn)循環(huán)隊列,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-10-10
  • 總結(jié)一下Java回調(diào)機制的相關(guān)知識

    總結(jié)一下Java回調(diào)機制的相關(guān)知識

    今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識,文章圍繞著Java回調(diào)機制展開,文中有非常詳細的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06

最新評論

东乌| 探索| 张北县| 北辰区| 金山区| 金寨县| 昭平县| 元阳县| 潼南县| 东山县| 依兰县| 瓦房店市| 长垣县| 博兴县| 繁峙县| 张掖市| 凌海市| 会宁县| 兴宁市| 昔阳县| 剑阁县| 葫芦岛市| 玛纳斯县| 蓬安县| 无锡市| 德钦县| 洪泽县| 喜德县| 土默特右旗| 苗栗市| 永修县| 吉隆县| 资兴市| 蚌埠市| 岳池县| 棋牌| 长汀县| 兴宁市| 富平县| 任丘市| 磐石市|