cn.zhangdeman.config 增加基础公共初始化类

This commit is contained in:
白茶清欢 2025-06-16 22:58:33 +08:00
parent 8cc165c9be
commit b8735a6c36
3 changed files with 187 additions and 0 deletions

View File

@ -0,0 +1,27 @@
package cn.zhangdeman.config;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
@Configuration
public class BaseWebConfig implements WebMvcConfigurer {
@Resource
private Http404Interceptor http404Interceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(http404Interceptor)
.addPathPatterns("/**")//拦截所有请求
.excludePathPatterns("/system/**");// 放行登录请求
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new SnakeToCamelCaseArgumentResolver());
}
}

View File

@ -0,0 +1,29 @@
package cn.zhangdeman.config;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
// Http404Interceptor 404请求的拦截器
@Slf4j
@Component
public class Http404Interceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse response, Object handler) throws Exception {
// throw new Exception("这里是我自定义的404拦截器");
return HandlerInterceptor.super.preHandle(httpServletRequest, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}

View File

@ -0,0 +1,131 @@
package cn.zhangdeman.config;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import java.util.HashMap;
import java.util.Map;
/**
* 下划线参数名转小驼峰属性名的参数解析器
*/
public class SnakeToCamelCaseArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
// 支持带有@ModelAttribute注解的参数
return parameter.hasParameterAnnotation(ModelAttribute.class);
}
@Override
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
// 1. 创建目标对象实例
Object target = parameter.getParameterType().getDeclaredConstructor().newInstance();
// 2. 创建数据绑定器
WebDataBinder binder = binderFactory.createBinder(webRequest, target, parameter.getParameterName());
// 3. 转换参数名并收集
Map<String, Object> convertedParams = convertParameterMap(webRequest.getParameterMap());
// 4. 绑定转换后的参数
binder.bind(new MutablePropertyValues(convertedParams));
// 5. 返回绑定后的对象
return binder.getTarget();
}
/**
* 将下划线风格的参数Map转换为小驼峰风格的Map
*/
private Map<String, Object> convertParameterMap(Map<String, String[]> parameterMap) {
Map<String, Object> result = new HashMap<>();
parameterMap.forEach((key, values) -> {
// 转换参数名user_name -> userName
String camelKey = convertSnakeToCamel(key);
// 处理数组参数如果是单值则取第一个元素
Object value = values.length == 1 ? values[0] : values;
// 处理嵌套参数address.home_address -> address.homeAddress
if (camelKey.contains(".")) {
handleNestedParameter(result, camelKey, value);
} else {
result.put(camelKey, value);
}
});
return result;
}
/**
* 处理嵌套参数
*/
private void handleNestedParameter(Map<String, Object> result, String key, Object value) {
String[] parts = key.split("\\.");
Map<String, Object> currentMap = result;
for (int i = 0; i < parts.length - 1; i++) {
String part = parts[i];
// 如果中间节点不存在则创建新的Map
if (!currentMap.containsKey(part)) {
currentMap.put(part, new HashMap<String, Object>());
}
// 向下钻取
Object nextLevel = currentMap.get(part);
if (nextLevel instanceof Map) {
currentMap = (Map<String, Object>) nextLevel;
} else {
// 如果中间节点不是Map则覆盖这种情况不应该发生
Map<String, Object> newMap = new HashMap<>();
currentMap.put(part, newMap);
currentMap = newMap;
}
}
// 设置最终的值
currentMap.put(parts[parts.length - 1], value);
}
/**
* 下划线命名转小驼峰命名
*/
private String convertSnakeToCamel(String snakeCase) {
if (snakeCase == null || snakeCase.isEmpty()) {
return snakeCase;
}
StringBuilder result = new StringBuilder();
boolean nextUpper = false;
for (int i = 0; i < snakeCase.length(); i++) {
char currentChar = snakeCase.charAt(i);
if (currentChar == '_') {
nextUpper = true;
} else {
if (nextUpper) {
result.append(Character.toUpperCase(currentChar));
nextUpper = false;
} else {
result.append(Character.toLowerCase(currentChar));
}
}
}
return result.toString();
}
}