• jenkins发送emailext 邮件


    1. 配置和插件
    # 插件
    Extended E-mail Notification
    Email Extension Template Plugin
    
    #模板地址
    https://github.com/jenkinsci/email-ext-plugin/tree/master/src/main/resources/hudson/plugins/emailext/templates
    https://github.com/jenkinsci/email-ext-plugin/blob/master/src/main/resources/hudson/plugins/emailext/templates
    https://plugins.jenkins.io/email-ext/
    
    # 简单说明
    为Jenkins API提供了一个pull,包括hudson.model.AbstractBuild和hudson.model.AbstractProject
    
    
    #配置Jelly
    1. 创建Jelly脚本。脚本的名称应该是<name> .jelly。名字以.jelly结尾非常重要。
    2.让您的Jenkins管理员将脚本放置在$ JENKINS_HOMemail-templates这个路径中。
    3.使用模板参数等于您的脚本文件名而不带.jelly扩展名的Jelly标记。例如,如果脚本文件名是foobar.jelly,则电子邮件内容将如下所示:$ {JELLY_SCRIPT,template =“foobar”}。
    
    
    
    
    1. 整体的pipeline
    
    
    import jenkins.model.*
    
    @NonCPS
    def getJobNames() {
    Hudson.instance.getAllItems(org.jenkinsci.plugins.workflow.job.WorkflowJob)*.fullName 
    }
        
    pipeline {
        agent any
        stages {
            
            stage('Test Stage') {
                steps {
                    sh '''
                        pwd
                    '''
                }
                
            }
        
    
            stage('getJobNames') {
                
                steps {
                    
                    script {
                        
                        def jobNames = getJobNames()
                        def matchjobs = jobNames.findAll{ name -> name =~ /(test)w*/ }
                        // println matchjobs
                        matchjobs.each {
                            try {
                                println(it)
                                res = jenkins.model.Jenkins.instance.getItem(it).lastBuild.getResult()
                                println res     
                            } catch (NullPointerException e1) {
                                    e1.printStackTrace();
                            }
                        }
            
                    }  
                  
                }
            
            }
    
            
        }//stages
        
        post {
            always {
                echo 'This will always run'
                script {                   
                        emailext (subject:'${ENV, var ="JOB_NAME"}',
                                    body:'${FILE ,path="email.html"}',
                                    to:'sgamize@sina.com',)         
                    }          
            }
            success {
                echo 'This will run only if successful'
            }
            failure {
                echo 'This will run only if failed'
            }
            unstable {
                echo 'This will run only if the run was marked as unstable'
            }
            changed {
                echo 'This will run only if the state of the Pipeline has changed'
                echo 'For example, if the Pipeline was previously failing but is now successful'
            }
        }
    }
    
    
    

    1.模板调用pipeline

    // 说明:
    // ${ENV, var="JOB_NAME"}
    // 这个写法其实和${JOB_NAME}、$JOB_NAME是等价的
    // 可以理解成:
    // ${ENV(var:JOB_NAME)}
    // 因为参数就一个所以可以简写为:
    // ${JOB_NAME}或者$JOB_NAME
    
    
    always {
        echo 'This will always run'
        script {                   
                emailext (subject:'${ENV, var ="JOB_NAME"}',
                            // body:'${FILE ,path="email.html"}',
                            // body:' ${JELLY_SCRIPT,template="foobar"}',
                            body:' ${SCRIPT,template="foobar.template.groovy"}',
                            
                            to:'sgamize@sina.com,amize.zhou@nokia-sbell.com',)         
            }          
    }
    
    1. html模板
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
        <title>Bootstrap 101 Template</title>
    
        <!-- Bootstrap -->
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
    
        <style>
            * {
                margin: 10px;
                /*background: #1b6d85;*/
            }
    
            #d2 {
                background: #4cae4c;
            }
    
            #d3 {
                background: #8a6d3b;
            }
        </style>
        <title>${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次构建日志</title>
    </head>
    
    <body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4"
        offset="0">
        <table width="95%" cellpadding="0" cellspacing="0"
            style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">
            <tr>
                <td>(本邮件是程序自动下发的,请勿回复!)</td>
            </tr>
            <tr>
                <td><h2>
                        <font color="#0000FF">构建结果 - ${BUILD_STATUS}</font>
                    </h2>
                </td>
            </tr>
            <tr>
                <td><br />
                <b><font color="#0B610B">构建信息</font></b>
                <hr size="2" width="100%" align="center" /></td>
            </tr>
            <tr>
                <td>
                    <ul>
                        <li>项目名称&nbsp;:&nbsp;${PROJECT_NAME}</li>
                        <li>构建编号&nbsp;:&nbsp;第${BUILD_NUMBER}次构建</li>
                        <li>SVN&nbsp;版本:&nbsp;${SVN_REVISION}</li>
                        <li>触发原因:&nbsp;${CAUSE}</li>
                        <li>构建日志:&nbsp;<a href="${BUILD_URL}console">${BUILD_URL}console</a></li>
                        <li>构建&nbsp;&nbsp;Url&nbsp;:&nbsp;<a href="${BUILD_URL}">${BUILD_URL}</a></li>
                        <li>工作目录&nbsp;:&nbsp;<a href="${PROJECT_URL}ws">${PROJECT_URL}ws</a></li>
                        <li>项目&nbsp;&nbsp;Url&nbsp;:&nbsp;<a href="${PROJECT_URL}">${PROJECT_URL}</a></li>
                        <li>Amize&nbsp;:&nbsp;${jobNames}:${BUILD_NUMBER}</li>
                        <j:set var="customMsg" value="${buildenv.get('jobNames')}"/>
                        <li>Amize&nbsp;:&nbsp;${customMsg}:${BUILD_NUMBER}</li>
                        <li>Amize&nbsp;:&nbsp;${buildenv.get('jobNames')}</li>
    
                    </ul>
                </td>
            </tr>
            <tr>
                <td><b><font color="#0B610B">Changes Since Last
                            Successful Build:</font></b>
                <hr size="2" width="100%" align="center" /></td>
            </tr>
            <tr>
                <td>
                    <ul>
                        <li>历史变更记录 : <a href="${PROJECT_URL}changes">${PROJECT_URL}changes</a></li>
                    </ul> ${CHANGES_SINCE_LAST_SUCCESS,reverse=true, format="Changes for Build #%n:<br />%c<br />",showPaths=true,changesFormat="<pre>[%a]<br />%m</pre>",pathFormat="&nbsp;&nbsp;&nbsp;&nbsp;%p"}
                </td>
            </tr>
            <tr>
                <td><b>Failed Test Results</b>
                <hr size="2" width="100%" align="center" /></td>
            </tr>
            <tr>
                <td><pre
                        style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">$FAILED_TESTS</pre>
                    <br /></td>
            </tr>
            <tr>
                <td><b><font color="#0B610B">构建日志 (最后 100行):</font></b>
                <hr size="2" width="100%" align="center" /></td>
            </tr>
            <tr>
                <td>Test Logs (if test has ran): <a
                    href="${PROJECT_URL}ws/TestResult/archive_logs/Log-Build-${BUILD_NUMBER}.zip">${PROJECT_URL}/ws/TestResult/archive_logs/Log-Build-${BUILD_NUMBER}.zip</a>
                    <br />
                <br />
                </td>
            </tr>
            <tr>
                <td><textarea cols="80" rows="30" readonly="readonly"
                        style="font-family: Courier New">${BUILD_LOG, maxLines=100}</textarea>
                </td>
            </tr>
        </table>
    </body>
    </html>
    

    3.jelly模板

    <?jelly escape-by-default='true'?>
    <!DOCTYPE html [
        <!ENTITY nbsp "&#38;nbsp;">
    ]>
    <j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define">
     
    <STYLE>
    BODY, TABLE, TD, TH, P {
      font-family:Verdana,Helvetica,sans serif;
      font-size:11px;
      color:black;
    }
    h1 { color:black; }
    h2 { color:black; }
    h3 { color:black; }
    TD.bg1 { color:white; background-color:#0000C0; font-size:120% }
    TD.bg2 { color:white; background-color:#4040FF; font-size:110% }
    TD.bg3 { color:white; background-color:#8080FF; }
    TD.test_passed { color:blue; }
    TD.test_failed { color:red; }
    TD.console { font-family:Courier New; }
    </STYLE>
    
    
    <BODY>
     
    <!-- GENERAL INFO -->
     
    <TABLE>
      <TR><TD align="right">
        <j:choose>
          <j:when test="${build.result=='SUCCESS'}">
            <IMG SRC="${rooturl}static/e59dfe28/images/32x32/blue.gif" />
          </j:when>
    	  <j:when test="${build.result=='FAILURE'}">
            <IMG SRC="${rooturl}static/e59dfe28/images/32x32/red.gif" />
          </j:when>
          <j:otherwise>
            <IMG SRC="${rooturl}static/e59dfe28/images/32x32/yellow.gif" />
          </j:otherwise>
        </j:choose>
      </TD><TD valign="center"><B style="font-size: 200%;">BUILD ${build.result}</B></TD></TR>
      <TR><TD>Build URL</TD><TD><A href="${rooturl}${build.url}">${rooturl}${build.url}</A></TD></TR>
      <TR><TD>Project:</TD><TD>${project.name}</TD></TR>
      <TR><TD>Date of build:</TD><TD>${it.timestampString}</TD></TR>
      <TR><TD>Build duration:</TD><TD>${build.durationString}</TD></TR>
    </TABLE>
    <BR/>
     
     
    <!-- CHANGE SET -->
     
    <j:set var="changeSet" value="${build.changeSet}" />
    <j:if test="${changeSet!=null}">
      <j:set var="hadChanges" value="false" />
      <TABLE width="100%">
        <TR><TD class="bg1" colspan="2"><B>CHANGES</B></TD></TR>
        <j:forEach var="cs" items="${changeSet}" varStatus="loop">
          <j:set var="hadChanges" value="true" />
          <j:set var="aUser" value="${cs.hudsonUser}"/>
          <TR>
            <TD colspan="2" class="bg2">  Revision <B>${cs.commitId?:cs.revision?:cs.changeNumber}</B> by
              <B>${aUser!=null?aUser.displayName:cs.author.displayName}: </B>
              <B>(${cs.msgAnnotated})</B>
             </TD>
          </TR>
          <j:forEach var="p" items="${cs.affectedFiles}">
            <TR>
              <TD width="10%">  ${p.editType.name}</TD>
              <TD>${p.path}</TD>
            </TR>
          </j:forEach>
        </j:forEach>
        <j:if test="${!hadChanges}">
          <TR><TD colspan="2">No Changes</TD></TR>
        </j:if>
      </TABLE>
    <BR/>
    </j:if>
     
     
    <!-- ARTIFACTS -->
     
    <j:set var="artifacts" value="${build.artifacts}" />
    <j:if test="${artifacts!=null and artifacts.size()>0}">
      <TABLE width="100%">
        <TR><TD class="bg1"><B>BUILD ARTIFACTS</B></TD></TR>
        <TR>
          <TD>
            <j:forEach var="f" items="${artifacts}">
          	  <li>
          	    <a href="${rooturl}${build.url}artifact/${f}">${f}</a>
          	  </li>
          	</j:forEach>
          </TD>
        </TR>
      </TABLE>
    <BR/>  
    </j:if>
     
     
    <!-- MAVEN ARTIFACTS -->
     
    <j:set var="mbuilds" value="${build.moduleBuilds}" />
    <j:if test="${mbuilds!=null}">
      <TABLE width="100%">
          <TR><TD class="bg1"><B>BUILD ARTIFACTS</B></TD></TR>
          <j:forEach var="m" items="${mbuilds}">
            <TR><TD class="bg2"><B>${m.key.displayName}</B></TD></TR>
            <j:forEach var="mvnbld" items="${m.value}">
            <j:set var="artifacts" value="${mvnbld.artifacts}" />
            <j:if test="${artifacts!=null and artifacts.size()>0}">
          <TR>
            <TD>
          	  <j:forEach var="f" items="${artifacts}">
          	    <li>
          	      <a href="${rooturl}${mvnbld.url}artifact/${f}">${f}</a>
          	    </li>
          	  </j:forEach>
          	</TD>
          </TR>
            </j:if>
            </j:forEach>
          </j:forEach>
      </TABLE>
    <BR/>  
    </j:if>
     
     
    <!-- JUnit TEMPLATE -->
     
    <j:set var="junitResultList" value="${it.JUnitTestResult}" />
    <j:if test="${junitResultList.isEmpty()!=true}">
      <TABLE width="100%">
        <TR><TD class="bg1" colspan="2"><B>JUnit Tests</B></TD></TR>
        <j:forEach var="junitResult" items="${it.JUnitTestResult}">
          <j:forEach var="packageResult" items="${junitResult.getChildren()}">
            <TR><TD class="bg2" colspan="2"> Name: ${packageResult.getName()} Failed: ${packageResult.getFailCount()} test(s), Passed: ${packageResult.getPassCount()} test(s), Skipped: ${packageResult.getSkipCount()} test(s), Total: ${packageResult.getPassCount()+packageResult.getFailCount()+packageResult.getSkipCount()} test(s)</TD></TR>
            <j:forEach var="test" items="${packageResult.getPassedTests()}">
              <j:if test="${test.status == 'FIXED'}">
                <TR bgcolor="white"><TD class="test_passed" colspan="2"><B><li>Fixed: ${test.getFullName()} (${test.getAge()})</li></B></TD></TR>
              </j:if>
            </j:forEach>
            <j:forEach var="failed_test" items="${packageResult.getFailedTests()}">
              <TR bgcolor="white"><TD class="test_failed" colspan="2"><B><li>Failed: ${failed_test.getFullName()} (${failed_test.getAge()})</li></B></TD></TR>
            </j:forEach>
          </j:forEach> 
        </j:forEach>  
      </TABLE>	
    <BR/>
    </j:if>
     
     
    <!-- COBERTURA TEMPLATE -->
     
    <j:set var="coberturaAction" value="${it.coberturaAction}" />
    <j:if test="${coberturaAction!=null}">
      <j:set var="coberturaResult" value="${coberturaAction.result}" />
      <j:if test="${coberturaResult!=null}">
      	<table width="100%"><TD class="bg1" colspan="2"><B>Cobertura Report</B></TD></table>
    	<table width="100%"><TD class="bg2" colspan="2"><B>Project Coverage Summary</B></TD></table>
                <table border="1px" class="pane">
                    <tr>
                        <td>Name</td>
                        <j:forEach var="metric" items="${coberturaResult.metrics}">
                            <td>${metric.name}</td>
                        </j:forEach>
                    </tr>
                    <tr>
                        <td>${coberturaResult.name}</td>
                        <j:forEach var="metric" items="${coberturaResult.metrics}">
                            <td data="${coberturaResult.getCoverage(metric).percentageFloat}">${coberturaResult.getCoverage(metric).percentage}%
                                (${coberturaResult.getCoverage(metric)})
                            </td>
                        </j:forEach>
                    </tr>
                </table>
     
                <j:if test="${coberturaResult.sourceCodeLevel}">
                    <h2>Source</h2>
                    <j:choose>
                        <j:when test="${coberturaResult.sourceFileAvailable}">
                            <div style="overflow-x:scroll;">
                                <table class="source">
                                    <thead>
                                        <tr>
                                            <th colspan="3">${coberturaResult.relativeSourcePath}</th>
                                        </tr>
                                    </thead>
                                    ${coberturaResult.sourceFileContent}
     
                                </table>
                            </div>
                        </j:when>
                        <j:otherwise>
                            <p>
                                <i>Source code is unavailable</i>
                            </p>
                        </j:otherwise>
                    </j:choose>
                </j:if>
     
                <j:forEach var="element" items="${coberturaResult.childElements}">
                    <j:set var="childMetrics" value="${coberturaResult.getChildMetrics(element)}"/>
                   <table width="100%"><TD class="bg2" colspan="2">Coverage Breakdown by ${element.displayName}</TD></table>
                    <table border="1px" class="pane sortable">
                        <tr>
                            <td>Name</td>
                            <j:forEach var="metric" items="${childMetrics}">
                                <td>${metric.name}</td>
                            </j:forEach>
                        </tr>
                        <j:forEach var="c" items="${coberturaResult.children}">
                            <j:set var="child" value="${coberturaResult.getChild(c)}"/>
                            <tr>
     
                                <td>
                                    ${child.xmlTransform(child.name)}
                                </td>
                                <j:forEach var="metric" items="${childMetrics}">
                                    <j:set var="childResult" value="${child.getCoverage(metric)}"/>
                                    <j:choose>
                                        <j:when test="${childResult!=null}">
                                            <td data="${childResult.percentageFloat}">${childResult.percentage}%
                                                (${childResult})
                                            </td>
                                        </j:when>
                                        <j:otherwise>
                                            <td data="101">N/A</td>
                                        </j:otherwise>
                                    </j:choose>
                                </j:forEach>
                            </tr>
                        </j:forEach>
                    </table>
                </j:forEach>
      </j:if>
    <BR/>
    </j:if>
     
     
    <!-- CONSOLE OUTPUT -->
     
    <j:getStatic var="resultFailure" field="FAILURE" className="hudson.model.Result"/>
    <j:if test="${build.result==resultFailure}">
    <TABLE width="100%" cellpadding="0" cellspacing="0">
    <TR><TD class="bg1"><B>CONSOLE OUTPUT</B></TD></TR>
    <j:forEach var="line" items="${build.getLog(100)}"><TR><TD class="console">${line}</TD></TR></j:forEach>
    </TABLE>
    <BR/>
    </j:if>
     
    </BODY>
    </j:jelly>
    

    4.groovy模板

    <STYLE>
    BODY, TABLE, TD, TH, P {
      font-family:Verdana,Helvetica,sans serif;
      font-size:11px;
      color:black;
    }
    h1 { color:black; }
    h2 { color:black; }
    h3 { color:black; }
    TD.bg1 { color:white; background-color:#0000C0; font-size:120% }
    TD.bg2 { color:white; background-color:#4040FF; font-size:110% }
    TD.bg3 { color:white; background-color:#8080FF; }
    TD.test_passed { color:blue; }
    TD.test_failed { color:red; }
    TD.console { font-family:Courier New; }
    </STYLE>
    <BODY>
    
    <TABLE>
      <TR><TD align="right"><IMG SRC="${rooturl}static/e59dfe28/images/32x32/<%= (build.result == null || build.result.toString() == 'SUCCESS') ? "blue.gif" : build.result.toString() == 'FAILURE' ? 'red.gif' : 'yellow.gif' %>" />
      </TD><TD valign="center"><B style="font-size: 200%;">BUILD ${build.result ?: 'SUCCESSFUL'}</B></TD></TR>
      <TR><TD>URL</TD><TD><A href="${rooturl}${build.url}">${rooturl}${build.url}</A></TD></TR>
      <TR><TD>Project:</TD><TD>${project.name}</TD></TR>
      <TR><TD>Date:</TD><TD>${it.timestampString}</TD></TR>
      <TR><TD>Duration:</TD><TD>${build.durationString}</TD></TR>
      <TR><TD>Cause:</TD><TD><% build.causes.each() { cause -> %> ${cause.shortDescription} <%  } %></TD></TR>
      <tr>
                <td>
                    <ul>
    
    
                    </ul>
                </td>
      </tr>
    </TABLE>
    <BR/>
    
    <!-- CHANGE SET -->
    <% def changeSets = build.changeSets
    if(changeSets != null) {
        def hadChanges = false %>
        <TABLE width="100%">
        <TR><TD class="bg1" colspan="2"><B>CHANGES</B></TD></TR>
    
    <%  changeSets.each() { cs_list ->
          cs_list.each() { cs ->
              hadChanges = true %>
            <TR>
              <TD colspan="2" class="bg2">&nbsp;&nbsp;Revision <B><%= cs.metaClass.hasProperty('commitId') ? cs.commitId : cs.metaClass.hasProperty('revision') ? cs.revision :
              cs.metaClass.hasProperty('changeNumber') ? cs.changeNumber : "" %></B> by
                <B><%= cs.author %>: </B>
                <B>(${cs.msgAnnotated})</B>
               </TD>
            </TR>
    <%      cs.affectedFiles.each() { p -> %>
            <TR>
              <TD width="10%">&nbsp;&nbsp;${p.editType.name}</TD>
              <TD>${p.path}</TD>
            </TR>
    <%      }
          }
      }
    
        if(!hadChanges) { %>
            <TR><TD colspan="2">No Changes</TD></TR>
    <%  } %>
      </TABLE>
    <BR/>
    <% } %>
    
    <!-- ARTIFACTS -->
    <% def artifacts = build.artifacts
    if(artifacts != null && artifacts.size() > 0) { %>
      <TABLE width="100%">
        <TR><TD class="bg1"><B>BUILD ARTIFACTS</B></TD></TR>
        <TR>
          <TD>
    <%      artifacts.each() { f -> %>
              <li>
                <a href="${rooturl}${build.url}artifact/${f}">${f}</a>
              </li>
    <%      } %>
          </TD>
        </TR>
      </TABLE>
    <BR/>
    <% } %>
    
    <!-- MAVEN ARTIFACTS -->
    <%
    try {
      def mbuilds = build.moduleBuilds
      if(mbuilds != null) { %>
      <TABLE width="100%">
          <TR><TD class="bg1"><B>BUILD ARTIFACTS</B></TD></TR>
    <%
        try {
            mbuilds.each() { m -> %>
            <TR><TD class="bg2"><B>${m.key.displayName}</B></TD></TR>
    <%      m.value.each() { mvnbld ->
                def artifactz = mvnbld.artifacts
                if(artifactz != null && artifactz.size() > 0) { %>
          <TR>
            <TD>
    <%              artifactz.each() { f -> %>
                <li>
                  <a href="${rooturl}${mvnbld.url}artifact/${f}">${f}</a>
                </li>
    <%              } %>
            </TD>
          </TR>
    <%          }
            }
           }
        } catch(e) {
        // we don't do anything
        }  %>
      </TABLE>
    <BR/>
    <% }
    
    }catch(e) {
        // we don't do anything
    }
    %>
    
    <!-- JUnit TEMPLATE -->
    
    <% def junitResultList = it.JUnitTestResult
    try {
     def cucumberTestResultAction = it.getAction("org.jenkinsci.plugins.cucumber.jsontestsupport.CucumberTestResultAction")
     junitResultList.add(cucumberTestResultAction.getResult())
    } catch(e) {
            //cucumberTestResultAction not exist in this build
    }
    if (junitResultList.size() > 0) { %>
     <TABLE width="100%">
     <TR><TD class="bg1" colspan="2"><B>${junitResultList.first().displayName}</B></TD></TR>
     <% junitResultList.each{
      junitResult -> %>
         <% junitResult.getChildren().each { packageResult -> %>
            <TR><TD class="bg2" colspan="2"> Name: ${packageResult.getName()} Failed: ${packageResult.getFailCount()} test(s), Passed: ${packageResult.getPassCount()} test(s), Skipped: ${packageResult.getSkipCount()} test(s), Total: ${packageResult.getPassCount()+packageResult.getFailCount()+packageResult.getSkipCount()} test(s)</TD></TR>
            <% packageResult.getFailedTests().each{ failed_test -> %>
              <TR bgcolor="white"><TD class="test_failed" colspan="2"><B><li>Failed: ${failed_test.getFullName()} </li></B></TD></TR>
            <% }
          }
     } %>
     </TABLE>
     <BR/>
    <%
    } %>
    
    <!-- CONSOLE OUTPUT -->
    <% if(build.result==hudson.model.Result.FAILURE) { %>
    <TABLE width="100%" cellpadding="0" cellspacing="0">
    <TR><TD class="bg1"><B>CONSOLE OUTPUT</B></TD></TR>
     <TR><TD class="console">${jenkins.model.Jenkins.instance.getJobNames().findAll{ name -> println name }}</TD></TR>
     
    <%  build.getLog(100).each() { line -> %>
        <TR><TD class="console">${org.apache.commons.lang.StringEscapeUtils.escapeHtml(line)}</TD></TR>
    <%  } %>
    </TABLE>
    <BR/>
    <% } %>
    
    </BODY>
    
  • 相关阅读:
    【POJ
    【OpenJ_Bailian
    【Aizu
    【OpenJ_Bailian
    leetcode-746-Min Cost Climbing Stairs(动态规划)
    leetcode-744-Find Smallest Letter Greater Than Target(改进的二分查找)
    leetcode-728-Self Dividing Numbers
    leetcode-717-1-bit and 2-bit Characters
    leetcode-697-Degree of an Array
    leetcode-682-Baseball Game
  • 原文地址:https://www.cnblogs.com/amize/p/14774013.html
Copyright © 2020-2023  润新知