Java:@SpringApplicationConfiguraction和@WebIntegrationTest在Spring Boot中不能使用的解决方案

@SpringApplicationConfiguraction和@WebIntegrationTest解决方案

在Spring Boot 1.5.7 中@SpringApplicationConfiguraction和@WebIntegrationTest中不能使用了.

找了半天总算找到了解决方案.

记录如下.

java标志

源码

@SpringApplicationConfiguraction

// 用下面这个替换.

@SpringBootTest(classes = ReadingListApplication.class,webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)


// 随机服务器端口号
@WebIntegrationTest(randomPort = true)

// 使用下面这个替换:

@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)

// 获取端口.

 // 用下面这个替换. @Value("${local.server.port}")
    @LocalServerPort
    private int port;

如果在Spring Boot中使用了Spring Security,并且使用了自定义UserDetails,在测试的时候需要使用如下方式:

 @Test
    @WithUserDetails(userDetailsServiceBeanName="userDetailsCustom",value="test")
    @WithMockUser(username="test", password="test", roles="READER")
    public void homePage_authenticatedUser() throws Exception {
        Reader expectedReader = new Reader();
        expectedReader.setUsername("test");
        expectedReader.setPassword("test");
        expectedReader.setFullname("Walt Disney");

        mockMvc.perform(get("/"))
                .andExpect(status().isOk())
                .andExpect(view().name("readingList"))
                .andExpect(model().attribute("reader",
                        samePropertyValuesAs(expectedReader)))
                .andExpect(model().attribute("books", hasSize(0)))
                .andExpect(model().attribute("amazonID", "habuma-20"));
    }

//   

@Bean
    public UserDetailsService userDetailsCustom(){
       return  new UserDetailsService() {
            @Override
            public UserDetails loadUserByUsername(String username)
                    throws UsernameNotFoundException {
                // readerRepository 是个实现了JpaRepository的空接口.
                UserDetails userDetails = readerRepository.findOne(username);
                if (userDetails != null) {
                    return userDetails;
                }
                throw new UsernameNotFoundException("User '" + username + "' not found.");
            }
        };
    }

Java:使用Spring Mail发送邮件

发送邮件

本项目源码在:https://coding.net/u/pruidong/p/SpringEmailDemo/git

之前简单使用过Java Email发送邮件,但最近接触了Spring Mail组件之后,发现在之前的基础上更加方便了.本文的内容参照了:Spring Mail官方文档,以及Thymeleaf官方示例.但对部分内容进行了修改和优化,也使得发送邮件变得更加简单.

有两点需要说明的是:

  1. 本文不会贴完所有的资源,可以前往[项目地址]获取所有源码;
  2. 项目基于Maven构建,并且不需要Spring Web MVC(也就是不需要在Tomcat中运行),配置相关邮箱信息之后,直接在控制台运行即可
Spring Mail发送邮件项目结构图
Spring Mail发送邮件项目结构图

部分源码

直接使用下面的源码无法构建出完整项目,因为有部分图片、模板文件(HTML,txt)未贴出,贴出下面的代码,仅作为参考依据.完整源码可以访问项目地址

Maven依赖文件(pom.xml):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>xyz.suancaiyu</groupId>
    <artifactId>SpringMail19Demo</artifactId>
    <version>1.0-SNAPSHOT</version>


    <dependencies>
        <dependency>
            <groupId>com.sun.mail</groupId>
            <artifactId>javax.mail</artifactId>
            <version>1.6.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.3.11.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.11.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>4.3.11.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.3.11.RELEASE</version>
        </dependency>


        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf</artifactId>
            <version>3.0.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring4</artifactId>
            <version>3.0.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.9.0</version>
        </dependency>


        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.5</version>
        </dependency>


    </dependencies>


</project>

java标志

配置邮箱地址、邮箱服务器信息(base.properties):

xyz.suancaiyu.smtpServer=SMTP服务器地址(smtp.qq.com)
xyz.suancaiyu.smtpServerPort=SMTP服务器端口
xyz.suancaiyu.smtpUserName=邮箱登录名
xyz.suancaiyu.smtpUserPassword=邮箱登录密码(QQ邮箱要使用授权码)
xyz.suancaiyu.smtpFromEmail=发件人邮箱地址
xyz.suancaiyu.smtpToEmail=收件人邮箱地址

Spring的配置文件(AppInitial.java):

package xyz.suancaiyu.config;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import org.thymeleaf.templateresolver.ITemplateResolver;
import org.thymeleaf.templateresolver.StringTemplateResolver;
import xyz.suancaiyu.Constat;

import java.util.Collections;
import java.util.Properties;

/**
 * Spring 配置文件.
 *
 * Created by puruidong on 2017/9/15.
 */
@Configuration
@ComponentScan(basePackages = "xyz.suancaiyu.*")
public class AppInitial {


    @Bean
    public SimpleMailMessage templateMessage() {
        SimpleMailMessage msg = new SimpleMailMessage();
        msg.setFrom(Constat.getValue(Constat.SMTPFROMEMAIL));
        msg.setTo(Constat.getValue(Constat.SMTPTOEMAIL));
        return msg;
    }

    @Bean
    public JavaMailSenderImpl mailSender() {
        JavaMailSenderImpl jmsl = new JavaMailSenderImpl();
        jmsl.setHost(Constat.getValue(Constat.SMTPSERVER));
        jmsl.setPort(Integer.valueOf(Constat.getValue(Constat.SMTPSERVERPORT)));
        jmsl.setUsername(Constat.getValue(Constat.SMTPUSERNAME));
        jmsl.setPassword(Constat.getValue(Constat.SMTPPASSWORD));
        Properties properties = new Properties();
        properties.setProperty("mail.smtp.auth", "true");
        properties.setProperty("mail.smtp.ssl.enable", "true");
        properties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        jmsl.setJavaMailProperties(properties);
        return jmsl;
    }

    /********* Thymeleaf Email Template **************/

    @Bean
    public ResourceBundleMessageSource emailMessageSource() {
        final ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        messageSource.setBasename("mail/MailMessages");
        return messageSource;
    }


    @Bean
    public TemplateEngine emailTemplateEngine() {
        final SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        // Resolver for TEXT emails
        templateEngine.addTemplateResolver(textTemplateResolver());
        // Resolver for HTML emails (except the editable one)
        templateEngine.addTemplateResolver(htmlTemplateResolver());
        // Resolver for HTML editable emails (which will be treated as a String)
        templateEngine.addTemplateResolver(stringTemplateResolver());
        // Message source, internationalization specific to emails
        templateEngine.setTemplateEngineMessageSource(emailMessageSource());
        return templateEngine;
    }

    private ITemplateResolver textTemplateResolver() {
        final ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
        templateResolver.setOrder(Integer.valueOf(1));
        templateResolver.setResolvablePatterns(Collections.singleton("text/*"));
        templateResolver.setPrefix("/mail/");
        templateResolver.setSuffix(".txt");
        templateResolver.setTemplateMode(TemplateMode.TEXT);
        templateResolver.setCharacterEncoding(Constat.EMAIL_TEMPLATE_ENCODING);
        templateResolver.setCacheable(false);
        return templateResolver;
    }

    private ITemplateResolver htmlTemplateResolver() {
        final ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
        templateResolver.setOrder(Integer.valueOf(2));
        templateResolver.setResolvablePatterns(Collections.singleton("html/*"));
        templateResolver.setPrefix("/mail/");
        templateResolver.setSuffix(".html");
        templateResolver.setTemplateMode(TemplateMode.HTML);
        templateResolver.setCharacterEncoding(Constat.EMAIL_TEMPLATE_ENCODING);
        templateResolver.setCacheable(false);
        return templateResolver;
    }

    private ITemplateResolver stringTemplateResolver() {
        final StringTemplateResolver templateResolver = new StringTemplateResolver();
        templateResolver.setOrder(Integer.valueOf(3));
        // No resolvable pattern, will simply process as a String template everything not previously matched
        templateResolver.setTemplateMode("HTML5");
        templateResolver.setCacheable(false);
        return templateResolver;
    }

    /********* Thymeleaf Email Template END **************/


}

发送纯文本邮件(未使用模板,SendTextEmail.java):

package xyz.suancaiyu.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.stereotype.Component;

import java.time.LocalDate;

/**
 * 发送纯文本邮件.
 * <p>
 * <p>
 * Created by puruidong on 2017/9/15.
 */
@Component
public class SendTextEmail {

    @Autowired
    private SimpleMailMessage templateMessage;

    @Autowired
    private MailSender mailSender;

    public void sendEmail() {
        System.out.println("发送纯文本邮件:");
        templateMessage.setSubject("订单信息-" + LocalDate.now().toString());
        templateMessage.setText("你好,email测试. ");
        mailSender.send(templateMessage);
        System.out.println("发送成功..");
    }

}

发送带附件的邮件(SendFileEmail.java):

package xyz.suancaiyu.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import xyz.suancaiyu.Constat;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

import static xyz.suancaiyu.Constat.PNG_MIME;

/**
 * 发送邮件-带附件.
 * <p>
 * Created by puruidong on 2017/9/15.
 */
@Component
public class SendFileEmail {


    @Autowired
    private JavaMailSenderImpl mailSender;

    public void sendEmail() {
        System.out.println("发送邮件,携带附件:");
        MimeMessage message = mailSender.createMimeMessage();
        try {
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setTo(Constat.getValue(Constat.SMTPTOEMAIL));
            helper.setFrom(Constat.getValue(Constat.SMTPFROMEMAIL));
            helper.setText("订单消息-详情请查看附件");
            helper.setSubject("订单消息");
            helper.addAttachment("detail.jpg", new ClassPathResource(Constat.THYMELEAF_LOGO_IMAGE), PNG_MIME);
            mailSender.send(message);
            System.out.println("发送成功!");
        } catch (MessagingException e) {
            e.printStackTrace();
        }
    }

    public void sendHTMLEmail() {
        System.out.println("发送HTML邮件:");
        MimeMessage message = mailSender.createMimeMessage();
        try {
            MimeMessageHelper helper = new MimeMessageHelper(message, true, "GBK");
            helper.setTo(Constat.getValue(Constat.SMTPTOEMAIL));
            helper.setFrom(Constat.getValue(Constat.SMTPFROMEMAIL));
            helper.setText("<mail.html><head><META http-equiv=Content-Type content='text/mail.html; charset=GBK'> <meta charset='utf-8'/><head><body><img src='cid:identifier1234'><b>测试一个文本.</b><p style='color:red'>重要提示.</p></body></mail.html>", true);
            helper.setSubject("订单消息");
            helper.addInline("identifier1234", new ClassPathResource(Constat.THYMELEAF_LOGO_IMAGE), PNG_MIME);
            mailSender.send(message);
            System.out.println("发送成功!");
        } catch (MessagingException e) {
            e.printStackTrace();
        }


    }


}

使用Thymeleaf发送模板邮件(参照了Thymeleaf官方示例,有部分改动):

package xyz.suancaiyu.service.thymeleaf;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import xyz.suancaiyu.Constat;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.util.Arrays;
import java.util.Date;


/**
 * 使用Thymeleaf发送模板邮件.
 * 
 * Created by puruidong on 2017/9/15.
 */
@Component
public class EmailService {

    @Autowired
    private JavaMailSenderImpl mailSender;

    @Autowired
    private TemplateEngine emailTemplateEngine;

    private static final String EMAIL_TEXT_TEMPLATE_NAME = "text/email-text";
    private static final String EMAIL_SIMPLE_TEMPLATE_NAME = "html/email-simple";
    private static final String EMAIL_WITHATTACHMENT_TEMPLATE_NAME = "html/email-withattachment";
    private static final String EMAIL_INLINEIMAGE_TEMPLATE_NAME = "html/email-inlineimage";
    private static final String EMAIL_EDITABLE_TEMPLATE_CLASSPATH_RES = "html/email-editable";

    public void sendTextMail() {
        // Prepare the evaluation context
        final Context ctx = new Context();
        ctx.setVariable("name", "test123");
        ctx.setVariable("subscriptionDate", new Date());
        ctx.setVariable("hobbies", Arrays.asList("Cinema", "Sports", "Music"));

        // Prepare message using a Spring helper
        final MimeMessage mimeMessage = this.mailSender.createMimeMessage();
        final MimeMessageHelper message = new MimeMessageHelper(mimeMessage, "UTF-8");
        try {
            message.setSubject("Example plain TEXT email");
            message.setFrom(Constat.getValue(Constat.SMTPFROMEMAIL));
            message.setTo(Constat.getValue(Constat.SMTPTOEMAIL));

            // Create the plain TEXT body using Thymeleaf
            final String textContent = emailTemplateEngine.process(EMAIL_TEXT_TEMPLATE_NAME, ctx);
            message.setText(textContent);

            // Send email
            mailSender.send(mimeMessage);
        } catch (MessagingException e) {
            e.printStackTrace();
        }
    }

    /*
     * Send HTML mail (simple)
     */
    public void sendSimpleMail() {

        // Prepare the evaluation context
        final Context ctx = new Context();
        ctx.setVariable("name", "13343sdsxvbn");
        ctx.setVariable("subscriptionDate", new Date());
        ctx.setVariable("hobbies", Arrays.asList("Cinema", "Sports", "Music"));

        // Prepare message using a Spring helper
        final MimeMessage mimeMessage = this.mailSender.createMimeMessage();
        final MimeMessageHelper message = new MimeMessageHelper(mimeMessage, "UTF-8");
        try {
            message.setSubject("Example HTML email (simple)");
            message.setFrom(Constat.getValue(Constat.SMTPFROMEMAIL));
            message.setTo(Constat.getValue(Constat.SMTPTOEMAIL));

            // Create the HTML body using Thymeleaf
            final String htmlContent = emailTemplateEngine.process(EMAIL_SIMPLE_TEMPLATE_NAME, ctx);
            message.setText(htmlContent, true /* isHtml */);

            // Send email
            this.mailSender.send(mimeMessage);
        } catch (MessagingException e) {
            e.printStackTrace();
        }

    }


    public void sendMailWithInline() {
        final Context ctx = new Context();
        ctx.setVariable("name", "testlocal");
        ctx.setVariable("subscriptionDate", new Date());
        ctx.setVariable("hobbies", Arrays.asList("Cinema", "Sports", "Music"));
        ctx.setVariable("imageResourceName", "identifier1234"); // so that we can reference it from HTML

        final MimeMessage mimeMessage = mailSender.createMimeMessage();
        try {
            final MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
            helper.setSubject("Thymeleaf模板邮件");
            helper.setFrom(Constat.getValue(Constat.SMTPFROMEMAIL));
            helper.setTo(Constat.getValue(Constat.SMTPTOEMAIL));
            final String htmlContent = emailTemplateEngine.process(EMAIL_INLINEIMAGE_TEMPLATE_NAME, ctx);
            helper.setText(htmlContent, true);

            helper.addInline("identifier1234", new ClassPathResource(Constat.THYMELEAF_LOGO_IMAGE), Constat.PNG_MIME);
            mailSender.send(mimeMessage);
        } catch (MessagingException e) {
            e.printStackTrace();
        }
    }


    /*
     * Send HTML mail with inline image
     */
    public void sendEditableMail() {
        try {
            // Prepare message using a Spring helper
            final MimeMessage mimeMessage = mailSender.createMimeMessage();
            final MimeMessageHelper message
                    = new MimeMessageHelper(mimeMessage, true /* multipart */, "UTF-8");
            message.setSubject("Example editable HTML email");
            message.setFrom(Constat.getValue(Constat.SMTPFROMEMAIL));
            message.setTo(Constat.getValue(Constat.SMTPTOEMAIL));

            // Prepare the evaluation context
            final Context ctx = new Context();
            ctx.setVariable("name", "fdsafdsadsaork11233");
            ctx.setVariable("subscriptionDate", new Date());
            ctx.setVariable("hobbies", Arrays.asList("Cinema", "Sports", "Music"));

            // Create the HTML body using Thymeleaf
            final String output = emailTemplateEngine.process(EMAIL_EDITABLE_TEMPLATE_CLASSPATH_RES, ctx);
            message.setText(output, true /* isHtml */);

            // Add the inline images, referenced from the HTML code as "cid:image-name"
            message.addInline("background", new ClassPathResource(Constat.BACKGROUND_IMAGE), Constat.PNG_MIME);
            message.addInline("logo-background", new ClassPathResource(Constat.LOGO_BACKGROUND_IMAGE), Constat.PNG_MIME);
            message.addInline("thymeleaf-banner", new ClassPathResource(Constat.THYMELEAF_BANNER_IMAGE), Constat.PNG_MIME);
            message.addInline("thymeleaf-logo", new ClassPathResource(Constat.THYMELEAF_LOGO_IMAGE), Constat.PNG_MIME);

            // Send mail
            mailSender.send(mimeMessage);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

运行测试类(Main.java):

package xyz.suancaiyu.main;


import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import xyz.suancaiyu.config.AppInitial;
import xyz.suancaiyu.service.SendFileEmail;
import xyz.suancaiyu.service.SendTextEmail;
import xyz.suancaiyu.service.thymeleaf.EmailService;

/**
 * 使用Spring mail发送邮件.
 * <p>
 * <p>
 * <p>
 * 可能出现的问题:
 * <p>
 * <p>
 * 1.增加验证,否则会报:553 authentication is required 的错误信息
 * Properties prop = new Properties();
 * prop.setProperty("mail.smtp.auth", "true");
 * JavaMailSenderImpl.setJavaMailProperties(prop);
 * <p>
 * 2.当邮件内容是HTML语言时的中文问题:
 * 初始化MimeMessageHelper辅助类时,设置"GBK" encoding!如:
 * MimeMessageHelper messageHelp = new MimeMessageHelper(message,true,"GBK");
 * 同时在设置:<META http-equiv=Content-Type content='text/mail.html; charset=GBK'>
 * 如果都设置为"UTF-8",在某些邮件客户端标题不能正常显示!
 * <p>
 * 3.邮件附件的中文问题!
 * spring的文档里面说MimeMessageHelper设置了encoding,同时对title,text,attach产生作用,但还是会出问题:
 * 解决方法:MimeUtility.encodeWord(file.getName());就OK了!
 * <p>
 * Created by puruidong on 2017/9/15.
 */
public class Main {

    private static final ApplicationContext ctx = new AnnotationConfigApplicationContext(AppInitial.class);

    /**
     * 发送文本邮件.
     */
    private static void sendTextEmail() {
        SendTextEmail send = ctx.getBean(SendTextEmail.class);
        send.sendEmail();
    }

    /**
     * 发送文件邮件.
     */
    private static void sendFileEmail() {
        SendFileEmail send = ctx.getBean(SendFileEmail.class);
        send.sendEmail();
        send.sendHTMLEmail();
    }

    /**
     * 使用Thymeleaf模板发送模板邮件.
     * <p>
     * 参考:https://github.com/thymeleaf/thymeleafexamples-springmail
     */
    private static void sendThymeleafEmail() {
        EmailService emailService = ctx.getBean(EmailService.class);
        emailService.sendMailWithInline();
        emailService.sendTextMail();
        emailService.sendSimpleMail();
        emailService.sendEditableMail();
    }

    public static void main(String[] args) {
        System.out.println("先配置base.properties");
        System.exit(1);
        sendThymeleafEmail();
    }
}

到此.

Java:DOM4J解析带命名空间的XML

XML解析

在Java中,XML有多种方式可以解析.但用的比较多的还是DOM4J,对于带命名空间的XML解析,DOM4J官网并没有提供例子.下面的工厂类来自网络,我只是在其中增加了几个方法.另外,下面代码基于jdk1.8.

解析所使用的XML源文件:

<CDocument
    xmlns="urn:sc-wst:v2"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:sc-wst:v2 SD.xsd">
    <id root="1.1.2" extension="xxxxslkjfkls-fdsajkdfsklalk"></id>
    <code code="C0004" displayName="xiyao" codeSystem="WS/T 445-2014" codeSystemName="xxx"></code>
    <effectiveTime value="20170911164900"></effectiveTime>
    <patient>
        <sourceid value="68417800-1"></sourceid>
        <id root="1.35" extension="xxxxas"></id>
        <id root="1.19" extension="1eeqwww"></id>
        <id root="1.11" extension="11222321112"></id>
        <id root="1.20" extension="2334557765432"></id>
        <id root="1.13" extension="21245675432"></id>
        <addr use="B">
            <houseNumber></houseNumber>
            <streetName></streetName>
            <township></township>
            <county value="DPQDSF"></county>
            <city value="SWERS"></city>
            <state value="SCSSD"></state>
            <postalCode></postalCode>
        </addr>
        <addr use="H">
            <houseNumber></houseNumber>
            <streetName></streetName>
            <township></township>
            <county></county>
            <city></city>
            <state value="SCSSD"></state>
            <postalCode></postalCode>
        </addr>
        <addr use="P">
            <houseNumber></houseNumber>
            <streetName></streetName>
            <township></township>
            <county></county>
           <city value="SWERS"></city>
            <state value="SCSSD"></state>
            <postalCode></postalCode>
        </addr>
        <item xsi:type="ST" nid="HDSD00.04.014" name="EWRU" value="DSAF"></item>
        <item xsi:type="CD" nid="HDSD00.04.020" name="SEX" value="2" codeSystem="2.3.3.4"></item>
        <item xsi:type="PQ" nid="HDSD00.04.017" name="SDFDS" unit="FDSAFADS" value="2"></item>
        <item xsi:type="PQ" nid="HDSD00.04.018" name="DFSAF" unit="FDSA" value="9"></item>
        <item xsi:type="ST" nid="HDSD00.04.005" name="FSDAFSDFSAFSD" value="EKMZ"></item>
        <item xsi:type="CD" nid="HDSD00.04.029" name="DSAFDSAFASFDS" value="68417800-1" codeSystem="2.3.4.1"></item>
        <guardian use="FDSAFDSACZXCXZCXZ">
            <addr use="F">
                <houseNumber value="18"></houseNumber>
                <streetName value="fdsazds"></streetName>
                <township value="cxvzcx"></township>
                <county value="qwwrt"></county>
                <city value="cxvbcx"></city>
                <state value="vcioklx"></state>
                <postalCode value="610000"></postalCode>
            </addr>
        </guardian>
    </patient>
</CDocument>

java

源码

import org.dom4j.*;
import org.dom4j.io.SAXReader;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * DOM4J解析带命名空间的XML.
 *
 * Created by puruidong on 2017/9/15.
 */
public class Main {

    public static void main(String[] args) throws DocumentException {
        Dom4jFactory df = new Dom4jFactory("E:\\test.xml");
        df.getAllElement();
    }

}


/**
 * 解析工厂类.
 *
 * 来自网络.
 * 增加了几个方法.
 *
 */
class Dom4jFactory {
    private SAXReader reader = new SAXReader();
    private Document document;
    private static Element root;
    private static Map<String, String> xmlMap = new HashMap<>();

    public Dom4jFactory(String path) {
        super();
        try {
            document = reader.read(path);
            root = document.getRootElement();
            String defaultNamespace = root.getNamespaceURI();
            xmlMap.put("default", defaultNamespace);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    /**
     * 递归获取节点数据.
     *
     *
     * @param elementList
     */
    public static void element(List<Element> elementList){
        if(elementList.size()==0){
            return ;
        }
        elementList.forEach(e->{
            List<Attribute> lists = e.attributes(); // 获取节点的属性.
            attribute(lists); // 遍历属性.
            element(e.elements()); // 递归调用.
        });
    }

    /**
     * 遍历属性数据.
     *
     *
     * @param attributes
     */
    public static void attribute(List<Attribute> attributes){
        attributes.forEach(x-> System.out.print(x.getQualifiedName()+"--"+":"+x.getName()+"--->"+x.getValue()+","));
        System.out.println("");
    }

    /**
     * 获取所有节点的值.
     *
     *
     * @throws DocumentException
     */
    public static void getAllElement() throws DocumentException {
        for (Iterator<Element> it = root.elementIterator(); it.hasNext();) {
            while(it.hasNext()){  // 循环获取根节点下面的节点.
                Element element = it.next(); // 获取节点.
                attribute(element.attributes()); // 获取本节点的属性.
                element(element.elements()); // 获取子节点(递归调用.)
            }
        }
    }

    /**
     * 获取指定节点.
     *
     *
     * @param arg0
     * @return
     */
    public static List<?> getSelectNodes(String arg0) {
        XPath selector = root.createXPath("//default:" + arg0);
        selector.setNamespaceURIs(xmlMap);
        return selector.selectNodes(root);
    }

    /**
     * 获取第一个节点.
     *
     * @param arg0
     * @param <T>
     * @return
     */
    public <T> T getSelectObject(String arg0){
        List<?> selectNodes = getSelectNodes(arg0);
        if(selectNodes.size()==1){
            return (T) selectNodes.get(0);
        }else{
            return null;
        }
    }
}

Vue:切换class模拟实现tab

实现个切换

其实就是翻译了jQuery的removeClass和addClass,只是在Vue里面使用了变量去切换.

vuejs logo

运行效果

vuejs tab 运行效果

源码

源码比较简单,引用了bootcss的cdn服务.

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="utf-8" />
    <title>首页</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <script src="https://cdn.bootcss.com/vue/2.4.2/vue.min.js"></script>
    <style>
       

        .Grid {
            display: flex;
        }

        .Grid-cell {
            flex: 1;
            text-align: center;
        }

   

        .bottomActive{
            background-color: #00ff00;
        }

        .Grid .Grid-cell {
            padding:5px;
            cursor: pointer;
        }
    </style>
</head>

<body>
<div id="app">
    
            <div class="Grid">
                <div :class="[[{'bottomActive':1==bottomactive},'Grid-cell']]" @click="bottomMenuClick(1)"> 
                    <div>第一个</div>
                </div>
                <div :class="[{'bottomActive':2==bottomactive},'Grid-cell']" @click="bottomMenuClick(2)">
                    <div>第二个</div>
                </div>
                <div :class="[{'bottomActive':3==bottomactive},'Grid-cell']" @click="bottomMenuClick(3)">
                    <div>第三个</div>
                </div>
            </div>


    </div>
    <script>
    var vue = new Vue({
        el:"#app",
        data:{
            bottomactive:1
        },
        methods:{
            bottomMenuClick:function(index){
                console.log("index:"+index);
                this.bottomactive=index;
            }
        }
    })

    </script>
</body>

</html>