参考:http://cxf.apache.org/javadoc/latest/
https://www.cnblogs.com/cac2020/p/5975473.html
https://blog.csdn.net/elim168/article/details/72356346
一、用途
CXF拦截器可以直接访问和修改sope消息,它可用于WS请求响应中的权限验证、日志记录,Soap消息处理,消息的压缩处理等。
二、CXF拦截器概要
先介绍几个比较重要的概念:拦截器类型、拦截阶段、拦截器链、全局拦截器、局部拦截器、捆绑拦截器。
2.1 拦截器类型:指定啥时候拦截
Name | Value |
inInterceptors | 入拦截器,拦截接收到的消息 |
inFaultInterceptors | 入出错拦截器,拦截接收错误消息 |
outInterceptors | 出拦截器,拦截发出去的消息 |
outFaultInterceptors | 出出错拦截器,拦截发出去的错误消息 |
2.2 拦截阶段(phase):
指定在什么时候起作用,在自定义拦截器中的构造方法中调用父类构造方发指定,以下是它的参数。在org.apache.cxf.phase.Phase可看到。(不同颜色只是方便区分不同前缀)
INVOKE |
MARSHAL |
MARSHAL_ENDING |
POST_INVOKE |
POST_LOGICAL |
POST_LOGICAL_ENDING |
POST_MARSHAL |
POST_PROTOCOL |
POST_PROTOCOL_ENDING |
POST_STREAM |
POST_STREAM_ENDING |
POST_UNMARSHAL |
PRE_INVOKE |
PRE_LOGICAL |
PRE_LOGICAL_ENDING |
PRE_MARSHAL |
PRE_PROTOCOL |
PRE_PROTOCOL_ENDING |
PRE_PROTOCOL_FRONTEND |
PRE_STREAM |
PRE_STREAM_ENDING |
PRE_UNMARSHAL |
PREPARE_SEND |
PREPARE_SEND_ENDING |
PROTOCOL |
READ |
RECEIVE |
SEND |
SEND_ENDING |
SETUP |
SETUP_ENDING |
UNMARSHAL |
USER_LOGICAL |
USER_LOGICAL_ENDING |
USER_PROTOCOL |
USER_PROTOCOL_ENDING |
USER_STREAM |
USER_STREAM_ENDING |
WRITE |
WRITE_ENDING |
使用方式:自定义拦截器中的构造方法中调用父类构造方发指定
public class LoggerInInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
public LoggerInInterceptor() {
super(Phase.RECEIVE);
}
public LoggerInInterceptor(String phase) {
super(phase);
}
……………………
}
注意:可以把拦截器类型理解为大的拦截阶段,拦截阶段理解成具体的小的阶段。当配置中出现inInterceptors时做outInterceptors时做的事就打印不出来日志。比如outInterceptors时候做RECEIVE
2.3 拦截器链:
拦截器链由若干拦截器组成,处理消息时Cxf会让对应的消息被拦截器链里面的每一个拦截器都执行一遍,执行顺序由拦截器中指定的phase确定。Cxf在正常调用InterceptorChain的时候会调用其中包含的Interceptor的handleMessage方法,当调用某一个Interceptor出错时,将依次回调已经回调过的Interceptor的handleFault方法。
Cxf中定义了一个接口InterceptorProvider,通过该接口可以获取到与当前对象绑定的拦截器链里面的所有拦截器,当我们需要往某对象现有的拦截器链里面添加拦截器的时候我们就可以往通过InterceptorProvider获取到的对应拦截器列表添加相应的拦截器来实现。当然比较方便的是通过xml配置文件,配置时是通过指定拦截点和拦截器的bean对象来添加。
package org.apache.cxf.interceptor;
public interface InterceptorProvider {
List<Interceptor<? extends Message>> getInInterceptors();
List<Interceptor<? extends Message>> getOutInterceptors();
List<Interceptor<? extends Message>> getInFaultInterceptors();
List<Interceptor<? extends Message>> getOutFaultInterceptors();
}
2.4 全局拦截器:
当某些拦截器需要让它作用在全局时,就使用<cxf:bus>的方式配置。配置方式如下:
<cxf:bus>
<cxf:properties>
<entry key="bus.io.CachedOutputStream.Threshold" value="10485760"/>
</cxf:properties>
<cxf:inInterceptors>
<ref bean="loggerInInterceptor"/>
</cxf:inInterceptors>
<cxf:outInterceptors>
<ref bean="loggerOutInterceptor"/>
</cxf:outInterceptors>
</cxf:bus>
2.5 局部拦截器:
针对一些接口需要的特殊拦截器做配置使用(服务端配置为例)
<bean id="weatherServiceImpl" class="com.whz.impl.WeatherServiceImpl"/>
<jaxws:server address="/WeatherService" serviceClass="com.whz.IWeatherService">
<jaxws:serviceBean>
<ref bean="weatherServiceImpl"/>
</jaxws:serviceBean>
<!--入拦截器-->
<jaxws:inInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
</jaxws:inInterceptors>
<!--出拦截器-->
<jaxws:outInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
</jaxws:outInterceptors>
<!--入出错拦截器-->
<jaxws:inFaultInterceptors>
<bean class="XXX"/>
</jaxws:inFaultInterceptors>
<!--出出错拦截器-->
<jaxws:outFaultInterceptors>
<bean class="XXX"/>
</jaxws:outFaultInterceptors>
</jaxws:server>
2.6 捆绑拦截器
当有多个拦截器需要同时使用时,可将多个拦截器捆绑在一起使用。这样就可以不用挨个去注册拦截器。 实现拦截器的捆绑过程非常简单,只需要继承AbstractFeature 类来实现一个新的特征,覆盖initializeProvider 方法,然后将该feature注册即可。
1、先来定义一个捆绑拦截器类:
public class InOutInterceptorFeature extends AbstractFeature {
@Override
protected void initializeProvider(InterceptorProvider provider, Bus bus) {
/* 将多个拦截器添加到InterceptorProvider中即可,添加不管先后顺序,只需要注意到是添加到哪个拦截点即可 */
provider.getOutInterceptors().add(new LoggerOutInterceptor());
provider.getInInterceptors().add(new LoggerInInterceptor());
}
}
2、再将该feature注册到服务中(服务端配置为例):
<jaxws:server address="/WeatherService" serviceClass="com.whz.IWeatherService">
<jaxws:serviceBean>
<ref bean="weatherServiceImpl"/>
</jaxws:serviceBean>
<jaxws:features>
<bean class="com.whz.datacenter.server.interceptor.InOutInterceptorFeature"/>
</jaxws:features>
</jaxws:server>
三、运用实例之服务端
- 定义拦截器处理器接口
package com.lord.datacenter.server.interceptor.handler; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.interceptor.Fault; /** * @author weihongzhou * @date 2019/11/12 */ public interface IInterceptorHandler { String getPhase(); void setPhase(String var1); void handleMessage(SoapMessage var1) throws Fault; }
- 定义抽象类,拦截器处理器
package com.lord.datacenter.server.interceptor.handler; /** * @author weihongzhou * @date 2019/11/12 */ public abstract class AbstractInterceptorHandler implements IInterceptorHandler { private String phase; public AbstractInterceptorHandler(String phase) { this.phase = phase; } @Override public String getPhase() { return this.phase; } @Override public void setPhase(String phase) { this.phase = phase; } }
- 1)定义默认输入拦截器处理器类
2)定义默认输出拦截器处理器类package com.lord.datacenter.server.interceptor.handler; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.helpers.IOUtils; import org.apache.cxf.interceptor.Fault; import org.apache.cxf.message.Exchange; import org.apache.cxf.phase.Phase; import org.apache.cxf.service.Service; import org.eclipse.jetty.util.StringUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author weihongzhou * @date 2019/11/12 */ public class DefaultLoggerInInterceptorHandler extends AbstractInterceptorHandler { private static final Logger log = LoggerFactory.getLogger(DefaultLoggerInInterceptorHandler.class); /** * 接收到请求时处理 */ public DefaultLoggerInInterceptorHandler() { super(Phase.RECEIVE); } public DefaultLoggerInInterceptorHandler(String phase) { super(phase); } @Override public void handleMessage(SoapMessage message) throws Fault { if ("receive".equals(this.getPhase())) { String ms = ""; try { ms = this.getMessage(message); } catch (Exception var9) { log.error(var9.getMessage(), var9); } if (StringUtil.isBlank(ms)) { return; } // 目的是获取其他系统调用本系统的某个接口 Exchange exchange = message.getExchange(); // 获取到“交换”数据的接口 Service service = (Service)exchange.get(Service.class); // 获取到别人调用的具体接口 Class<?> cls = (Class)service.get("endpoint.class"); String interfacePath = cls.getName(); String method = this.getMethod(ms); log.info("\n调用的接口:{}.{}", interfacePath, method); log.info("\n\n=========================== in begin===========================\n {} \n===========================in end=============================\n", ms); } } private String getMessage(SoapMessage message) { // 将message中的内容放到输入流中 InputStream in = (InputStream)message.getContent(InputStream.class); String ret = ""; try { // 将输入流转化为字符串,并设置编码 ret = IOUtils.toString(in, "UTF-8"); in.close(); InputStream in1 = new ByteArrayInputStream(ret.getBytes("UTF-8")); message.setContent(InputStream.class, in1); } catch (IOException var5) { log.error(var5.getMessage(), var5); } return ret; } /** * 用正则表达式的方式从message中获取到方法名 * @param inMessage * @return */ private String getMethod(String inMessage) { String ret = ""; if (StringUtil.isBlank(inMessage)) { return ret; } else { try { Pattern pattern = Pattern.compile("<ns2:[\\s\\S]*?xmlns:ns2="); Matcher matcher = pattern.matcher(inMessage); if (matcher.find()) { ret = matcher.group(); } if (StringUtil.isBlank(ret)) { return ""; } ret = ret.split("ns2:")[1]; ret = ret.split(" xmlns")[0]; } catch (Exception var5) { log.error(var5.getMessage(), var5); } return ret; } } }
package com.lord.datacenter.server.interceptor.handler; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.helpers.IOUtils; import org.apache.cxf.interceptor.Fault; import org.apache.cxf.io.CachedOutputStream; import org.apache.cxf.phase.Phase; import org.eclipse.jetty.util.StringUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author weihongzhou * @date 2019/11/12 */ public class DefaultLoggerOutInterceptorHandler extends AbstractInterceptorHandler { private static final Logger log = LoggerFactory.getLogger(DefaultLoggerOutInterceptorHandler.class); public DefaultLoggerOutInterceptorHandler() { super(Phase.PRE_STREAM); } public DefaultLoggerOutInterceptorHandler(String phase) { super(phase); } @Override public void handleMessage(SoapMessage message) throws Fault { /** * 在流关闭之前处理 */ if ((Phase.PRE_STREAM).equals(this.getPhase())) { String ms = ""; try { // 从输出流中获取内容 OutputStream os = (OutputStream)message.getContent(OutputStream.class); CachedOutputStream cs = new CachedOutputStream(); message.setContent(OutputStream.class, cs); message.getInterceptorChain().doIntercept(message); CachedOutputStream csnew = (CachedOutputStream)message.getContent(OutputStream.class); InputStream in = csnew.getInputStream(); // 将流转换为字符串 ms = IOUtils.toString(in, "UTF-8"); IOUtils.copy(new ByteArrayInputStream(ms.getBytes("UTF-8")), os); cs.close(); os.flush(); message.setContent(OutputStream.class, os); } catch (IOException var7) { log.error(var7.getMessage(), var7); } if (StringUtil.isBlank(ms)) { return; } log.info("\n\n=========================== out begin===========================\n {} \n===========================out end=============================\n", ms); this.saveLog(message, ms); } } private void saveLog(SoapMessage message, String outMessage) { /*****/ } private String getResponseCode(String outMessage) { String ret = ""; try { Pattern pattern = Pattern.compile("<responseCode>[\\s\\S]*?</responseCode>"); for(Matcher matcher = pattern.matcher(outMessage); matcher.find(); ret = matcher.group()) { } ret = ret.split("e>")[1]; ret = ret.split("</")[0]; } catch (Exception var5) { log.error(var5.getMessage(), var5); } return ret; } private String getResponseMessage(String outMessage) { String ret = ""; try { Pattern pattern = Pattern.compile("<message>[\\s\\S]*?</message>"); for(Matcher matcher = pattern.matcher(outMessage); matcher.find(); ret = matcher.group()) { } ret = ret.split("e>")[1]; ret = ret.split("</")[0]; } catch (Exception var5) { log.error(var5.getMessage(), var5); } return ret; } }
- 1)定义输入拦截器类
2)定义输入拦截器类package com.lord.datacenter.server.interceptor; import com.lord.datacenter.server.interceptor.handler.DefaultLoggerInInterceptorHandler; import com.lord.datacenter.server.interceptor.handler.IInterceptorHandler; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.interceptor.Fault; import org.apache.cxf.phase.AbstractPhaseInterceptor; import org.apache.cxf.phase.Phase; /** * @author weihongzhou * @date 2019/11/12 */ public class LoggerInInterceptor extends AbstractPhaseInterceptor<SoapMessage> { private IInterceptorHandler handler; public LoggerInInterceptor() { super(Phase.RECEIVE); } public LoggerInInterceptor(String phase) { super(phase); } @Override public void handleMessage(SoapMessage message) throws Fault { if (this.handler == null) { this.handler = new DefaultLoggerInInterceptorHandler(this.getPhase()); } else { this.handler.setPhase(this.getPhase()); } this.handler.handleMessage(message); } public void setHandler(IInterceptorHandler handler) { this.handler = handler; } }
package com.lord.datacenter.server.interceptor; import com.lord.datacenter.server.interceptor.handler.DefaultLoggerOutInterceptorHandler; import com.lord.datacenter.server.interceptor.handler.IInterceptorHandler; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.interceptor.Fault; import org.apache.cxf.phase.AbstractPhaseInterceptor; import org.apache.cxf.phase.Phase; /** * @author weihongzhou * @date 2019/11/12 */ public class LoggerOutInterceptor extends AbstractPhaseInterceptor<SoapMessage> { private IInterceptorHandler handler; public LoggerOutInterceptor() { super(Phase.PRE_STREAM); } public LoggerOutInterceptor(String phase) { super(phase); } @Override public void handleMessage(SoapMessage message) throws Fault { // 可以不使用默认的,即自定义:指定phase+handler if (this.handler == null) { this.handler = new DefaultLoggerOutInterceptorHandler(this.getPhase()); } else { this.handler.setPhase(this.getPhase()); } this.handler.handleMessage(message); } public void setHandler(IInterceptorHandler handler) { this.handler = handler; } }
- 将输入拦截器和输出拦截器捆绑在一起
package com.lord.datacenter.server.interceptor; import org.apache.cxf.Bus; import org.apache.cxf.feature.AbstractFeature; import org.apache.cxf.interceptor.InterceptorProvider; /** * @author weihongzhou * @date 2019/11/13 */ public class InOutInterceptorFeature extends AbstractFeature { @Override protected void initializeProvider(InterceptorProvider provider, Bus bus) { /* 将多个拦截器添加到InterceptorProvider中即可,添加不管先后顺序,只需要注意到是添加到那个拦截点即可 */ provider.getOutInterceptors().add(new LoggerOutInterceptor()); provider.getInInterceptors().add(new LoggerInInterceptor()); } }
- 在spring中配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:context="http://www.springframework.org/schema/context" xmlns:cxf="http://cxf.apache.org/core" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd"> <bean id="weatherServiceImpl" class="com.lord.whz.impl.WeatherServiceImpl"/> <jaxws:server address="/WeatherService" serviceClass="com.lord.whz.IWeatherService"> <jaxws:serviceBean> <ref bean="weatherServiceImpl"/> </jaxws:serviceBean> <jaxws:features> <bean class="com.lord.datacenter.server.interceptor.InOutInterceptorFeature"/> </jaxws:features> </jaxws:server> </beans>
web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>Archetype Created Web Application</display-name>
<!-- Spring配置 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value> classpath:config/spring-config.xml</param-value>
</context-param>
<!--配置CXF的Servlet用于解析cxf发布webservice-->
<servlet>
<servlet-name>CXF</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CXF</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>characterEncoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- log4j配置文件位置 -->
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log4j.properties</param-value>
</context-param>
<!-- 利用spring来使用log4j -->
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
</web-app>
log4j.properties配置
### set log levels ###
log4j.rootLogger = DEBUG,stdout,D,E
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.Threshold = INFO
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss} %l%m%n
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = F://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =F://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
maven配置
<?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>com.wisewe.whz</groupId>
<artifactId>webservice_spring_server</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>webservice_spring_server Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<!-- spring版本号 -->
<spring.version>4.3.11.RELEASE</spring.version>
<mybatis.version>3.2.4</mybatis.version>
<slf4j.version>1.7.25</slf4j.version>
<log4j.version>1.2.14</log4j.version>
<test.vsersion>4.11</test.vsersion>
<cxf.version>3.1.14</cxf.version>
</properties>
<dependencies>
<!-- spring核心包 -->
<!-- springframe start -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- springframe end -->
<!--cxf start-->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-core</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>${cxf.version}</version>
</dependency>
<!--cxf end -->
<!--日志 start-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!--日志 end -->
</dependencies>
<build>
<finalName>webservice_spring_server</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>