diff --git a/blade-core-secure/src/main/java/org/springblade/core/secure/config/BladeViewRoleConfiguration.java b/blade-core-secure/src/main/java/org/springblade/core/secure/config/BladeViewRoleConfiguration.java new file mode 100644 index 0000000..89cf182 --- /dev/null +++ b/blade-core-secure/src/main/java/org/springblade/core/secure/config/BladeViewRoleConfiguration.java @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.com). + *
+ * 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 + *
+ * http://www.gnu.org/licenses/lgpl.html + *
+ * 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 org.springblade.core.secure.config; + +import org.springblade.core.secure.utils.SecureUtil; +import org.springblade.core.tool.jackson.BladeRoleSupplier; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; + +/** + * Jackson Views 角色提供者自动装配 + *
+ * 默认通过 {@link SecureUtil#getUserRole()} 获取当前用户角色名, + * 用户可自定义 {@link BladeRoleSupplier} Bean 来覆盖。 + *
+ * + * @author Chill + */ +@AutoConfiguration +public class BladeViewRoleConfiguration { + + /** + * 默认角色名称提供者 + *使用 {@link ConditionalOnMissingBean} 允许用户自定义覆盖
+ */ + @Bean + @ConditionalOnMissingBean + public BladeRoleSupplier roleNameSupplier() { + return SecureUtil::getUserRole; + } + +} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/config/BladeViewAutoConfiguration.java b/blade-core-tool/src/main/java/org/springblade/core/tool/config/BladeViewAutoConfiguration.java new file mode 100644 index 0000000..eb529fc --- /dev/null +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/config/BladeViewAutoConfiguration.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.com). + *+ * 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 + *
+ * http://www.gnu.org/licenses/lgpl.html + *
+ * 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 org.springblade.core.tool.config; + +import org.springblade.core.tool.jackson.*; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; + +/** + * BladeView 视图序列化自动装配 + *
+ * 框架内置常驻加载,无需手动开启。 + * 当 Controller 方法未标注 {@link BladeView} 时不产生任何额外开销。 + * 所有 Bean 均支持 {@link ConditionalOnMissingBean},可由用户自定义覆盖。 + *
+ * + * @author Chill + */ +@AutoConfiguration(after = JacksonConfiguration.class) +public class BladeViewAutoConfiguration { + + /** + * 视图解析器 + */ + @Bean + @ConditionalOnMissingBean + public BladeViewResolver bladeViewResolver(BladeJacksonProperties properties, ObjectProvider可选: summary / detail / admin / administrator
+ */ + private String defaultView = "summary"; + /** + * 角色 → 视图映射 + */ + private Map+ * 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 + *
+ * http://www.gnu.org/licenses/lgpl.html + *
+ * 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 org.springblade.core.tool.jackson; + +import java.util.function.Supplier; + +/** + * BladeView 角色名提供者 + *
+ * 用于 {@link BladeViewResponseAdvice} 动态模式下按角色解析视图。
+ * 自定义时请实现本接口而非通用的 {@code Supplier
+ * @Bean
+ * public BladeRoleSupplier myRoleSupplier() {
+ * return () -> currentUserHolder.getRole();
+ * }
+ *
+ *
+ * @author Chill
+ */
+@FunctionalInterface
+public interface BladeRoleSupplier extends Supplier+ * 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 + *
+ * http://www.gnu.org/licenses/lgpl.html + *
+ * 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 org.springblade.core.tool.jackson; + +import java.lang.annotation.*; + +/** + * BladeX 视图控制注解(全场景统一) + *
+ * 用在字段上:标记该字段的可见视图层级(替代 {@code @JsonView}) + * 用在方法/类上:控制接口的视图过滤策略 + *
+ * + *+ * @BladeView(Views.Detail.class) + * private String tenantName; + *+ * + *
+ * // 静态:明确指定视图
+ * @BladeView(Views.Summary.class)
+ * public R<List<UserVO>> list() { ... }
+ *
+ * // 动态:根据用户角色自动解析
+ * @BladeView
+ * public R<UserVO> detail() { ... }
+ *
+ * // 类级别默认(方法级可覆盖)
+ * @BladeView(Views.Admin.class)
+ * public class AdminController { ... }
+ *
+ *
+ * @author Chill
+ */
+@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface BladeView {
+
+ /**
+ * 视图类型
+ * + * 字段上:指定 Views.Summary / Detail / Admin / Administrator + * 方法上:指定具体视图 = 静态模式;默认 Auto.class = 动态模式 + *
+ */ + Class> value() default Auto.class; + + /** + * 动态解析标记(仅用于 Controller 方法/类) + */ + interface Auto { + } + +} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/BladeViewAnnotationIntrospector.java b/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/BladeViewAnnotationIntrospector.java new file mode 100644 index 0000000..06a9151 --- /dev/null +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/BladeViewAnnotationIntrospector.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.com). + *+ * 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 + *
+ * http://www.gnu.org/licenses/lgpl.html + *
+ * 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 org.springblade.core.tool.jackson; + +import com.fasterxml.jackson.databind.introspect.Annotated; +import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; + +import java.io.Serial; + +/** + * 自定义 Jackson 注解内省器 + *
+ * 让 Jackson 序列化引擎识别字段上的 {@link BladeView} 注解, + * 将其等同于标准的 {@code @JsonView} 处理。 + *
+ *+ * 继承 {@link JacksonAnnotationIntrospector},所有标准 Jackson 注解 + * ({@code @JsonIgnore}、{@code @JsonSerialize}、{@code @JsonFormat} 等) + * 通过 super 正常工作。 + *
+ * + * @author Chill + */ +public class BladeViewAnnotationIntrospector extends JacksonAnnotationIntrospector { + + @Serial + private static final long serialVersionUID = 1L; + + @Override + public Class>[] findViews(Annotated a) { + // 优先识别 @BladeView(仅处理非 Auto 的静态视图标注) + BladeView bladeView = _findAnnotation(a, BladeView.class); + if (bladeView != null && bladeView.value() != BladeView.Auto.class) { + return new Class>[]{bladeView.value()}; + } + // 兼容:仍然识别标准 @JsonView + return super.findViews(a); + } + +} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/BladeViewCustomizer.java b/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/BladeViewCustomizer.java new file mode 100644 index 0000000..f2bd2c7 --- /dev/null +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/BladeViewCustomizer.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.com). + *+ * 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 + *
+ * http://www.gnu.org/licenses/lgpl.html + *
+ * 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 org.springblade.core.tool.jackson; + +/** + * 视图自定义扩展接口 + *
+ * 用户可通过实现此接口来注册自定义视图层级, + * 注册为 Spring Bean 即可生效。 + *
+ * + *
+ * // 1. 定义自定义视图接口
+ * public interface SuperView extends Views.Administrator {}
+ *
+ * // 2. 注册到解析器
+ * @Bean
+ * public BladeViewCustomizer myViewCustomizer() {
+ * return resolver -> resolver.registerView("super", SuperView.class, 4);
+ * }
+ *
+ * // 3. 在 YAML 中映射角色
+ * // blade.jackson.view.role-mapping.superadmin: super
+ *
+ *
+ * @author Chill
+ */
+@FunctionalInterface
+public interface BladeViewCustomizer {
+
+ /**
+ * 自定义视图注册
+ *
+ * @param resolver 视图解析器
+ */
+ void customize(BladeViewResolver resolver);
+
+}
diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/BladeViewResolver.java b/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/BladeViewResolver.java
new file mode 100644
index 0000000..60db3db
--- /dev/null
+++ b/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/BladeViewResolver.java
@@ -0,0 +1,114 @@
+/**
+ * Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.com).
+ * + * 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 + *
+ * http://www.gnu.org/licenses/lgpl.html + *
+ * 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 org.springblade.core.tool.jackson; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 视图解析器 — 视图名/角色名 → 视图 Class + *
+ * 内置四级视图:summary(0) → detail(1) → admin(2) → administrator(3) + * 可通过 {@link BladeViewCustomizer} 注册自定义视图层级 + *
+ * + * @author Chill + */ +public class BladeViewResolver { + + private final BladeJacksonProperties.View viewProperties; + + /** + * 视图名称 → 视图 Class 映射(线程安全) + */ + private final Map+ * 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 + *
+ * http://www.gnu.org/licenses/lgpl.html + *
+ * 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 org.springblade.core.tool.jackson; + +import lombok.RequiredArgsConstructor; +import net.dreamlu.mica.auto.annotation.AutoIgnore; +import org.springframework.core.MethodParameter; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJacksonValue; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; + +/** + * {@link BladeView} 响应拦截器 + *
+ * 拦截 Controller 方法/类上的 {@link BladeView} 注解, + * 解析视图 Class 后包装为 {@link MappingJacksonValue} 交给 Jackson 处理。 + *
+ * + * @author Chill + */ +@AutoIgnore +@ControllerAdvice +@RequiredArgsConstructor +public class BladeViewResponseAdvice implements ResponseBodyAdvice