{"id":10006343,"date":"2022-08-30T12:58:05","date_gmt":"2022-08-30T04:58:05","guid":{"rendered":"https:\/\/ityet.com\/?p=10006343"},"modified":"2022-08-30T12:58:05","modified_gmt":"2022-08-30T04:58:05","slug":"%e8%81%8a%e8%81%8a%e5%a6%82%e4%bd%95%e5%88%a9%e7%94%a8%e7%ae%a1%e9%81%93%e6%a8%a1%e5%bc%8f%e6%9d%a5%e8%bf%9b%e8%a1%8c%e4%b8%9a%e5%8a%a1%e7%bc%96%e6%8e%92%ef%bc%88%e4%b8%8a%e7%af%87%ef%bc%89","status":"publish","type":"post","link":"https:\/\/itmax.cn\/?p=10006343","title":{"rendered":"\u804a\u804a\u5982\u4f55\u5229\u7528\u7ba1\u9053\u6a21\u5f0f\u6765\u8fdb\u884c\u4e1a\u52a1\u7f16\u6392\uff08\u4e0a\u7bc7\uff09"},"content":{"rendered":"<h2>\u524d\u8a00<\/h2>\n<blockquote><p>1\u3001\u4ec0\u4e48\u662f\u7ba1\u9053\u6a21\u5f0f<\/p><\/blockquote>\n<p>\u7ba1\u9053\u6a21\u5f0f\u4e0d\u5c5e\u4e8e\u6211\u4eec\u5e38\u8bf4\u768423\u79cd\u8bbe\u8ba1\u6a21\u5f0f\u4e2d\u7684\u4e00\u79cd\uff0c\u5b83\u53ef\u4ee5\u770b\u6210\u662f\u8d23\u4efb\u94fe\u6a21\u5f0f\u7684\u4e00\u79cd\u53d8\u4f53\u3002\u6240\u8c13\u7684\u7ba1\u9053\u6a21\u5f0f\u7528\u6280\u672f\u8bdd\u6765\u8bf4\uff0c\u5c31\u662f\u628a\u6570\u636e\u4f20\u9012\u7ed9\u4e00\u4e2a\u4efb\u52a1\u961f\u5217\uff0c\u7531\u4efb\u52a1\u961f\u5217\u6309\u6b21\u5e8f\u4f9d\u6b21\u5bf9\u6570\u636e\u8fdb\u884c\u52a0\u5de5\u5904\u7406\u3002<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042398703\" alt=\"\" title=\"\" loading=\"lazy\"><\/p>\n<blockquote><p>2\u3001\u4ec0\u4e48\u6837\u7684\u573a\u666f\u9002\u5408\u7528\u7ba1\u9053\u6a21\u5f0f<\/p><\/blockquote>\n<p>\u5f53\u4e1a\u52a1\u6d41\u7a0b\u6bd4\u8f83\u590d\u6742\u65f6\uff0c\u9700\u8981\u62c6\u5206\u6210\u591a\u4e2a\u5b50\u6b65\u9aa4\uff0c\u4e14\u6bcf\u4e2a\u5b50\u6b65\u9aa4\u53ef\u4ee5\u81ea\u7531\u7ec4\u5408\uff0c\u66ff\u6362\uff0c\u65b0\u589e\uff0c\u5220\u9664\u7684\u573a\u666f<\/p>\n<h2>\u5b9e\u73b0\u7ba1\u9053\u7684\u4e00\u822c\u5957\u8def<\/h2>\n<blockquote><p>1\u3001\u5c01\u88c5\u7ba1\u9053\u6570\u636e\u900f\u4f20\u4e0a\u4e0b\u6587<\/p><\/blockquote>\n<pre><code class=\"java\">public class ChannelHandlerContext extends ConcurrentHashMap&lt;String,Object&gt; {\n\n    protected static Class&lt;? extends ChannelHandlerContext&gt; contextClass = ChannelHandlerContext.class;\n\n    protected static final TransmittableThreadLocal&lt;? extends ChannelHandlerContext&gt; CHAIN_CONTEXT = new TransmittableThreadLocal&lt;ChannelHandlerContext&gt;() {\n        @Override\n        protected ChannelHandlerContext initialValue() {\n            try {\n                return contextClass.getDeclaredConstructor().newInstance();\n            } catch (Throwable e) {\n                throw new RuntimeException(e);\n            }\n        }\n    };\n\n    \/**\n     * \u8986\u76d6\u9ed8\u8ba4\u7684\u7ba1\u9053\u4e0a\u4e0b\u6587\n     *\n     * @param clazz\n     *\/\n    public static void setContextClass(Class&lt;? extends ChannelHandlerContext&gt; clazz) {\n        contextClass = clazz;\n    }\n\n    \/**\n     * \u83b7\u53d6\u5f53\u524d\u7ba1\u9053\u4e0a\u4e0b\u6587\n     *\n     *\n     *\/\n    public static final ChannelHandlerContext getCurrentContext() {\n        return CHAIN_CONTEXT.get();\n    }\n\n    \/**\n     * \u91ca\u653e\u4e0a\u4e0b\u6587\u8d44\u6e90\n     *\n     * @return\n     *\/\n    public void release() {\n        this.clear();\n        CHAIN_CONTEXT.remove();\n    }\n\n    \/**\n     *\n     * \u83b7\u53d6\u4e0a\u4e0b\u6587\u9ed8\u8ba4\u503c\n     * @param key\n     * @param defaultValue\n     * @return\n     *\/\n    public Object getDefault(String key, Object defaultValue) {\n        return Optional.ofNullable(get(key)).orElse(defaultValue);\n    }\n\n    public static final String CHANNEL_HANDLER_REQUEST_KEY = &quot;channelHandlerRequest&quot;;\n\n    public ChannelHandlerRequest getChannelHandlerRequest() {\n        return (ChannelHandlerRequest) this.getDefault(CHANNEL_HANDLER_REQUEST_KEY,ChannelHandlerRequest.builder().build());\n    }\n\n\n}\n<\/code><\/pre>\n<blockquote><p>2\u3001\u5b9a\u4e49\u7ba1\u9053\u62bd\u8c61\u6267\u884c\u5668<\/p><\/blockquote>\n<pre><code class=\"java\">public abstract class AbstactChannelHandler {\n\n    private String channelHandlerName;\n\n    public String getChannelHandlerName() {\n        return channelHandlerName;\n    }\n\n    public void setChannelHandlerName(String channelHandlerName) {\n        this.channelHandlerName = channelHandlerName;\n    }\n\n    public abstract boolean handler(ChannelHandlerContext chx);\n\n\n}\n<\/code><\/pre>\n<blockquote><p>3\u3001\u5b9a\u4e49\u7ba1\u9053<\/p><\/blockquote>\n<pre><code class=\"java\">@Slf4j\npublic class ChannelPipeline {\n\n    private LinkedBlockingDeque&lt;AbstactChannelHandler&gt; channelHandlers = new LinkedBlockingDeque();\n\n    private ChannelHandlerContext handlerContext;\n\n\n    public ChannelPipeline addFirst(AbstactChannelHandler channelHandler){\n       return addFirst(null,channelHandler);\n    }\n\n    public ChannelPipeline addLast(AbstactChannelHandler channelHandler){\n      return addLast(null,channelHandler);\n    }\n\n    public ChannelPipeline addFirst(String channelHandlerName,AbstactChannelHandler channelHandler){\n        if(StringUtils.isNotBlank(channelHandlerName)){\n            channelHandler.setChannelHandlerName(channelHandlerName);\n        }\n        channelHandlers.addFirst(channelHandler);\n        return this;\n    }\n\n    public ChannelPipeline addLast(String channelHandlerName,AbstactChannelHandler channelHandler){\n        if(org.apache.commons.lang3.StringUtils.isNotBlank(channelHandlerName)){\n            channelHandler.setChannelHandlerName(channelHandlerName);\n        }\n        channelHandlers.addLast(channelHandler);\n        return this;\n    }\n\n\n    public void setChannelHandlers(LinkedBlockingDeque&lt;AbstactChannelHandler&gt; channelHandlers) {\n        this.channelHandlers = channelHandlers;\n    }\n\n    public ChannelHandlerContext getHandlerContext() {\n        return handlerContext;\n    }\n\n    public void setHandlerContext(ChannelHandlerContext handlerContext) {\n        this.handlerContext = handlerContext;\n    }\n\n    public boolean start(ChannelHandlerRequest channelHandlerRequest){\n         if(channelHandlers.isEmpty()){\n             log.warn(&quot;channelHandlers is empty&quot;);\n             return false;\n         }\n\n        return handler(channelHandlerRequest);\n    }\n\n    private boolean handler(ChannelHandlerRequest channelHandlerRequest) {\n        if(StringUtils.isBlank(channelHandlerRequest.getRequestId())){\n            channelHandlerRequest.setRequestId(String.valueOf(SnowflakeUtils.getNextId()));\n        }\n        handlerContext.put(ChannelHandlerContext.CHANNEL_HANDLER_REQUEST_KEY,channelHandlerRequest);\n        boolean isSuccess = true;\n        try {\n            for (AbstactChannelHandler channelHandler : channelHandlers) {\n                  isSuccess = channelHandler.handler(handlerContext);\n                if(!isSuccess){\n                    break;\n                }\n            }\n\n            if(!isSuccess){\n                channelHandlers.clear();\n            }\n        } catch (Exception e) {\n            log.error(&quot;{}&quot;,e.getMessage());\n            isSuccess = false;\n        } finally {\n            handlerContext.release();\n        }\n        return isSuccess;\n    }\n\n}\n<\/code><\/pre>\n<blockquote><p>4\u3001\u6839\u636e\u4e1a\u52a1\u7684\u590d\u6742\u5ea6\u62c6\u5206\u4e0d\u540c\u5b50\u4efb\u52a1\u7ba1\u9053\u6267\u884c\u5668<\/p><\/blockquote>\n<pre><code class=\"java\">@Slf4j\npublic class UserCheckChannelHandler extends AbstactChannelHandler {\n\n    \n    @Override\n    public boolean handler(ChannelHandlerContext chx) {\n        ChannelHandlerRequest channelHandlerRequest = chx.getChannelHandlerRequest();\n        System.out.println(&quot;------------------------------------\u6b65\u9aa4\u4e00\uff1a\u7528\u6237\u6570\u636e\u6821\u9a8c\u3010&quot;+channelHandlerRequest.getRequestId()+&quot;\u3011&quot;);\n        Object params = channelHandlerRequest.getParams();\n        if(params instanceof User){\n            User user = (User)params;\n            if(StringUtils.isBlank(user.getFullname())){\n                log.error(&quot;\u7528\u6237\u540d\u4e0d\u80fd\u4e3a\u7a7a&quot;);\n                return false;\n            }\n            return true;\n        }\n\n\n        return false;\n    }\n}<\/code><\/pre>\n<pre><code class=\"java\">@Slf4j\npublic class UserFillUsernameAndEmailChannelHandler extends AbstactChannelHandler {\n    @SneakyThrows\n    @Override\n    public boolean handler(ChannelHandlerContext chx) {\n        ChannelHandlerRequest channelHandlerRequest = chx.getChannelHandlerRequest();\n        System.out.println(&quot;------------------------------------\u6b65\u9aa4\u4e8c\uff1a\u7528\u6237\u540d\u4ee5\u53ca\u90ae\u7bb1\u586b\u5145\u3010\u5c06\u6c49\u8bed\u8f6c\u6210\u62fc\u97f3\u586b\u5145\u3011\u3010&quot;+channelHandlerRequest.getRequestId()+&quot;\u3011&quot;);\n        Object params = channelHandlerRequest.getParams();\n        if(params instanceof User){\n            User user = (User)params;\n            String fullname = user.getFullname();\n            HanyuPinyinOutputFormat hanyuPinyinOutputFormat = new HanyuPinyinOutputFormat();\n            hanyuPinyinOutputFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);\n            String username = PinyinHelper.toHanYuPinyinString(fullname, hanyuPinyinOutputFormat);\n            user.setUsername(username);\n            user.setEmail(username + &quot;@qq.com&quot;);\n            return true;\n        }\n\n\n        return false;\n    }\n}\n<\/code><\/pre>\n<pre><code class=\"java\">public class UserPwdEncryptChannelHandler extends AbstactChannelHandler {\n    @Override\n    public boolean handler(ChannelHandlerContext chx) {\n        ChannelHandlerRequest channelHandlerRequest = chx.getChannelHandlerRequest();\n        System.out.println(&quot;------------------------------------\u6b65\u9aa4\u4e09\uff1a\u7528\u6237\u5bc6\u7801\u660e\u6587\u8f6c\u5bc6\u6587\u3010&quot;+channelHandlerRequest.getRequestId()+&quot;\u3011&quot;);\n        Object params = channelHandlerRequest.getParams();\n        if(params instanceof User){\n            String encryptPwd = DigestUtil.sha256Hex(((User) params).getPassword());\n            ((User) params).setPassword(encryptPwd);\n            return true;\n        }\n\n        return false;\n    }\n}\n<\/code><\/pre>\n<pre><code class=\"java\">public class UserMockSaveChannelHandler extends AbstactChannelHandler {\n\n    @Override\n    public boolean handler(ChannelHandlerContext chx) {\n        ChannelHandlerRequest channelHandlerRequest = chx.getChannelHandlerRequest();\n        System.out.println(&quot;------------------------------------\u6b65\u9aa4\u56db\uff1a\u6a21\u62df\u7528\u6237\u6570\u636e\u843d\u5e93\u3010&quot;+channelHandlerRequest.getRequestId()+&quot;\u3011&quot;);\n        Object params = channelHandlerRequest.getParams();\n        if(params instanceof User){\n            Map&lt;String, User&gt; userMap = new HashMap&lt;&gt;();\n            User user = (User)params;\n            userMap.put(user.getUsername(),user);\n            chx.put(&quot;userMap&quot;,userMap);\n            return true;\n        }\n\n\n        return false;\n    }\n}\n<\/code><\/pre>\n<pre><code class=\"java\">public class UserPrintChannleHandler extends AbstactChannelHandler {\n    @Override\n    public boolean handler(ChannelHandlerContext chx) {\n        ChannelHandlerRequest channelHandlerRequest = chx.getChannelHandlerRequest();\n        System.out.println(&quot;------------------------------------\u6b65\u9aa4\u4e94\uff1a\u6253\u5370\u7528\u6237\u6570\u636e\u3010&quot;+channelHandlerRequest.getRequestId()+&quot;\u3011&quot;);\n        Object params = channelHandlerRequest.getParams();\n        if(params instanceof User){\n            Object userMap = chx.get(&quot;userMap&quot;);\n            if(userMap instanceof Map){\n                Map map = (Map)userMap;\n                if(map.containsKey(((User) params).getUsername())){\n                    System.out.println(map.get(((User) params).getUsername()));\n                    return true;\n                }\n            }\n        }\n\n        return false;\n    }\n}\n<\/code><\/pre>\n<blockquote><p>5\u3001\u5bf9\u5404\u4e2a\u5b50\u4efb\u52a1\u8fdb\u884c\u7f16\u6392\u7ec4\u5408<\/p><\/blockquote>\n<pre><code class=\"java\">@Service\npublic class UserServiceImpl implements UserService {\n\n    @Override\n    public boolean save(User user) {\n       return ChannelPipelineExecutor.pipeline()\n                .addLast(new UserCheckChannelHandler())\n                .addLast(new UserFillUsernameAndEmailChannelHandler())\n                .addLast(new UserPwdEncryptChannelHandler())\n                .addLast(new UserMockSaveChannelHandler())\n                .addLast(new UserPrintChannleHandler())\n                .start(ChannelHandlerRequest.builder().params(user).build());\n    }\n}\n<\/code><\/pre>\n<blockquote><p>6\u3001\u6d4b\u8bd5<\/p><\/blockquote>\n<pre><code class=\"java\">  Faker faker = Faker.instance(Locale.CHINA);\n        User user = User.builder().age(20)\n                .fullname(faker.name().fullName())\n                .mobile(faker.phoneNumber().phoneNumber())\n                .password(&quot;123456&quot;).build();\n        userService.save(user);<\/code><\/pre>\n<p>\u67e5\u770b\u63a7\u5236\u53f0<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042398704\" alt=\"\" title=\"\" loading=\"lazy\"><\/p>\n<blockquote><p>\u601d\u8003\u4e00\u4e0b\uff1a\u4e0a\u8ff0\u5b9e\u73b0\u7684\u7ba1\u9053\u6a21\u5f0f\uff0c\u6709\u6ca1\u6709\u4f18\u5316\u7684\u7a7a\u95f4\uff1f<\/p><\/blockquote>\n<p>\u5728\u6b65\u9aa45\u5bf9\u5404\u4e2a\u5b50\u4efb\u52a1\u8fdb\u884c\u7f16\u6392\u7ec4\u5408\uff0c\u5047\u8bbe\u5b50\u4e1a\u52a1\u5b58\u5728N\u4e2a\u6b65\u9aa4\uff0c\u6211\u4eec\u9700\u8981addLast N\u6b21\uff0c\u611f\u89c9\u6709\u70b9\u786c\u7f16\u7801\u4e86\u3002\u56e0\u6b64\u6211\u4eec\u53ef\u4ee5\u505a\u5982\u4e0b\u6539\u9020<\/p>\n<h2>\u6539\u9020<\/h2>\n<blockquote><p>1\u3001\u5b9a\u4e49\u7ba1\u9053\u6ce8\u89e3<\/p><\/blockquote>\n<pre><code class=\"java\">@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.TYPE)\n@Documented\n@Component\n@Role(BeanDefinition.ROLE_INFRASTRUCTURE)\npublic @interface Pipeline {\n\n    Class consumePipelinesService();\n\n    String consumePipelinesMethod();\n\n    Class[] args() default {};\n\n    int order();\n}\n<\/code><\/pre>\n<blockquote><p>2\u3001\u5b9a\u4e49\u7ba1\u9053\u626b\u63cf\u5668<\/p><\/blockquote>\n<pre><code class=\"java\">public class PipelineClassPathBeanDefinitionScanner extends ClassPathBeanDefinitionScanner {\n\n    public PipelineClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {\n        super(registry);\n    }\n\n\n    @Override\n    protected Set&lt;BeanDefinitionHolder&gt; doScan(String... basePackages) {\n        Set&lt;BeanDefinitionHolder&gt; beanDefinitionHolders = super.doScan(basePackages);\n        for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {\n            GenericBeanDefinition beanDefinition = (GenericBeanDefinition) beanDefinitionHolder.getBeanDefinition();\n            String className = beanDefinition.getBeanClassName();\n            beanDefinition.getPropertyValues().addPropertyValue(&quot;pipelineServiceClz&quot;,className);\n            beanDefinition.setBeanClass(ComsumePipelineFactoryBean.class);\n\n        }\n\n        return beanDefinitionHolders;\n\n    }\n\n    @Override\n    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {\n        return beanDefinition.getMetadata().isInterface();\n    }\n}\n<\/code><\/pre>\n<blockquote><p>3\u3001\u5b9a\u4e49\u7ba1\u9053\u6ce8\u518c\u5668<\/p><\/blockquote>\n<pre><code class=\"java\">public class PipelineImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {\n\n    @Override\n    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {\n\n\n        PipelineClassPathBeanDefinitionScanner scanner = new PipelineClassPathBeanDefinitionScanner(registry);\n        scanner.addIncludeFilter(new AnnotationTypeFilter(FunctionalInterface.class));\n        Set&lt;String&gt; basePackages = getBasePackages(importingClassMetadata);\n        String[] basePackageArr = {};\n        scanner.scan(basePackages.toArray(basePackageArr));\n\n    }\n\n    protected Set&lt;String&gt; getBasePackages(AnnotationMetadata importingClassMetadata) {\n        Map&lt;String, Object&gt; attributes = importingClassMetadata.getAnnotationAttributes(EnabledPipeline.class.getCanonicalName());\n\n        Set&lt;String&gt; basePackages = new HashSet&lt;&gt;();\n\n        for (String pkg : (String[]) attributes.get(&quot;basePackages&quot;)) {\n            if (StringUtils.hasText(pkg)) {\n                basePackages.add(pkg);\n            }\n        }\n\n        if (basePackages.isEmpty()) {\n            basePackages.add(\n                    ClassUtils.getPackageName(importingClassMetadata.getClassName()));\n        }\n        return basePackages;\n    }\n}\n<\/code><\/pre>\n<blockquote><p>4\u3001\u5b9a\u4e49EnableXXX\u6ce8\u89e3<\/p><\/blockquote>\n<pre><code class=\"java\">@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.TYPE)\n@Documented\n@Import(PipelineImportBeanDefinitionRegistrar.class)\npublic @interface EnabledPipeline {\n\n    String[] basePackages() default {};\n}\n<\/code><\/pre>\n<p><strong>\u6ce8\uff1a<\/strong> \u6b64\u5916\u8fd8\u9700\u5b9a\u4e49\u7ba1\u9053\u4ee3\u7406\u548c\u7ba1\u9053factoryBean\uff0c\u56e0\u4e3a\u7bc7\u5e45\u5c31\u4e0d\u8d34\u4e86\u3002\u611f\u5174\u8da3\u7684\u670b\u53cb\u5c31\u67e5\u770b\u6587\u672b\u7684demo\u94fe\u63a5<\/p>\n<blockquote><p>5\u3001\u5c06\u539f\u6709\u7684\u7ba1\u9053\u4efb\u52a1\u6267\u884c\u5668\uff0c\u6539\u9020\u6210\u5982\u4e0b<\/p><\/blockquote>\n<pre><code class=\"java\">@Slf4j\n@Pipeline(consumePipelinesService = UserService.class,consumePipelinesMethod = &quot;save&quot;,args = {User.class},order = 1)\npublic class UserCheckChannelHandler extends AbstactChannelHandler {\n\n    \n    @Override\n    public boolean handler(ChannelHandlerContext chx) {\n        ChannelHandlerRequest channelHandlerRequest = chx.getChannelHandlerRequest();\n        System.out.println(&quot;------------------------------------\u6b65\u9aa4\u4e00\uff1a\u7528\u6237\u6570\u636e\u6821\u9a8c\u3010&quot;+channelHandlerRequest.getRequestId()+&quot;\u3011&quot;);\n        String json = JSON.toJSONString(channelHandlerRequest.getParams());\n        List&lt;User&gt; users = JSON.parseArray(json,User.class);\n        if(CollectionUtil.isEmpty(users) || StringUtils.isBlank(users.get(0).getFullname())){\n            log.error(&quot;\u7528\u6237\u540d\u4e0d\u80fd\u4e3a\u7a7a&quot;);\n            return false;\n        }\n        return true;\n\n\n    }\n}\n<\/code><\/pre>\n<pre><code class=\"java\">@Slf4j\n@Pipeline(consumePipelinesService = UserService.class,consumePipelinesMethod = &quot;save&quot;,args = {User.class},order = 2)\npublic class UserFillUsernameAndEmailChannelHandler extends AbstactChannelHandler {\n    @SneakyThrows\n    @Override\n    public boolean handler(ChannelHandlerContext chx) {\n        ChannelHandlerRequest channelHandlerRequest = chx.getChannelHandlerRequest();\n        System.out.println(&quot;------------------------------------\u6b65\u9aa4\u4e8c\uff1a\u7528\u6237\u540d\u4ee5\u53ca\u90ae\u7bb1\u586b\u5145\u3010\u5c06\u6c49\u8bed\u8f6c\u6210\u62fc\u97f3\u586b\u5145\u3011\u3010&quot;+channelHandlerRequest.getRequestId()+&quot;\u3011&quot;);\n        String json = JSON.toJSONString(channelHandlerRequest.getParams());\n        List&lt;User&gt; users = JSON.parseArray(json,User.class);\n        if(CollectionUtil.isNotEmpty(users)){\n            User user = users.get(0);\n            String fullname = user.getFullname();\n            HanyuPinyinOutputFormat hanyuPinyinOutputFormat = new HanyuPinyinOutputFormat();\n            hanyuPinyinOutputFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);\n            String username = PinyinHelper.toHanYuPinyinString(fullname, hanyuPinyinOutputFormat);\n            user.setUsername(username);\n            user.setEmail(username + &quot;@qq.com&quot;);\n            return true;\n\n        }\n\n\n\n        return false;\n    }\n}\n<\/code><\/pre>\n<p>\u3002\u3002\u3002\u7701\u7565\u5269\u4f59\u7ba1\u9053\u4efb\u52a1\u6267\u884c\u5668<\/p>\n<blockquote><p>6\u3001\u539f\u6765\u7684\u6b65\u9aa4\u7f16\u6392\uff0c\u4ec5\u9700\u5199\u63a5\u53e3\u5373\u53ef<\/p><\/blockquote>\n<pre><code class=\"java\">@FunctionalInterface\npublic interface UserService {\n\n    boolean save(User user);\n\n}\n<\/code><\/pre>\n<p>\u4ec5\u9700\u8fd9\u6837\u5373\u53ef\u8fdb\u884c\u7f16\u6392<\/p>\n<blockquote><p>7\u3001\u6d4b\u8bd5<\/p><\/blockquote>\n<p>\u5728\u542f\u52a8\u7c7b\u4e0a\u52a0\u4e0a@EnabledPipeline\u6ce8\u89e3\u3002\u793a\u4f8b\u5982\u4e0b<\/p>\n<pre><code class=\"java\">@SpringBootApplication\n@EnabledPipeline(basePackages = &quot;com.github.lybgeek.pipeline.spring.test&quot;)\npublic class SpringPipelineApplication  {\n\n    public static void main(String[] args) {\n        SpringApplication.run(SpringPipelineApplication.class);\n    }\n\n}<\/code><\/pre>\n<pre><code class=\"java\"> @Test\n    public void testPipeline(){\n        boolean isOk = userService.save(user);\n        Assert.assertTrue(isOk);\n\n    }<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042398705\" alt=\"\" title=\"\" loading=\"lazy\"><br \/>\u7f16\u6392\u7684\u6548\u679c\u548c\u4e4b\u524d\u7684\u4e00\u6837<\/p>\n<h2>\u603b\u7ed3<\/h2>\n<p>\u672c\u6587\u4e3b\u8981\u5b9e\u73b02\u79cd\u4e0d\u540c\u5f62\u5f0f\u7684\u7ba1\u9053\u6a21\u5f0f\uff0c\u4e00\u79cd\u57fa\u4e8e\u6ce8\u89e3\uff0c\u7f16\u6392\u6b65\u9aa4\u901a\u8fc7\u6ce8\u89e3\u76f4\u63a5\u5199\u5728\u4e86\u6267\u884c\u5668\u4e0a\uff0c\u901a\u8fc7\u6267\u884c\u5668\u53bb\u5b9a\u4f4d\u4e1a\u52a1\u6267\u884c\u65b9\u6cd5\u3002\u53e6\u5916\u4e00\u79cd\u662f\u4e1a\u52a1\u65b9\u6cd5\u91cc\u9762\u81ea\u5df1\u7ec4\u5408\u8c03\u7528\u6267\u884c\u5668\u3002\u901a\u8fc7\u6ce8\u89e3\u8fd9\u65b9\u5f0f\u867d\u7136\u907f\u514d\u4e86\u4e1a\u52a1\u65b9\u6cd5\u81ea\u5df1\u53bb\u7f16\u6392\u6267\u884c\u5668\uff0c\u4f46\u4e5f\u5b58\u5728\u5f53\u6267\u884c\u5668\u4e00\u591a\u7684\u8bdd\uff0c\u5c31\u9700\u8981\u7ffb\u6bcf\u4e2a\u6267\u884c\u5668\u7c7b\uff0c\u770b\u4ed6\u7684\u6267\u884c\u5668\u987a\u5e8f\uff0c\u8fd9\u6837\u53ef\u80fd\u4f1a\u51fa\u73b0\u6267\u884c\u5668\u56e0\u4e3a\u987a\u5e8f\u95ee\u9898\uff0c\u800c\u8fbe\u4e0d\u5230\u6211\u4eec\u60f3\u8981\u7684\u7ec4\u5408\u6548\u679c\u3002\u57fa\u4e8e\u8fd9\u4e2a\u95ee\u9898\uff0c\u6211\u5c06\u5728\u4e0b\u7bc7\u6587\u7ae0\uff0c\u5728\u4ecb\u7ecd\u5176\u4ed62\u79cd\u5b9e\u73b0\u65b9\u5f0f<\/p>\n<h2>demo\u94fe\u63a5<\/h2>\n<p><a href=\"https:\/\/link.segmentfault.com\/?enc=iRvQznb16lf0adwYiqmprQ%3D%3D.nOgGZAo6DGXxB4equkIJGA9w5kDJgWnV4YTeeziSUR1jN44uiS1rZK56jflbYpud%2BN5gIPmQUxFnParbyjQ5R7pbVC2ne21u9%2Bncm7uRXN4%3D\" rel=\"nofollow\">https:\/\/github.com\/lyb-geek\/springboot-learning\/tree\/master\/springboot-pipeline<\/a><\/p>\n<p><a href=\"https:\/\/segmentfault.com\/a\/1190000042398701\">https:\/\/segmentfault.com\/a\/1190000042398701<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u524d\u8a00 1\u3001\u4ec0\u4e48\u662f\u7ba1\u9053\u6a21\u5f0f \u7ba1\u9053\u6a21\u5f0f\u4e0d\u5c5e\u4e8e\u6211\u4eec\u5e38\u8bf4\u768423\u79cd\u8bbe\u8ba1\u6a21\u5f0f\u4e2d\u7684\u4e00\u79cd\uff0c\u5b83\u53ef\u4ee5\u770b\u6210\u662f\u8d23\u4efb\u94fe\u6a21\u5f0f\u7684\u4e00\u79cd\u53d8\u4f53\u3002\u6240 [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[],"tags":[],"class_list":["post-10006343","post","type-post","status-publish","format-standard","hentry"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10006343","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10006343"}],"version-history":[{"count":0,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10006343\/revisions"}],"wp:attachment":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10006343"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10006343"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10006343"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}