Mapstruct如何配置全局规则实现源字段映射到带__c后缀的目标字段
MapStruct自动映射源字段到加__c后缀目标字段的解决方案
方案1:编译期全局命名策略(推荐,性能无损耗)
该方案通过自定义MapStruct的访问器命名策略,在编译阶段自动识别带__c后缀的目标字段,匹配对应同源字段,无运行期反射开销,适合项目中普遍存在「目标字段=源字段+__c」映射规则的场景。
第一步:自定义命名策略类
import org.mapstruct.ap.spi.DefaultAccessorNamingStrategy; import javax.lang.model.element.ExecutableElement; public class SuffixAccessorNamingStrategy extends DefaultAccessorNamingStrategy { private static final String TARGET_SUFFIX = "__c"; @Override public String getPropertyName(ExecutableElement getterOrSetterMethod) { String propertyName = super.getPropertyName(getterOrSetterMethod); // 目标类带__c后缀的字段自动去除后缀后,和源字段做匹配 if (propertyName.endsWith(TARGET_SUFFIX)) { return propertyName.substring(0, propertyName.length() - TARGET_SUFFIX.length()); } return propertyName; } }
第二步:注册自定义策略
在项目resources目录下创建层级路径META-INF/services/,新建文件名为org.mapstruct.ap.spi.AccessorNamingStrategy,文件内容填写你自定义策略类的全限定名即可,示例:
com.yourbusiness.config.SuffixAccessorNamingStrategy
配置完成后所有Mapper的目标字段只要符合「源字段名+__c」的规则,都不需要单独写@Mapping注解,编译时会自动完成映射匹配,存在特殊规则的字段单独加@Mapping注解即可覆盖自动匹配逻辑。
方案2:单Mapper局部生效(不需要全局配置)
如果只需要在个别Mapper中使用该规则,不需要全局生效,可以自定义映射方法实现批量转换:
import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Named; import org.springframework.beans.BeanWrapper; import org.springframework.beans.BeanWrapperImpl; import java.beans.PropertyDescriptor; @Mapper public interface ContactMapper { ContactMapper INSTANCE = Mappers.getMapper(ContactMapper.class); @Mapping(target = ".", source = ".", qualifiedByName = "suffixFieldMapping") SimpleDestination customerContact(SimpleSource source); @Named("suffixFieldMapping") default SimpleDestination mapWithSuffix(SimpleSource source) throws Exception { if (source == null) { return null; } SimpleDestination target = new SimpleDestination(); BeanWrapper srcWrapper = new BeanWrapperImpl(source); BeanWrapper targetWrapper = new BeanWrapperImpl(target); for (PropertyDescriptor pd : srcWrapper.getPropertyDescriptors()) { String fieldName = pd.getName(); if ("class".equals(fieldName) || pd.getReadMethod() == null) { continue; } String targetField = fieldName + "__c"; if (targetWrapper.isWritableProperty(targetField)) { targetWrapper.setPropertyValue(targetField, pd.getReadMethod().invoke(source)); } } return target; } }
注意事项
- 方案1依赖MapStruct的SPI机制,需要保证自定义策略类在编译期的annotationProcessor路径中可被加载
- 两种方案都支持和单独配置的
@Mapping注解共存,手动配置的注解优先级高于自动匹配规则
内容的提问来源于stack exchange,提问作者ibo
相关产品推荐
相关产品推荐

