96SEO 2026-02-20 07:44 0
但是不想写重复代码#xff0c;我们可以提供一个通用starter#xff0c;提…1.

在我们日常的Java开发中免不了和其他系统的业务交互或者微服务之间的接口调用
但是不想写重复代码我们可以提供一个通用starter提供通用加密解密功能
hutool-crypto提供了很多加密解密工具包括对称加密非对称加密摘要加密等等这不做详细介绍。
在接口调用链中request的请求流只能调用一次处理之后如果之后还需要用到请求流获取数据就会发现数据为空。
比如使用了filter或者aop在接口处理之前获取了request中的数据对参数进行了校验那么之后就不能在获取request请求流了。
继承HttpServletRequestWrapper将请求中的流copy一份复写getInputStream和getReader方法供外部使用。
每次调用后的getInputStream方法都是从复制出来的二进制数组中进行获取这个二进制数组在对象存在期间一致存在。
使用Filter过滤器在一开始替换request为自己定义的可以多次读取流的request。
InputStreamHttpServletRequestWrapper
xyz.hlh.cryptotest.utils;import
org.apache.commons.io.IOUtils;import
javax.servlet.ServletInputStream;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletRequestWrapper;
InputStreamHttpServletRequestWrapper
InputStreamHttpServletRequestWrapper(HttpServletRequest
{super(request);}Overridepublic
CachedServletInputStream(cachedBytes.toByteArray());}Overridepublic
InputStreamReader(getInputStream()));}/***
ByteArrayOutputStream();IOUtils.copy(super.getInputStream(),
CachedServletInputStream(byte[]
ByteArrayInputStream(buf);}Overridepublic
HttpServletRequestInputStreamFilter
xyz.hlh.cryptotest.filter;import
org.springframework.core.annotation.Order;
org.springframework.stereotype.Component;
xyz.hlh.cryptotest.utils.InputStreamHttpServletRequestWrapper;import
javax.servlet.ServletException;
javax.servlet.http.HttpServletRequest;
org.springframework.core.Ordered.HIGHEST_PRECEDENCE;/***
HttpServletRequestInputStreamFilter
转换为可以多次获取流的requestHttpServletRequest
request;InputStreamHttpServletRequestWrapper
inputStreamHttpServletRequestWrapper
InputStreamHttpServletRequestWrapper(httpServletRequest);//
放行chain.doFilter(inputStreamHttpServletRequestWrapper,
SpringBoot-validation提供了优雅的参数校验入参都是实体类在实体类字段上加上对应注解就可以在进入方法之前进行参数校验如果参数错误会抛出错误BindException是不会进入方法的。
这种方法必须要求在接口参数上加注解Validated或者是Valid
但是很多清空下我们希望在代码中调用某个实体类的校验功能所以需要如下工具类。
xyz.hlh.cryptotest.exception;import
xyz.hlh.cryptotest.utils;import
xyz.hlh.cryptotest.exception.CustomizeException;
xyz.hlh.cryptotest.exception.ParamException;import
javax.validation.ConstraintViolation;
Validation.buildDefaultValidatorFactory().getValidator();/***
验证结果异常throwParamException(validate);}/***
验证结果异常throwParamException(validate);}/***
VALIDATOR.validateProperty(object,
验证结果异常throwParamException(validate);}/***
VALIDATOR.validateProperty(object,
验证结果异常throwParamException(validate);}/***
throwParamException(SetConstraintViolationObject
{fieldList.add(next.getPropertyPath().toString());msgList.add(next.getMessage());}throw
声明自动配置类把需要对外提供的对象创建好通过配置类统一向外暴露
在resource目录下准备一个名为spring/spring.factories的文件以org.springframework.boot.autoconfigure.EnableAutoConfiguration为key自动配置类为value列表进行注册
RequestBodyAdvice和ResponseBodyAdvice
RequestBodyAdvice是对请求的json串进行处理
ResponseBodyAdvice是对请求相应的jsoin传进行处理一般用于相应结果的加密
接口入参的时候接收的是解密之后的数据但是在进入接口之前会自动解密取得对应的数据
加密解密使用对称加密的AES算法使用hutool-crypto模块进行实现
所有的实体类提取一个公共父类包含属性时间戳用于加密数据返回之后的实效性如果超过60分钟那么其他接口将不进行处理。
如果接口加了加密注解EncryptionAnnotation并且返回统一的json数据Result类则自动对数据进行加密。
如果是继承了统一父类RequestBase的数据自动注入时间戳确保数据的时效性
如果接口加了解密注解DecryptionAnnotation并且参数使用RequestBody注解标注传入json使用统一格式RequestData类并且内容是继承了包含时间长的父类RequestBase则自动解密并且转为对应的数据类型
org.springframework.boot.autoconfigure.EnableAutoConfiguration\
xyz.hlh.crypto.config.AppConfig
org.springframework.boot.context.properties.ConfigurationProperties;
org.springframework.context.annotation.Configuration;
org.springframework.context.annotation.PropertySource;import
PropertySource(classpath:crypto.properties)
cn.hutool.crypto.symmetric.AES;
org.springframework.context.annotation.Bean;
org.springframework.context.annotation.Configuration;import
java.nio.charset.StandardCharsets;/***
cryptConfig.getKey().getBytes(StandardCharsets.UTF_8),
cryptConfig.getIv().getBytes(StandardCharsets.UTF_8));}}
com.fasterxml.jackson.databind.ObjectMapper;
org.apache.commons.lang3.StringUtils;
org.springframework.beans.factory.annotation.Autowired;
org.springframework.core.MethodParameter;
org.springframework.http.HttpInputMessage;
org.springframework.http.converter.HttpMessageConverter;
org.springframework.web.bind.annotation.ControllerAdvice;
org.springframework.web.context.request.RequestAttributes;
org.springframework.web.context.request.RequestContextHolder;
org.springframework.web.context.request.ServletRequestAttributes;
org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;
xyz.hlh.crypto.annotation.DecryptionAnnotation;
xyz.hlh.crypto.common.exception.ParamException;
xyz.hlh.crypto.constant.CryptoConstant;
xyz.hlh.crypto.entity.RequestBase;
xyz.hlh.crypto.entity.RequestData;
xyz.hlh.crypto.util.AESUtil;import
javax.servlet.ServletInputStream;
javax.servlet.http.HttpServletRequest;
方法上有DecryptionAnnotation注解的进入此拦截器*
methodParameter.hasMethodAnnotation(DecryptionAnnotation.class);}Overridepublic
beforeBodyRead(HttpInputMessage
真实的参数*/SneakyThrowsOverridepublic
RequestContextHolder.getRequestAttributes();ServletRequestAttributes
ParamException(request错误);}HttpServletRequest
servletRequestAttributes.getRequest();//
request.getInputStream();RequestData
objectMapper.readValue(inputStream,
StringUtils.isBlank(requestData.getText()))
放入解密之前的数据request.setAttribute(CryptoConstant.INPUT_ORIGINAL_DATA,
(StringUtils.isBlank(decryptText))
放入解密之后的数据request.setAttribute(CryptoConstant.INPUT_DECRYPT_DATA,
objectMapper.readValue(decryptText,
result).getCurrentTimeMillis();//
ParamException(String.format(请求参数类型%s
RequestBase.class.getName()));}}/***
真实的参数*/SneakyThrowsOverridepublic
targetType.getTypeName();Class?
com.fasterxml.jackson.databind.ObjectMapper;
org.apache.commons.lang3.StringUtils;
org.springframework.beans.factory.annotation.Autowired;
org.springframework.core.MethodParameter;
org.springframework.http.MediaType;
org.springframework.http.ResponseEntity;
org.springframework.http.converter.HttpMessageConverter;
org.springframework.http.server.ServerHttpRequest;
org.springframework.http.server.ServerHttpResponse;
org.springframework.web.bind.annotation.ControllerAdvice;
org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
xyz.hlh.crypto.annotation.EncryptionAnnotation;
xyz.hlh.crypto.common.entity.Result;
xyz.hlh.crypto.common.exception.CryptoException;
xyz.hlh.crypto.entity.RequestBase;
xyz.hlh.crypto.util.AESUtil;import
(ParameterizedTypeImpl)returnType.getGenericParameterType();//
(genericParameterType.getRawType()
returnType.hasMethodAnnotation(EncryptionAnnotation.class))
(genericParameterType.getRawType()
genericParameterType.getActualTypeArguments())
returnType.hasMethodAnnotation(EncryptionAnnotation.class))
false;}SneakyThrowsOverridepublic
{((RequestBase)data).setCurrentTimeMillis(System.currentTimeMillis());}String
(StringUtils.isBlank(dataText))
CryptoException(加密失败数据小于16位);}String
AESUtil.encryptHex(dataText);return
Result.builder().status(body.getStatus()).data(encryptText).message(body.getMessage()).build();}
org.hibernate.validator.constraints.Range;import
javax.validation.constraints.NotBlank;
javax.validation.constraints.NotNull;
Teacher实体类使用SpringBoot的validation校验*
xyz.hlh.crypto.controller;import
org.springframework.http.ResponseEntity;
org.springframework.validation.annotation.Validated;
org.springframework.web.bind.annotation.PostMapping;
org.springframework.web.bind.annotation.RequestBody;
org.springframework.web.bind.annotation.RestController;
xyz.hlh.crypto.annotation.DecryptionAnnotation;
xyz.hlh.crypto.annotation.EncryptionAnnotation;
xyz.hlh.crypto.common.entity.Result;
xyz.hlh.crypto.common.entity.ResultBuilder;
xyz.hlh.crypto.entity.Teacher;/***
不加密的对象*/PostMapping(/get)public
ResponseBodyResult格式*/PostMapping(/encrypt)EncryptionAnnotationpublic
Result格式*/PostMapping(/encrypt1)EncryptionAnnotationpublic
success(teacher).getBody();}/***
返回解密后的数据*/PostMapping(/decrypt)DecryptionAnnotationpublic
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback