mirror of
				https://github.com/continew-org/continew-starter.git
				synced 2025-10-30 23:00:11 +08:00 
			
		
		
		
	refactor(extension/crud): 重构 BaseController 内权限校验
1.移除 SaToken 依赖 2.移除 checkPermission 方法 3.新增 CrudApi 注解
This commit is contained in:
		| @@ -30,18 +30,6 @@ | ||||
|             <artifactId>continew-starter-web</artifactId> | ||||
|         </dependency> | ||||
|  | ||||
|         <!-- 认证模块 - SaToken --> | ||||
|         <dependency> | ||||
|             <groupId>top.continew</groupId> | ||||
|             <artifactId>continew-starter-auth-satoken</artifactId> | ||||
|             <exclusions> | ||||
|                 <exclusion> | ||||
|                     <groupId>org.springframework.boot</groupId> | ||||
|                     <artifactId>spring-boot-starter-web</artifactId> | ||||
|                 </exclusion> | ||||
|             </exclusions> | ||||
|         </dependency> | ||||
|  | ||||
|         <!-- 数据访问模块 - 核心模块 --> | ||||
|         <dependency> | ||||
|             <groupId>top.continew</groupId> | ||||
|   | ||||
| @@ -0,0 +1,38 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. | ||||
|  * <p> | ||||
|  * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * <p> | ||||
|  * http://www.gnu.org/licenses/lgpl.html | ||||
|  * <p> | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
|  | ||||
| package top.continew.starter.extension.crud.annotation; | ||||
|  | ||||
| import top.continew.starter.extension.crud.enums.Api; | ||||
|  | ||||
| import java.lang.annotation.*; | ||||
|  | ||||
| /** | ||||
|  * CRUD(增删改查)API | ||||
|  * | ||||
|  * @author Charles7c | ||||
|  * @since 2.7.5 | ||||
|  */ | ||||
| @Target(ElementType.METHOD) | ||||
| @Retention(RetentionPolicy.RUNTIME) | ||||
| @Documented | ||||
| public @interface CrudApi { | ||||
|  | ||||
|     /** | ||||
|      * API 类型 | ||||
|      */ | ||||
|     Api value() default Api.LIST; | ||||
| } | ||||
| @@ -17,6 +17,7 @@ | ||||
| package top.continew.starter.extension.crud.annotation; | ||||
|  | ||||
| import org.springframework.context.annotation.Import; | ||||
| import top.continew.starter.extension.crud.autoconfigure.CrudRequestMappingAutoConfiguration; | ||||
| import top.continew.starter.extension.crud.autoconfigure.CrudRestControllerAutoConfiguration; | ||||
|  | ||||
| import java.lang.annotation.*; | ||||
| @@ -30,5 +31,5 @@ import java.lang.annotation.*; | ||||
| @Target({ElementType.TYPE}) | ||||
| @Retention(RetentionPolicy.RUNTIME) | ||||
| @Documented | ||||
| @Import({CrudRestControllerAutoConfiguration.class}) | ||||
| @Import({CrudRequestMappingAutoConfiguration.class, CrudRestControllerAutoConfiguration.class}) | ||||
| public @interface EnableCrudRestController {} | ||||
|   | ||||
| @@ -0,0 +1,62 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. | ||||
|  * <p> | ||||
|  * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * <p> | ||||
|  * http://www.gnu.org/licenses/lgpl.html | ||||
|  * <p> | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
|  | ||||
| package top.continew.starter.extension.crud.aop; | ||||
|  | ||||
| import org.aopalliance.aop.Advice; | ||||
| import org.springframework.aop.Pointcut; | ||||
| import org.springframework.aop.support.AbstractPointcutAdvisor; | ||||
| import org.springframework.aop.support.ComposablePointcut; | ||||
| import org.springframework.aop.support.annotation.AnnotationMatchingPointcut; | ||||
| import org.springframework.beans.BeansException; | ||||
| import org.springframework.beans.factory.BeanFactory; | ||||
| import org.springframework.beans.factory.BeanFactoryAware; | ||||
|  | ||||
| import java.lang.annotation.Annotation; | ||||
|  | ||||
| /** | ||||
|  * CRUD API 注解通知 | ||||
|  * | ||||
|  * @author Charles7c | ||||
|  * @since 2.7.5 | ||||
|  */ | ||||
| public class CrudApiAnnotationAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware { | ||||
|  | ||||
|     private final Advice advice; | ||||
|     private final Pointcut pointcut; | ||||
|  | ||||
|     public CrudApiAnnotationAdvisor(CrudApiAnnotationInterceptor advice, Class<? extends Annotation> annotation) { | ||||
|         this.advice = advice; | ||||
|         this.pointcut = new ComposablePointcut(AnnotationMatchingPointcut.forMethodAnnotation(annotation)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Pointcut getPointcut() { | ||||
|         return this.pointcut; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Advice getAdvice() { | ||||
|         return this.advice; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void setBeanFactory(BeanFactory beanFactory) throws BeansException { | ||||
|         if (this.advice instanceof BeanFactoryAware beanFactoryAware) { | ||||
|             beanFactoryAware.setBeanFactory(beanFactory); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,57 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. | ||||
|  * <p> | ||||
|  * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * <p> | ||||
|  * http://www.gnu.org/licenses/lgpl.html | ||||
|  * <p> | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
|  | ||||
| package top.continew.starter.extension.crud.aop; | ||||
|  | ||||
| import org.aopalliance.intercept.MethodInterceptor; | ||||
| import org.aopalliance.intercept.MethodInvocation; | ||||
| import org.springframework.aop.support.AopUtils; | ||||
| import org.springframework.core.BridgeMethodResolver; | ||||
| import org.springframework.core.annotation.AnnotatedElementUtils; | ||||
| import org.springframework.util.ClassUtils; | ||||
| import top.continew.starter.extension.crud.annotation.CrudApi; | ||||
| import top.continew.starter.extension.crud.handler.CrudApiHandler; | ||||
|  | ||||
| import java.lang.reflect.Method; | ||||
| import java.util.Objects; | ||||
|  | ||||
| /** | ||||
|  * CRUD API 注解拦截器 | ||||
|  * | ||||
|  * @author Charles7c | ||||
|  * @since 2.7.5 | ||||
|  */ | ||||
| public class CrudApiAnnotationInterceptor implements MethodInterceptor { | ||||
|  | ||||
|     private final CrudApiHandler handler; | ||||
|  | ||||
|     public CrudApiAnnotationInterceptor(CrudApiHandler handler) { | ||||
|         this.handler = handler; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Object invoke(MethodInvocation invocation) throws Throwable { | ||||
|         // 获取目标类 | ||||
|         Class<?> targetClass = AopUtils.getTargetClass(Objects.requireNonNull(invocation.getThis())); | ||||
|         // 获取目标方法 | ||||
|         Method specificMethod = ClassUtils.getMostSpecificMethod(invocation.getMethod(), targetClass); | ||||
|         Method targetMethod = BridgeMethodResolver.findBridgedMethod(specificMethod); | ||||
|         // 获取 @CrudApi 注解 | ||||
|         CrudApi crudApi = AnnotatedElementUtils.findMergedAnnotation(targetMethod, CrudApi.class); | ||||
|         handler.preHandle(crudApi, targetMethod, targetClass); | ||||
|         return invocation.proceed(); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,56 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. | ||||
|  * <p> | ||||
|  * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * <p> | ||||
|  * http://www.gnu.org/licenses/lgpl.html | ||||
|  * <p> | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
|  | ||||
| package top.continew.starter.extension.crud.autoconfigure; | ||||
|  | ||||
| import org.springframework.beans.factory.annotation.Qualifier; | ||||
| import org.springframework.boot.context.properties.EnableConfigurationProperties; | ||||
| import org.springframework.context.annotation.Bean; | ||||
| import org.springframework.context.annotation.Configuration; | ||||
| import org.springframework.context.annotation.Primary; | ||||
| import org.springframework.format.support.FormattingConversionService; | ||||
| import org.springframework.web.accept.ContentNegotiationManager; | ||||
| import org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration; | ||||
| import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; | ||||
| import org.springframework.web.servlet.resource.ResourceUrlProvider; | ||||
|  | ||||
| /** | ||||
|  * CRUD Request Mapping 自动配置 | ||||
|  * | ||||
|  * @author Charles7c | ||||
|  * @since 1.0.0 | ||||
|  */ | ||||
| @Configuration | ||||
| @EnableConfigurationProperties(CrudProperties.class) | ||||
| public class CrudRequestMappingAutoConfiguration extends DelegatingWebMvcConfiguration { | ||||
|  | ||||
|     /** | ||||
|      * CRUD 请求映射器处理器映射器(覆盖默认 RequestMappingHandlerMapping) | ||||
|      */ | ||||
|     @Override | ||||
|     public RequestMappingHandlerMapping createRequestMappingHandlerMapping() { | ||||
|         return new CrudRequestMappingHandlerMapping(); | ||||
|     } | ||||
|  | ||||
|     @Bean | ||||
|     @Primary | ||||
|     @Override | ||||
|     public RequestMappingHandlerMapping requestMappingHandlerMapping(@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager, | ||||
|                                                                      @Qualifier("mvcConversionService") FormattingConversionService conversionService, | ||||
|                                                                      @Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) { | ||||
|         return super.requestMappingHandlerMapping(contentNegotiationManager, conversionService, resourceUrlProvider); | ||||
|     } | ||||
| } | ||||
| @@ -19,44 +19,53 @@ package top.continew.starter.extension.crud.autoconfigure; | ||||
| import jakarta.annotation.PostConstruct; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| import org.springframework.beans.factory.annotation.Qualifier; | ||||
| import org.springframework.boot.autoconfigure.AutoConfiguration; | ||||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | ||||
| import org.springframework.boot.context.properties.EnableConfigurationProperties; | ||||
| import org.springframework.context.annotation.Bean; | ||||
| import org.springframework.context.annotation.Configuration; | ||||
| import org.springframework.context.annotation.Primary; | ||||
| import org.springframework.format.support.FormattingConversionService; | ||||
| import org.springframework.web.accept.ContentNegotiationManager; | ||||
| import org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration; | ||||
| import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; | ||||
| import org.springframework.web.servlet.resource.ResourceUrlProvider; | ||||
| import top.continew.starter.extension.crud.annotation.CrudApi; | ||||
| import top.continew.starter.extension.crud.aop.CrudApiAnnotationAdvisor; | ||||
| import top.continew.starter.extension.crud.aop.CrudApiAnnotationInterceptor; | ||||
| import top.continew.starter.extension.crud.handler.CrudApiHandler; | ||||
| import top.continew.starter.extension.crud.handler.DefaultCrudApiHandler; | ||||
|  | ||||
| /** | ||||
|  * CRUD REST Controller 自动配置 | ||||
|  * | ||||
|  * @author Charles7c | ||||
|  * @since 1.0.0 | ||||
|  * @since 2.7.5 | ||||
|  */ | ||||
| @Configuration | ||||
| @AutoConfiguration | ||||
| @EnableConfigurationProperties(CrudProperties.class) | ||||
| public class CrudRestControllerAutoConfiguration extends DelegatingWebMvcConfiguration { | ||||
| public class CrudRestControllerAutoConfiguration { | ||||
|  | ||||
|     private static final Logger log = LoggerFactory.getLogger(CrudRestControllerAutoConfiguration.class); | ||||
|  | ||||
|     /** | ||||
|      * CRUD 请求映射器处理器映射器(覆盖默认 RequestMappingHandlerMapping) | ||||
|      * CRUD API 注解通知 | ||||
|      */ | ||||
|     @Override | ||||
|     public RequestMappingHandlerMapping createRequestMappingHandlerMapping() { | ||||
|         return new CrudRequestMappingHandlerMapping(); | ||||
|     @Bean | ||||
|     @ConditionalOnMissingBean | ||||
|     public CrudApiAnnotationAdvisor crudApiAnnotationAdvisor(CrudApiAnnotationInterceptor crudApiAnnotationInterceptor) { | ||||
|         return new CrudApiAnnotationAdvisor(crudApiAnnotationInterceptor, CrudApi.class); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * CRUD API 注解拦截器 | ||||
|      */ | ||||
|     @Bean | ||||
|     @Primary | ||||
|     @Override | ||||
|     public RequestMappingHandlerMapping requestMappingHandlerMapping(@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager, | ||||
|                                                                      @Qualifier("mvcConversionService") FormattingConversionService conversionService, | ||||
|                                                                      @Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) { | ||||
|         return super.requestMappingHandlerMapping(contentNegotiationManager, conversionService, resourceUrlProvider); | ||||
|     @ConditionalOnMissingBean | ||||
|     public CrudApiAnnotationInterceptor crudApiAnnotationInterceptor(CrudApiHandler crudApiHandler) { | ||||
|         return new CrudApiAnnotationInterceptor(crudApiHandler); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * CRUD API 处理器(默认) | ||||
|      */ | ||||
|     @Bean | ||||
|     @ConditionalOnMissingBean | ||||
|     public CrudApiHandler crudApiHandler() { | ||||
|         return new DefaultCrudApiHandler(); | ||||
|     } | ||||
|  | ||||
|     @PostConstruct | ||||
|   | ||||
| @@ -0,0 +1,40 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. | ||||
|  * <p> | ||||
|  * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * <p> | ||||
|  * http://www.gnu.org/licenses/lgpl.html | ||||
|  * <p> | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
|  | ||||
| package top.continew.starter.extension.crud.handler; | ||||
|  | ||||
| import top.continew.starter.extension.crud.annotation.CrudApi; | ||||
|  | ||||
| import java.lang.reflect.Method; | ||||
|  | ||||
| /** | ||||
|  * CRUD API 处理器 | ||||
|  * | ||||
|  * @author Charles7c | ||||
|  * @since 2.7.5 | ||||
|  */ | ||||
| public interface CrudApiHandler { | ||||
|  | ||||
|     /** | ||||
|      * 前置处理 | ||||
|      * | ||||
|      * @param crudApi      CRUD API 注解 | ||||
|      * @param targetMethod 目标方法 | ||||
|      * @param targetClass  目标类 | ||||
|      * @throws Exception 处理异常 | ||||
|      */ | ||||
|     void preHandle(CrudApi crudApi, Method targetMethod, Class<?> targetClass) throws Exception; | ||||
| } | ||||
| @@ -0,0 +1,35 @@ | ||||
| /* | ||||
|  * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. | ||||
|  * <p> | ||||
|  * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * <p> | ||||
|  * http://www.gnu.org/licenses/lgpl.html | ||||
|  * <p> | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
|  | ||||
| package top.continew.starter.extension.crud.handler; | ||||
|  | ||||
| import top.continew.starter.extension.crud.annotation.CrudApi; | ||||
|  | ||||
| import java.lang.reflect.Method; | ||||
|  | ||||
| /** | ||||
|  * CRUD API 处理器(默认) | ||||
|  * | ||||
|  * @author Charles7c | ||||
|  * @since 2.7.5 | ||||
|  */ | ||||
| public class DefaultCrudApiHandler implements CrudApiHandler { | ||||
|  | ||||
|     @Override | ||||
|     public void preHandle(CrudApi crudApi, Method targetMethod, Class<?> targetClass) { | ||||
|         // do nothing | ||||
|     } | ||||
| } | ||||
| @@ -16,9 +16,7 @@ | ||||
|  | ||||
| package top.continew.starter.extension.crud.controller; | ||||
|  | ||||
| import cn.dev33.satoken.stp.StpUtil; | ||||
| import cn.hutool.core.lang.tree.Tree; | ||||
| import cn.hutool.core.text.CharSequenceUtil; | ||||
| import com.feiniaojin.gracefulresponse.api.ExcludeFromGracefulResponse; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.Parameter; | ||||
| @@ -27,8 +25,7 @@ import jakarta.servlet.http.HttpServletResponse; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.validation.annotation.Validated; | ||||
| import org.springframework.web.bind.annotation.*; | ||||
| import top.continew.starter.core.constant.StringConstants; | ||||
| import top.continew.starter.extension.crud.annotation.CrudRequestMapping; | ||||
| import top.continew.starter.extension.crud.annotation.CrudApi; | ||||
| import top.continew.starter.extension.crud.enums.Api; | ||||
| import top.continew.starter.extension.crud.model.query.PageQuery; | ||||
| import top.continew.starter.extension.crud.model.query.SortQuery; | ||||
| @@ -63,11 +60,11 @@ public abstract class BaseController<S extends BaseService<L, D, Q, C>, L, D, Q, | ||||
|      * @param pageQuery 分页查询条件 | ||||
|      * @return 分页信息 | ||||
|      */ | ||||
|     @CrudApi(Api.PAGE) | ||||
|     @Operation(summary = "分页查询列表", description = "分页查询列表") | ||||
|     @ResponseBody | ||||
|     @GetMapping | ||||
|     public PageResp<L> page(Q query, @Validated PageQuery pageQuery) { | ||||
|         this.checkPermission(Api.LIST); | ||||
|         return baseService.page(query, pageQuery); | ||||
|     } | ||||
|  | ||||
| @@ -78,11 +75,11 @@ public abstract class BaseController<S extends BaseService<L, D, Q, C>, L, D, Q, | ||||
|      * @param sortQuery 排序查询条件 | ||||
|      * @return 列表信息 | ||||
|      */ | ||||
|     @CrudApi(Api.LIST) | ||||
|     @Operation(summary = "查询列表", description = "查询列表") | ||||
|     @ResponseBody | ||||
|     @GetMapping("/list") | ||||
|     public List<L> list(Q query, SortQuery sortQuery) { | ||||
|         this.checkPermission(Api.LIST); | ||||
|         return baseService.list(query, sortQuery); | ||||
|     } | ||||
|  | ||||
| @@ -93,11 +90,11 @@ public abstract class BaseController<S extends BaseService<L, D, Q, C>, L, D, Q, | ||||
|      * @param sortQuery 排序查询条件 | ||||
|      * @return 树列表信息 | ||||
|      */ | ||||
|     @CrudApi(Api.TREE) | ||||
|     @Operation(summary = "查询树列表", description = "查询树列表") | ||||
|     @ResponseBody | ||||
|     @GetMapping("/tree") | ||||
|     public List<Tree<Long>> tree(Q query, SortQuery sortQuery) { | ||||
|         this.checkPermission(Api.LIST); | ||||
|         return baseService.tree(query, sortQuery, false); | ||||
|     } | ||||
|  | ||||
| @@ -107,41 +104,41 @@ public abstract class BaseController<S extends BaseService<L, D, Q, C>, L, D, Q, | ||||
|      * @param id ID | ||||
|      * @return 详情信息 | ||||
|      */ | ||||
|     @CrudApi(Api.DETAIL) | ||||
|     @Operation(summary = "查询详情", description = "查询详情") | ||||
|     @Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH) | ||||
|     @ResponseBody | ||||
|     @GetMapping("/{id}") | ||||
|     public D detail(@PathVariable("id") Long id) { | ||||
|         this.checkPermission(Api.DETAIL); | ||||
|         return baseService.get(id); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 新增 | ||||
|      * | ||||
|      * @param req 创建信息 | ||||
|      * @return 自增 ID | ||||
|      * @param req 创建参数 | ||||
|      * @return ID | ||||
|      */ | ||||
|     @CrudApi(Api.ADD) | ||||
|     @Operation(summary = "新增数据", description = "新增数据") | ||||
|     @ResponseBody | ||||
|     @PostMapping | ||||
|     public BaseIdResp<Long> add(@Validated(ValidateGroup.Crud.Add.class) @RequestBody C req) { | ||||
|         this.checkPermission(Api.ADD); | ||||
|         return new BaseIdResp<>(baseService.add(req)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 修改 | ||||
|      * | ||||
|      * @param req 修改信息 | ||||
|      * @param req 修改参数 | ||||
|      * @param id  ID | ||||
|      */ | ||||
|     @CrudApi(Api.UPDATE) | ||||
|     @Operation(summary = "修改数据", description = "修改数据") | ||||
|     @Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH) | ||||
|     @ResponseBody | ||||
|     @PutMapping("/{id}") | ||||
|     public void update(@Validated(ValidateGroup.Crud.Update.class) @RequestBody C req, @PathVariable("id") Long id) { | ||||
|         this.checkPermission(Api.UPDATE); | ||||
|         baseService.update(req, id); | ||||
|     } | ||||
|  | ||||
| @@ -150,12 +147,12 @@ public abstract class BaseController<S extends BaseService<L, D, Q, C>, L, D, Q, | ||||
|      * | ||||
|      * @param ids ID 列表 | ||||
|      */ | ||||
|     @CrudApi(Api.DELETE) | ||||
|     @Operation(summary = "删除数据", description = "删除数据") | ||||
|     @Parameter(name = "ids", description = "ID 列表", example = "1,2", in = ParameterIn.PATH) | ||||
|     @ResponseBody | ||||
|     @DeleteMapping("/{ids}") | ||||
|     public void delete(@PathVariable("ids") List<Long> ids) { | ||||
|         this.checkPermission(Api.DELETE); | ||||
|         baseService.delete(ids); | ||||
|     } | ||||
|  | ||||
| @@ -166,24 +163,11 @@ public abstract class BaseController<S extends BaseService<L, D, Q, C>, L, D, Q, | ||||
|      * @param sortQuery 排序查询条件 | ||||
|      * @param response  响应对象 | ||||
|      */ | ||||
|     @CrudApi(Api.EXPORT) | ||||
|     @ExcludeFromGracefulResponse | ||||
|     @Operation(summary = "导出数据", description = "导出数据") | ||||
|     @GetMapping("/export") | ||||
|     public void export(Q query, SortQuery sortQuery, HttpServletResponse response) { | ||||
|         this.checkPermission(Api.EXPORT); | ||||
|         baseService.export(query, sortQuery, response); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 根据 API 类型进行权限验证 | ||||
|      * | ||||
|      * @param api API 类型 | ||||
|      */ | ||||
|     protected void checkPermission(Api api) { | ||||
|         CrudRequestMapping crudRequestMapping = this.getClass().getDeclaredAnnotation(CrudRequestMapping.class); | ||||
|         String path = crudRequestMapping.value(); | ||||
|         String permissionPrefix = String.join(StringConstants.COLON, CharSequenceUtil | ||||
|             .splitTrim(path, StringConstants.SLASH)); | ||||
|         StpUtil.checkPermission("%s:%s".formatted(permissionPrefix, api.name().toLowerCase())); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -16,9 +16,7 @@ | ||||
|  | ||||
| package top.continew.starter.extension.crud.controller; | ||||
|  | ||||
| import cn.dev33.satoken.stp.StpUtil; | ||||
| import cn.hutool.core.lang.tree.Tree; | ||||
| import cn.hutool.core.text.CharSequenceUtil; | ||||
| import com.feiniaojin.gracefulresponse.api.ExcludeFromGracefulResponse; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.Parameter; | ||||
| @@ -27,8 +25,7 @@ import jakarta.servlet.http.HttpServletResponse; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.validation.annotation.Validated; | ||||
| import org.springframework.web.bind.annotation.*; | ||||
| import top.continew.starter.core.constant.StringConstants; | ||||
| import top.continew.starter.extension.crud.annotation.CrudRequestMapping; | ||||
| import top.continew.starter.extension.crud.annotation.CrudApi; | ||||
| import top.continew.starter.extension.crud.enums.Api; | ||||
| import top.continew.starter.extension.crud.model.query.PageQuery; | ||||
| import top.continew.starter.extension.crud.model.query.SortQuery; | ||||
| @@ -63,11 +60,11 @@ public abstract class BaseController<S extends BaseService<L, D, Q, C>, L, D, Q, | ||||
|      * @param pageQuery 分页查询条件 | ||||
|      * @return 分页信息 | ||||
|      */ | ||||
|     @CrudApi(Api.PAGE) | ||||
|     @Operation(summary = "分页查询列表", description = "分页查询列表") | ||||
|     @ResponseBody | ||||
|     @GetMapping | ||||
|     public PageResp<L> page(Q query, @Validated PageQuery pageQuery) { | ||||
|         this.checkPermission(Api.LIST); | ||||
|         return baseService.page(query, pageQuery); | ||||
|     } | ||||
|  | ||||
| @@ -78,11 +75,11 @@ public abstract class BaseController<S extends BaseService<L, D, Q, C>, L, D, Q, | ||||
|      * @param sortQuery 排序查询条件 | ||||
|      * @return 列表信息 | ||||
|      */ | ||||
|     @CrudApi(Api.LIST) | ||||
|     @Operation(summary = "查询列表", description = "查询列表") | ||||
|     @ResponseBody | ||||
|     @GetMapping("/list") | ||||
|     public List<L> list(Q query, SortQuery sortQuery) { | ||||
|         this.checkPermission(Api.LIST); | ||||
|         return baseService.list(query, sortQuery); | ||||
|     } | ||||
|  | ||||
| @@ -93,11 +90,11 @@ public abstract class BaseController<S extends BaseService<L, D, Q, C>, L, D, Q, | ||||
|      * @param sortQuery 排序查询条件 | ||||
|      * @return 树列表信息 | ||||
|      */ | ||||
|     @CrudApi(Api.TREE) | ||||
|     @Operation(summary = "查询树列表", description = "查询树列表") | ||||
|     @ResponseBody | ||||
|     @GetMapping("/tree") | ||||
|     public List<Tree<Long>> tree(Q query, SortQuery sortQuery) { | ||||
|         this.checkPermission(Api.LIST); | ||||
|         return baseService.tree(query, sortQuery, false); | ||||
|     } | ||||
|  | ||||
| @@ -107,41 +104,41 @@ public abstract class BaseController<S extends BaseService<L, D, Q, C>, L, D, Q, | ||||
|      * @param id ID | ||||
|      * @return 详情信息 | ||||
|      */ | ||||
|     @CrudApi(Api.DETAIL) | ||||
|     @Operation(summary = "查询详情", description = "查询详情") | ||||
|     @Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH) | ||||
|     @ResponseBody | ||||
|     @GetMapping("/{id}") | ||||
|     public D detail(@PathVariable("id") Long id) { | ||||
|         this.checkPermission(Api.DETAIL); | ||||
|         return baseService.get(id); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 新增 | ||||
|      * | ||||
|      * @param req 创建信息 | ||||
|      * @return 自增 ID | ||||
|      * @param req 创建参数 | ||||
|      * @return ID | ||||
|      */ | ||||
|     @CrudApi(Api.ADD) | ||||
|     @Operation(summary = "新增数据", description = "新增数据") | ||||
|     @ResponseBody | ||||
|     @PostMapping | ||||
|     public BaseIdResp<Long> add(@Validated(ValidateGroup.Crud.Add.class) @RequestBody C req) { | ||||
|         this.checkPermission(Api.ADD); | ||||
|         return new BaseIdResp<>(baseService.add(req)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 修改 | ||||
|      * | ||||
|      * @param req 修改信息 | ||||
|      * @param req 修改参数 | ||||
|      * @param id  ID | ||||
|      */ | ||||
|     @CrudApi(Api.UPDATE) | ||||
|     @Operation(summary = "修改数据", description = "修改数据") | ||||
|     @Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH) | ||||
|     @ResponseBody | ||||
|     @PutMapping("/{id}") | ||||
|     public void update(@Validated(ValidateGroup.Crud.Update.class) @RequestBody C req, @PathVariable("id") Long id) { | ||||
|         this.checkPermission(Api.UPDATE); | ||||
|         baseService.update(req, id); | ||||
|     } | ||||
|  | ||||
| @@ -150,12 +147,12 @@ public abstract class BaseController<S extends BaseService<L, D, Q, C>, L, D, Q, | ||||
|      * | ||||
|      * @param ids ID 列表 | ||||
|      */ | ||||
|     @CrudApi(Api.DELETE) | ||||
|     @Operation(summary = "删除数据", description = "删除数据") | ||||
|     @Parameter(name = "ids", description = "ID 列表", example = "1,2", in = ParameterIn.PATH) | ||||
|     @ResponseBody | ||||
|     @DeleteMapping("/{ids}") | ||||
|     public void delete(@PathVariable("ids") List<Long> ids) { | ||||
|         this.checkPermission(Api.DELETE); | ||||
|         baseService.delete(ids); | ||||
|     } | ||||
|  | ||||
| @@ -166,24 +163,11 @@ public abstract class BaseController<S extends BaseService<L, D, Q, C>, L, D, Q, | ||||
|      * @param sortQuery 排序查询条件 | ||||
|      * @param response  响应对象 | ||||
|      */ | ||||
|     @CrudApi(Api.EXPORT) | ||||
|     @ExcludeFromGracefulResponse | ||||
|     @Operation(summary = "导出数据", description = "导出数据") | ||||
|     @GetMapping("/export") | ||||
|     public void export(Q query, SortQuery sortQuery, HttpServletResponse response) { | ||||
|         this.checkPermission(Api.EXPORT); | ||||
|         baseService.export(query, sortQuery, response); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 根据 API 类型进行权限验证 | ||||
|      * | ||||
|      * @param api API 类型 | ||||
|      */ | ||||
|     protected void checkPermission(Api api) { | ||||
|         CrudRequestMapping crudRequestMapping = this.getClass().getDeclaredAnnotation(CrudRequestMapping.class); | ||||
|         String path = crudRequestMapping.value(); | ||||
|         String permissionPrefix = String.join(StringConstants.COLON, CharSequenceUtil | ||||
|             .splitTrim(path, StringConstants.SLASH)); | ||||
|         StpUtil.checkPermission("%s:%s".formatted(permissionPrefix, api.name().toLowerCase())); | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user