`

普通springmvc项目转换为springboot项目

阅读更多

1.背景说明:近期要做一个支付网关系统,原来的网关系统买的别人的,用的技术比较老webservice,由于现在springboot比较火,关键是很好用,开箱即用,所以决定在原来系统的基础上进行改造。

2.开始动手:

原来的代码结构,如下图:



 

3.第一步,结构调整,先添加一个新的springboot模块:

从官网http://projects.spring.io/spring-boot/快速生成一个springboot示例,然后在主pom中添加一个新的module,命名为mag-spring-boot,我用的是idea,然后导入添加的模块。

新的项目代码结构图,去除了多余的模块,把相应的依赖进行整理:

 

 

4.代码配置以此替换,springmvc的配置替换。

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" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">

	<display-name>mag-facade-web</display-name>

	<context-param>
		<param-name>logbackConfigLocation</param-name>
		<param-value>file:///opt/pay/config/basis/mag-tzt/mag-logback.xml</param-value>
	</context-param>
	<context-param>
		<param-name>webAppRootKey</param-name>
		<param-value>com.netfinworks.mag</param-value>
	</context-param>
	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>0</load-on-startup>
	</servlet>
	<servlet>
	    <servlet-name>healthCheckDispatcher</servlet-name>
	    <servlet-class>com.netfinworks.common.monitor.web.servlet.HeathCheckDispatcherServlet</servlet-class>
	    <load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
	    <servlet-name>healthCheckDispatcher</servlet-name>
	    <url-pattern>/_health_check</url-pattern>
	</servlet-mapping>

	<!--param-->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:spring/applicationContext.xml</param-value>
	</context-param>
	<!-- listener -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<listener>
		<listener-class>ch.qos.logback.ext.spring.web.LogbackConfigListener</listener-class>
	</listener>

    <filter>
        <filter-name>CharacterEncodingFilter</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>
    </filter>

    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>

   dispatch-servlet的配置:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:util="http://www.springframework.org/schema/util"
	default-lazy-init="true" xmlns="http://www.springframework.org/schema/beans"
	xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:task="http://www.springframework.org/schema/task"
	xmlns:http-conf="http://cxf.apache.org/transports/http/configuration"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/util
	http://www.springframework.org/schema/util/spring-util.xsd
		http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
		http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd
		http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd"
	default-autowire="byName">

	<!-- 配置参数 -->
	<bean
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>file:///opt/pay/config/basis/mag-tzt/mag-app.properties</value>
				<value>file:///opt/pay/config/basis/mag-tzt/mag-sftp-config.properties
				</value>
			</list>
		</property>
	</bean>

	<!-- 收单网关 -->
	<bean name="/gateway/receiveOrder.do" class="com.netfinworks.mag.web.controller.RecvOrder">
		<property name="verifyService" ref="verifyService" />
		<!-- property name="notifyService" ref="notifyService" / -->
		<property name="contextUtil" ref="contextUtil" />
	</bean>
	
	<!-- 收单网关  投资通-->
	<bean name="/gateway/receiveOrderTzt.do" class="com.netfinworks.mag.web.controller.RecvOrderTzt">
		<property name="verifyService" ref="verifyService" />
		<property name="contextUtil" ref="contextUtil" />
	</bean>
	
	<bean name="/sdk_gateway/sdk_receiveOrder.do" class="com.netfinworks.mag.web.controller.SDKRecvOrder">
		<property name="verifyService" ref="verifyService" />
		<!-- property name="notifyService" ref="notifyService" / -->
		<property name="contextUtil" ref="contextUtil" />
	</bean>
	<!-- verifySign -->
	<bean name="verifyService" class="com.netfinworks.mag.web.verify.VerifyService">
		<property name="md5KeyService" ref="md5KeyService"></property>
		<property name="rsaService" ref="rsaService"></property>
		<property name="uesFacade" ref="uesFacade"></property>
	</bean>

	<bean name="md5KeyService" class="com.netfinworks.mag.web.sign.MD5KeyService">
	</bean>

	<bean name="rsaService" class="com.netfinworks.mag.web.sign.RSAService">
	</bean>

	<!-- ma -->
	<bean name="maQueryService" class="com.netfinworks.mag.ext.service.MaQueryService">
		<property name="memberFacade" ref="memberFacade" />
		<property name="accountFacade" ref="accountFacade" />
		<property name="merchantFacade" ref="merchantFacade" />
		<property name="bankAccountFacade" ref="bankAccountFacade" />
		<property name="udinghuoPartnerId" value="${udinghuo.partnerid}" />
		<property name="verifyFacade" ref="verifyFacade" />
	</bean>
	<!-- 鉴权系统 -->
	<jaxws:client id="authControlService"
		serviceClass="com.netfinworks.authsys.api.AuthControlService"
		address="${authsys.ws.url}/authControlFacadeAddress" />
	<!-- 鉴权相关 -->
	<bean name="authSysAuthControlService" class="com.netfinworks.mag.ext.service.AuthSysAuthControlService">
		<property name="authControlService" ref="authControlService" />
	</bean>
	<!--  cac卡账务中心-->
	<bean name="cacService" class="com.netfinworks.mag.ext.service.CacService">
		<property name="iBankAccountFacade" ref="iBankAccountFacade" />
	</bean>
	<jaxws:client id="iBankAccountFacade"
		serviceClass="com.netfinworks.cac.service.facade.IBankAccountFacade"
		address="${cac.ws.url}/BankAccountFacade" />
	<!-- ues -->
	<jaxws:client id="uesFacade"
		serviceClass="com.netfinworks.ues.services.UesRemoteService" address="${ma.ws.url}/UesRemoteService" />

	<!-- ma -->
	<jaxws:client id="memberFacade"
		serviceClass="com.netfinworks.ma.service.facade.IMemberFacade"
		address="${ma.ws.url}/MemberFacade" />

	<jaxws:client id="accountFacade"
		serviceClass="com.netfinworks.ma.service.facade.IAccountFacade"
		address="${ma.ws.url}/AccountFacade" />

	<jaxws:client id="merchantFacade"
		serviceClass="com.netfinworks.ma.service.facade.IMerchantFacade"
		address="${ma.ws.url}/MerchantFacade" />

	<jaxws:client id="bankAccountFacade"
		serviceClass="com.netfinworks.ma.service.facade.IBankAccountFacade"
		address="${ma.ws.url}/BankAccountFacade" />
		
	<jaxws:client id="verifyFacade"
		serviceClass="com.netfinworks.ma.service.facade.IVerifyFacade"
		address="${ma.ws.url}/VerifyFacade" />

	<!-- cashier -->
	<bean id="cashierQueryService" class="com.netfinworks.mag.ext.service.CashierQueryService">
		<property name="cashierFacade" ref="cashierFacade"></property>
	</bean>
	<jaxws:client id="cashierFacade"
		serviceClass="com.netfinworks.cashier.facade.api.CashierFacade"
		address="${cashier.ws.url}/cashierService">
	</jaxws:client>
	
	<!-- site -->
	<bean id="siteQueryService" class="com.netfinworks.mag.ext.service.SiteQueryService">
		<property name="siteFacade" ref="siteFacade"></property>
	</bean>	
	<jaxws:client id="siteFacade"
		serviceClass="com.netfinworks.site.facade.api.SiteFacade"
		address="${site.ws.url}/siteService">
	</jaxws:client>

	<!-- trade -->
	<bean id="tradeService" class="com.netfinworks.mag.ext.service.TradeService">
		<property name="tradeFacade" ref="tradeFacade"></property>
		<property name="cashierQueryService" ref="cashierQueryService"></property>
		<property name="maQueryService" ref="maQueryService"></property>
		<property name="netbankSuccessUrl" value="${netbank.success.url}"></property>
		<property name="whiteChannelCodeMap" value="${white.channel.code}"></property>
	</bean>
	<jaxws:client id="tradeFacade"
		serviceClass="com.netfinworks.tradeservice.facade.api.TradeProcessFacade"
		address="${trade.ws.url}/tradeProcessFacade">
	</jaxws:client>
	<http-conf:conduit name=".*/tradeProcessFacade">
		<http-conf:client ConnectionTimeout="25000"
			ReceiveTimeout="30000" />
	</http-conf:conduit>

	<!-- trade query -->
	<bean id="tradeQueryService" class="com.netfinworks.mag.ext.service.TradeQueryService">
		<property name="tradeQueryFacade" ref="tradeQueryFacade"></property>
	</bean>
	<jaxws:client id="tradeQueryFacade"
		serviceClass="com.netfinworks.tradeservice.facade.api.TradeQueryFacade"
		address="${trade.ws.url}/tradeQueryFacade">
	</jaxws:client>
	
	<!-- trade-site query -->
	<bean id="tradeSiteQueryService" class="com.netfinworks.mag.ext.service.TradeSiteQueryService">
		<property name="tradeSiteQueryFacade" ref="tradeSiteQueryFacade"></property>
	</bean>
	<jaxws:client id="tradeSiteQueryFacade"
		serviceClass="com.netfinworks.tradeservice.facade.api.TradeQueryFacade"
		address="${trade-query.ws.url}/tradeQueryFacade">
	</jaxws:client>
	
	<!-- acs -->
	<bean id="acsQueryService" class="com.netfinworks.mag.ext.service.AcsQueryService">
		<property name="authFacade" ref="authFacade"></property>
		<property name="merchantCofFacade" ref="merchantCofFacade"></property>
	</bean>
	<jaxws:client id="authFacade"
		serviceClass="com.netfinworks.acs.service.facade.ApiAuthorizationFacade"
		address="${acs.ws.url}/apiAuth" />
	<jaxws:client id="merchantCofFacade"
		serviceClass="com.netfinworks.acs.service.facade.MerchantConfigurationFacade"
		address="${acs.ws.url}/merchantCof" />
	<!-- 统一凭证 -->
	<bean id="voucherService" class="com.netfinworks.mag.ext.service.VoucherService">
		<property name="voucherFacade" ref="voucherFacade"></property>
	</bean>

	<jaxws:client id="voucherFacade"
		serviceClass="com.netfinworks.voucher.service.facade.VoucherFacade"
		address="${voucher.ws.url}/voucherFacade" />

	<!-- Fos -->
	<bean id="fosService" class="com.netfinworks.mag.ext.service.FosService">
		<property name="fosFacade" ref="fosFacade"></property>
		<property name="fundoutFacade" ref="fundoutFacade"></property>
		<property name="paymentFacade" ref="paymentFacade"></property>
	</bean>

	<jaxws:client id="fosFacade"
		serviceClass="com.netfinworks.fos.service.facade.WithdrawalFacade"
		address="${fos.ws.url}/WithdrawalFacade">
	</jaxws:client>
	<jaxws:client id="fundoutFacade"
		serviceClass="com.netfinworks.fos.service.facade.FundoutFacade"
		address="${fos.ws.url}/FundoutFacade">
	</jaxws:client>
	<jaxws:client id="paymentFacade"
		serviceClass="com.netfinworks.fos.service.facade.PaymentFacade"
		address="${fos.ws.url}/PaymentFacade">
	</jaxws:client>

	<!-- pfs -->
	<bean id="pfsService" class="com.netfinworks.mag.ext.service.PfsService">
		<property name="fundsControlFacade" ref="fundsControlFacade"></property>
	</bean>
	<jaxws:client id="fundsControlFacade"
		serviceClass="com.netfinworks.pfs.service.payment.FundsControlFacade"
		address="${pfs-payment.ws.url}/fundsControlFacade">
	</jaxws:client>
	
	<bean id="cardBinValidateService" class="com.netfinworks.mag.ext.service.CardBinValidateService">
        <property name="cardBinValidateFacade" ref="cardBinValidateFacade"></property>
    </bean>
    <jaxws:client id="cardBinValidateFacade"
        serviceClass="com.netfinworks.pfs.service.basis.cardbin.CardBinValidateFacade"
        address="${pfs-basis.ws.url}/cardBinValidateService">
    </jaxws:client>
    
    <bean id="bankInfoService" class="com.netfinworks.mag.ext.service.BankInfoService">
        <property name="bankInfoFacade" ref="bankInfoFacade"></property>
    </bean>
    <jaxws:client id="bankInfoFacade"
        serviceClass="com.netfinworks.pfs.service.manager.basis.baseinfo.BankInfoFacade"
        address="${pfs-manager.ws.url}/bankInfoService">
    </jaxws:client>
    
    <bean id="branchQueryService" class="com.netfinworks.mag.ext.service.BranchQueryService">
        <property name="branchQueryFacade" ref="branchQueryFacade"></property>
    </bean>
    <jaxws:client id="branchQueryFacade"
        serviceClass="com.netfinworks.pfs.service.basis.branchinfo.BranchQueryFacade"
        address="${pfs-basis.ws.url}/branchQueryService">
    </jaxws:client>
    

	<!-- sars -->
	<bean id="sarsService" class="com.netfinworks.mag.ext.service.SarsService">
		<property name="sarsClientService" ref="sarsClientService"></property>
	</bean>
	<bean name="sarsEngineContext" id="sarsEngineContext"
		class="com.netfinworks.sars.rules.engine.EngineContext">
		<property name="checkPoints">
			<util:list>
				<value>CP101</value>
			</util:list>
		</property>

		<property name="ruleServerWSDL" value="${sars.address}/PolicyRemoteService?wsdl" />

		<property name="sarsServerWsdl" value="${sars.address}/RmsRemoteService?wsdl" />

		<!-- Sars server MQ conf -->
		<property name="sarsServerMqEnvironment">
			<props>
				<prop key="java.naming.factory.initial">${netfinworksmq.java.naming.factory.initial}</prop>
				<prop key="java.naming.provider.url">${netfinworksmq.java.naming.provider.url}</prop>
				<prop key="java.naming.security.principal">${netfinworksmq.java.naming.security.principal}
				</prop>
				<prop key="java.naming.security.credentials">${netfinworksmq.java.naming.security.credentials}
				</prop>
			</props>
		</property>
		<property name="sarsServerMqDestination" value="${jms.sars.server.destination}" />

		<!-- Sars client Venus conf -->

	</bean>
	<bean id="sarsClientService" class="com.netfinworks.sars.client.api.SarsServiceFactory"
		factory-method="newSarsService">
		<constructor-arg ref="sarsEngineContext" />
	</bean>
	<jaxws:client id="uesRemoteService"
		serviceClass="com.netfinworks.ues.services.UesRemoteService" address="${ues.ws.url}/UesRemoteService" />
	<bean id="uesClient" class="com.netfinworks.ues.UesClient">
		<property name="uesRemoteService" ref="uesRemoteService" />
	</bean>
	<bean class="com.netfinworks.mag.ext.service.UesService" name="uesService"
		id="uesService">
		<property name="uesClient" ref="uesClient"></property>
	</bean>


	<!-- service route -->
	<bean name="serviceBase" class="com.netfinworks.mag.service.base.MagServiceBase">
		<property name="maQueryService" ref="maQueryService"></property>
		<property name="voucherService" ref="voucherService"></property>
		<property name="tradeService" ref="tradeService"></property>
		<property name="cashierQueryService" ref="cashierQueryService"></property>
		<property name="tradeQueryService" ref="tradeQueryService"></property>
		<property name="authSysAuthControlService" ref="authSysAuthControlService"></property>
		<property name="sarsService" ref="sarsService"></property>
		<property name="cacService" ref="cacService"></property>
		<property name="acsQueryService" ref="acsQueryService"></property>
		<property name="uesService" ref="uesService"></property>
	</bean>
	
	<bean id="sftpService" class="com.netfinworks.mag.ext.service.SftpService">
		<property name="sftpHost" value="${sftp.host}" />
		<property name="sftpPort" value="${sftp.port}" />
		<property name="sftpUserName" value="${sftp.username}" />
		<property name="sftpPassword" value="${sftp.password}" />
		<property name="sftpRootDir" value="${sftp.rootdir}" />
	</bean>

	<!-- add by niubl 20160325 start 新增收单网关接口 -->
	<bean
		class="com.netfinworks.mag.service.route.chanpay.CJT_CreateBatchInstantTrade"></bean>
	<bean
		class="com.netfinworks.mag.service.route.chanpay.CJT_CreateInstantTrade">
		<property name="acsQueryService" ref="acsQueryService"></property>
		<property name="userId" value="${externalSettlement.chanpay.userId}" />
		<property name="pid" value="${externalSettlement.chanpay.PID}" />
		<property name="accountType" value="${externalSettlement.chanpay.accountType}" />
	</bean>
	<bean
		class="com.netfinworks.mag.service.route.chanpay.CJT_CreateWapBatchInstantTrade"></bean>
	<bean
		class="com.netfinworks.mag.service.route.chanpay.CJT_CreateWapInstantTrade"></bean>
	<bean class="com.netfinworks.mag.service.route.chanpay.CJT_CreateRefund"></bean>
	<bean class="com.netfinworks.mag.service.route.chanpay.CJT_EveryDayTradeFile">
		<property name="sftpService" ref="sftpService" />
	</bean>
	<bean class="com.netfinworks.mag.service.route.chanpay.CJT_FeeTradeFile">
		<property name="sftpService" ref="sftpService" />
	</bean>
	<bean class="com.netfinworks.mag.service.route.chanpay.CJT_RefundTradeFile">
		<property name="sftpService" ref="sftpService" />
	</bean>
	<bean class="com.netfinworks.mag.service.route.chanpay.CJT_EveryDayTradeOwnFile">
		<property name="sftpService" ref="sftpService" />
	</bean>
	<bean class="com.netfinworks.mag.service.route.chanpay.CJT_FeeTradeOwnFile">
		<property name="sftpService" ref="sftpService" />
	</bean>
	<bean class="com.netfinworks.mag.service.route.chanpay.CJT_RefundTradeOwnFile">
		<property name="sftpService" ref="sftpService" />
	</bean>
	<bean class="com.netfinworks.mag.service.route.chanpay.CJT_MerSourceTradeOwnFile">
		<property name="sftpService" ref="sftpService" />
	</bean>
	<bean class="com.netfinworks.mag.service.route.chanpay.CJT_GetPayChannel"></bean>
	<bean
		class="com.netfinworks.mag.service.route.chanpay.CJT_MerSourceTradeFile"></bean>
	<bean class="com.netfinworks.mag.service.route.chanpay.CJT_QueryTrade">
		<property name="tradeQueryService" ref="tradeQueryService"></property>
		<property name="fosService" ref="fosService"></property>
	</bean>
	<bean
			class="com.netfinworks.mag.service.route.chanpay.CJT_SDKCreateInstantTrade"></bean>
	<bean class="com.netfinworks.mag.service.route.chanpay.CJT_ViewReceipt">
		<property name="downloadReceiptURL" value="${download.receipt.url}"></property>
	</bean>
	<bean class="com.netfinworks.mag.service.route.chanpay.CJT_PaymentToCardService">
		<property name="fosService" ref="fosService"></property>
		<property name="uesService" ref="uesService"></property>
		<property name="acsQueryService" ref="acsQueryService"></property>
	</bean>
	<bean class="com.netfinworks.mag.service.route.chanpay.CJT_GetBindingCards">
	</bean>
	<bean class="com.netfinworks.mag.service.route.chanpay.CJT_UnbindCard">
	</bean>
	<bean class="com.netfinworks.mag.service.route.chanpay.CJT_OrderWithdraw">
    </bean>
    <bean class="com.netfinworks.mag.service.route.chanpay.CJT_CreateQuickPayment">
		<property name="uesService" ref="uesService"></property>
		<property name="acsQueryService" ref="acsQueryService"></property>
    </bean>
    <bean class="com.netfinworks.mag.service.route.chanpay.CJT_QuickPaymentConfirm">
    	<property name="acsQueryService" ref="acsQueryService"></property>
    </bean>
    <bean class="com.netfinworks.mag.service.route.chanpay.CJT_WapQuickPayment">
    </bean>
    <bean class="com.netfinworks.mag.service.route.chanpay.CJT_Withdraw">
    </bean>
    <bean class="com.netfinworks.mag.service.route.chanpay.CJT_CreateSettle">
    </bean>
    <bean class="com.netfinworks.mag.service.route.chanpay.CJT_EnsureTrade">
    </bean>
    <bean class="com.netfinworks.mag.service.route.chanpay.CJT_CreateBalanceTransfer">
    </bean>
    <bean class="com.netfinworks.mag.service.route.chanpay.CJT_RealTimePaymentService">
		<property name="fosService" ref="fosService"></property>
		<property name="uesService" ref="uesService"></property>
		<property name="acsQueryService" ref="acsQueryService"></property>
    </bean>
	
	<bean class="com.netfinworks.mag.service.route.chanpay.CJT_RealTimeReceiveService">
		<property name="uesService" ref="uesService"></property>
		<property name="acsQueryService" ref="acsQueryService"></property>
    </bean>
    
    <bean class="com.netfinworks.mag.service.route.chanpay.CJT_QueryPayService">
    	<property name="tradeQueryService" ref="tradeQueryService"></property>
	</bean>
    <bean class="com.netfinworks.mag.service.route.chanpay.CJT_QuickEnsureTrade">
    </bean>
	
	<bean class="com.netfinworks.mag.service.route.chanpay.CJT_BatchRealTimePayment">
		<property name="fosService" ref="fosService"></property>
		<property name="uesService" ref="uesService"></property>
		<property name="acsQueryService" ref="acsQueryService"></property>
    </bean>
	
	<!-- add by niubl 20160325 end -->
	<bean class="com.netfinworks.mag.service.route.GetPayChannelService"></bean>
	<bean class="com.netfinworks.mag.service.route.InstantTradeService"></bean>
	<bean class="com.netfinworks.mag.service.route.InstantTradeForAppService"></bean>
	<bean class="com.netfinworks.mag.service.route.EnsureTradeService"></bean>
	<bean class="com.netfinworks.mag.service.route.BatchPayService"></bean>
	<bean class="com.netfinworks.mag.service.route.BatchPayForAppService"></bean>
	<bean class="com.netfinworks.mag.service.route.SettleService"></bean>
	<bean class="com.netfinworks.mag.service.route.RefundService"></bean>
	<bean class="com.netfinworks.mag.service.route.PrepayService"></bean>
	<bean class="com.netfinworks.mag.service.route.PrepayWithholdService"></bean>

	<bean class="com.netfinworks.mag.service.route.QueryTradeService">
		<property name="tradeQueryService" ref="tradeQueryService"></property>
	</bean>
	<bean class="com.netfinworks.mag.service.route.ChangeTradeAmountService"></bean>
	<bean class="com.netfinworks.mag.service.route.CancelTradeService"></bean>
	<bean class="com.netfinworks.mag.service.route.WithdrawalService"></bean>
	<bean class="com.netfinworks.mag.service.route.BatchWithdrawalService"></bean>
	<bean class="com.netfinworks.mag.service.route.MarginRechargeService"></bean>
	<bean class="com.netfinworks.mag.service.route.QueryMarginChangesService"></bean>
	<bean class="com.netfinworks.mag.service.route.BalanceTransferService"></bean>
	<bean class="com.netfinworks.mag.service.route.DownloadReceipt2Image">
		<property name="downloadReceiptURL" value="${download.receipt.url}"></property>
	</bean>
	<bean class="com.netfinworks.mag.service.route.PaymentToCardService">
		<property name="fosService" ref="fosService"></property>
		<property name="uesService" ref="uesService"></property>
		<property name="acsQueryService" ref="acsQueryService"></property>
	</bean>
	<bean class="com.netfinworks.mag.service.route.FrozenFundsService"></bean>
	<bean class="com.netfinworks.mag.service.route.UnfreezeFundsService"></bean>
	<bean id="contextUtil" class="com.netfinworks.mag.service.base.SpringContextUtil"></bean>
	
	<!-- 投资通新增接口bean注入 -->
	<bean class="com.netfinworks.mag.service.route.invest.AuthWithoutSmsService"></bean>
	<bean class="com.netfinworks.mag.service.route.invest.SmsAuthBindCardConfirmService"></bean>
	<bean class="com.netfinworks.mag.service.route.invest.SmsAuthBindCardService"></bean>
	<bean class="com.netfinworks.mag.service.route.invest.SmsBindCardReqService"></bean>
	<bean class="com.netfinworks.mag.service.route.invest.SmsBindCardConfirmService"></bean>
	<bean class="com.netfinworks.mag.service.route.invest.UnifiedQueryOrderService"></bean>
	<bean class="com.netfinworks.mag.service.route.invest.UrgentOrderWithdrawService"></bean>
	<bean class="com.netfinworks.mag.service.route.invest.UnifiedOrderRefundService"></bean>
	<bean class="com.netfinworks.mag.service.route.invest.AuthBindCardInfoQueryService"></bean>
	<bean class="com.netfinworks.mag.service.route.invest.SmsAuthBindCardResendService"></bean>
	<bean class="com.netfinworks.mag.service.route.invest.BindCardModifyStateService"></bean>
	
	<!-- 定时任务 -->
	<task:scheduled-tasks>
		<task:scheduled ref="acsTask" method="refresh" cron="${task.cron}" />
	</task:scheduled-tasks>

	<bean id="acsTask" class="com.netfinworks.mag.service.trigger.AcsTask">
		<property name="acsQueryService" ref="acsQueryService"></property>
	</bean>
	<!-- 
	<bean id="createStatementFileTask"
		class="com.netfinworks.mag.service.trigger.CreateStatementFileTask">
		<property name="tradeSiteQueryService" ref="tradeSiteQueryService" />
		<property name="sftpService" ref="sftpService" />
		<property name="voucherService" ref="voucherService" />
		<property name="maQueryService" ref="maQueryService" />
		<property name="uesService" ref="uesService" />
		<property name="acsQueryService" ref="acsQueryService"></property>
	</bean>
	<task:scheduled-tasks>
		<task:scheduled ref="createStatementFileTask" method="createStatementFile4PayWater"
			cron="${sftp.task.corn}" />
		<task:scheduled ref="createStatementFileTask" method="createStatementFile4RefundWater"
			cron="${sftp.task.corn}" />
	</task:scheduled-tasks>
	 -->
</beans>

    applicationContext.xml的配置:

 

<?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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.0.xsd"
	default-autowire="byName">

    <context:annotation-config/>


<!-- <context:property-placeholder location="file:///opt/pay/config/basis/inf/mag/mag-app.properties" ignore-unresolvable="true" />-->

 <import resource="classpath:META-INF/spring/*-bean.xml" />
</beans>

 首先在mag-spring-boot模块中加入spring-boot-starter-web依赖,具体该依赖都包含哪些自动配置,请参考一下链接:https://zhuanlan.zhihu.com/p/28580443?group_id=881552221710458881,支持springmvc和web开发等。具体的springboot的启动流程详解请参考链接:http://www.cnblogs.com/xinzhao/p/5551828.html,在目录resources下面新建目录MATE-INFO,再新建文件spring.factories,配置需要加载的类:

 

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.netfinworks.mag.config.WebConfig

 

类WebConfig继承了WebmvcConfigurerAdapter来加载springmvc配置:

 

package com.netfinworks.mag.config;

import ch.qos.logback.access.servlet.TeeFilter;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.catalina.filters.RemoteIpFilter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

import java.util.ArrayList;
import java.util.List;

/**
 * WEB配置类
 *
 * @author zhangyongji
 */
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

    /**
     * 对应web.xml
     * -> <servlet-name>dispatcher</servlet-name>
     * -> <filter-name>CharacterEncodingFilter</filter-name>
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean encodingFilter() {
        CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter("UTF-8", true);
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(encodingFilter);
        List<String> list = new ArrayList<>();
        list.add("/");
        filterRegistrationBean.setUrlPatterns(list);
        return filterRegistrationBean;
    }

    /**
     * 对应applicationContext.xml里面的配置
     *
     * @return
     */
    @Bean
    public ViewResolver getViewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/static");
        resolver.setSuffix(".html");
        resolver.setViewClass(org.springframework.web.servlet.view.JstlView.class);
        return resolver;
    }

    /**
     * 注册试图解析器
     *
     * @param registry
     */
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.viewResolver(getViewResolver());
    }


    /**
     * Remote ip filter remote ip filter.
     *
     * @return the remote ip filter
     */
    @Bean
    public RemoteIpFilter remoteIpFilter() {
        return new RemoteIpFilter();
    }

    /**
     * Tee filter tee filter.
     *
     * @return the tee filter
     */
    @Bean
    @ConditionalOnProperty(prefix = "server.tomcat.accesslog", name = "debug", havingValue = "true")
    public TeeFilter teeFilter() {
        //复制请求响应流,用于打印调试日志
        return new TeeFilter();
    }

    /**
     * Object mapper object mapper.
     *
     * @return the object mapper
     */
    @Bean
    public ObjectMapper objectMapper() {
        return new JsonMapper();
    }

    /**
     * Http message converter http message converter.
     *
     * @return the http message converter
     */
    @Bean
    public HttpMessageConverter httpMessageConverter() {
        return new MappingJackson2HttpMessageConverter(this.objectMapper());
    }

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.setUseSuffixPatternMatch(false) // 系统对外暴露的 URL 不会识别和匹配 .* 后缀
                .setUseTrailingSlashMatch(true); // 系统不区分 URL 的最后一个字符是否是斜杠 /
    }

    @Override
    public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer) {
        // 等价于<mvc:default-servlet-handler />, 对静态资源文件的访问, 将无法 mapping 到 Controller 的 path 交给 default servlet handler 处理
        configurer.enable();
    }

    /**
     * Validator local validator factory bean.
     *
     * @return the local validator factory bean
     */
    @Bean
    public LocalValidatorFactoryBean validator() {
        LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
        localValidatorFactoryBean.setProviderClass(org.hibernate.validator.HibernateValidator.class);
        return localValidatorFactoryBean;
    }

    /**
     * Gets method validation post processor.
     *
     * @return the method validation post processor
     */
    @Bean
    public MethodValidationPostProcessor getMethodValidationPostProcessor() {
        MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
        processor.setValidator(validator());
        return processor;
    }

    /**
     * Container customizer embedded servlet container customizer.
     *
     * @return the embedded servlet container customizer
     */
    @Bean
    @ConditionalOnProperty(prefix = "server.tomcat.accesslog", name = "debug", havingValue = "true")
    public EmbeddedServletContainerCustomizer containerCustomizer() {
        return new ContainerAccessLogCustomizer("logback-access.xml");
    }

    /**
     * 这个地方要重新注入一下资源文件,不然不会注入资源的,也没有注入requestHandlerMappping,相当于xml配置的
     * <!--swagger资源配置-->
     * <mvc:resources location="classpath:/META-INF/resources/" mapping="swagger-ui.html"/>
     * <mvc:resources location="classpath:/META-INF/resources/webjars/" mapping="/webjars/**"/>
     * 不知道为什么,这也是spring boot的一个缺点(菜鸟觉得的)
     * <p>
     * //* @param registry
     */
    //@Override
    //public void addResourceHandlers(ResourceHandlerRegistry registry) {
    //    registry.addResourceHandler("swagger-ui.html")
    //            .addResourceLocations("classpath:/META-INF/resources/");
    //    registry.addResourceHandler("/webjars*")
    //            .addResourceLocations("classpath:/META-INF/resources/webjars/");
    //}
    @Bean(name = "/gateway/dptRoute.do")
    public GatewayRoute getGatewayRoute() {
        return new GatewayRoute();
    }
}

 默认错误页面,如果在下图目录下有500页面,则会加载自定义的错误页面;主要启动类,自动配置,启动定时任务,引入dubbo配置:



 

入口类GatewayRoute,用SpringContextUtil获取带注解@serviceRoute的类,eg:@ServiceRoute(name = "DPT_HSB_API_ALEVE_FILE"):即通过前台传过来的service名称路由到不同的类进行处理。

 

package com.netfinworks.mag.config;

import com.meidusa.fastjson.JSON;
import com.netfinworks.common.lang.StringUtil;
import com.netfinworks.mag.constant.RequestConstant;
import com.netfinworks.mag.domain.base.PubBaseRequestDto;
import com.netfinworks.mag.domain.base.PubBaseResponseDto;
import com.netfinworks.mag.enums.ServiceKind;
import com.netfinworks.mag.exception.CommonDefinedException;
import com.netfinworks.mag.exception.ErrorCodeException;
import com.netfinworks.mag.exception.ErrorCodeException.CommonException;
import com.netfinworks.mag.helper.RequestHelper;
import com.netfinworks.mag.service.base.IMagService;
import com.netfinworks.mag.service.base.SpringContextUtil;
import com.netfinworks.mag.service.job.Jobs;
import com.netfinworks.mag.util.tools.AuniXSS;
import com.netfinworks.mag.util.tools.MagCore;
import com.netfinworks.mag.web.verify.VerifyService;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class GatewayRoute extends AbstractController {

    private static final Logger logger = LoggerFactory
            .getLogger(GatewayRoute.class);

    private final Charset BASIC_REQUEST_ENCODING = Charset.forName("UTF-8");

    @Autowired
    private VerifyService verifyService;

    @Autowired
    private Jobs jobs;

    @Autowired
    private SpringContextUtil contextUtil;

    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest request,
                                                 HttpServletResponse response) throws Exception {
        PubBaseResponseDto pubBaseResponseDto = new PubBaseResponseDto();
        PubBaseRequestDto pubBaseRequestDto = new PubBaseRequestDto();
        try {
            logger.info(">>..行业统一网关接入");
            Map<?, ?> parameters = request.getParameterMap();
            if (logger.isInfoEnabled()) {
                logger.info(request.getMethod()
                        + ", GatewayRoute original request:"
                        + JSON.toJSONString(parameters));
            }
            logger.info(">>..公共请求参数 request{}", parameters);
            if (parameters == null || parameters.isEmpty() == true) {
                // 什么参数都没有
                throw CommonDefinedException.REQUIRED_FIELD_NOT_EXIST;
            }
            Charset charset = getEncoding(request);
            logger.info(">>..charset={}", charset);
            Map<String, String> formattedParameters = new HashMap<String, String>(
                    parameters.size());
            for (Map.Entry<?, ?> entry : parameters.entrySet()) {
                if (entry.getValue() == null
                        || Array.getLength(entry.getValue()) == 0) {
                    formattedParameters.put((String) entry.getKey(), null);
                } else {
                    if (HttpMethod.GET.name().equals(request.getMethod())) {
                        formattedParameters.put(
                                (String) entry.getKey(),
                                new String(((String) Array.get(
                                        entry.getValue(), 0))
                                        .getBytes(BASIC_REQUEST_ENCODING),
                                        charset));
                    } else {
                        formattedParameters
                                .put((String) entry.getKey(), URLDecoder
                                        .decode((String) Array.get(
                                                entry.getValue(), 0),
                                                charset.name()));
                    }
                }
            }

            if (logger.isInfoEnabled()) {
                logger.info("GatewayRoute original request format:"
                        + JSON.toJSONString(formattedParameters));
            }
            String serviceName = getServiceName(formattedParameters);
            logger.info(">>..接口名称 serviceName={}", serviceName);
            IMagService service = (IMagService) contextUtil
                    .getServiceByAnnoName(serviceName);

            // 转换为基础对象
            pubBaseRequestDto = RequestHelper.convertBase(formattedParameters);
            logger.info(">>..转换为基础对象 PubBaseRequestDto={}", pubBaseRequestDto);
            // 验签
            verify(pubBaseRequestDto, charset, formattedParameters);
            // 防XSS攻击,去掉“<”和“>”
            formattedParameters = auniXSS(formattedParameters);
            // 获取Ip
            String ip = getIpFromReq(request);
            formattedParameters.put(RequestConstant.IP, ip);
            // 分接口处理
            pubBaseResponseDto = service.process(formattedParameters);
            // 电子账户密码是否已设置可以通过接口查询账户是否已设置密码5004查询。如果已设置密码,可以直接引导客户进入提现页面
            if (service.equals("DPT_HSB_API_PIN_SETUP") || service.equals("DPT_HSB_API_WITHHOLDING")) {
                Map<String, String> modelMap = new HashMap<String, String>();
                ////modelMap.put("CardNbr",formattedParameters.get("CardNbr"));
                ////modelMap.put("MerId",formattedParameters.get("MerId"));
                ////modelMap.put("InputCharset",formattedParameters.get("InputCharset"));
                ////modelMap.put("TradeDate",formattedParameters.get("TradeDate"));
                ////modelMap.put("TradeTime",formattedParameters.get("TradeTime"));
                ////modelMap.put("CoinstCode",formattedParameters.get("CoinstCode"));
                ////modelMap.put("CoinstChannel",formattedParameters.get("CoinstChannel"));
                ////modelMap.put("ESBSource",formattedParameters.get("ESBSource"));
                ////modelMap.put("Sign","");
                ////modelMap.put("SignType","RSA");
                ////modelMap.put("TradeMemo","");
                ////modelMap.put("RetCode",RequestConstant.SYSTEM_SUCCESS);
                ////modelMap.put("RetMsg","交易成功");
                ////String respMsg = this.sign(pubBaseResponseDto);
                ////modelMap = (Map) JSON.parse(respMsg);
                ////modelMap.put("InputCharset", "UTF-8");
                ////String resetPwdSurl = formattedParameters.get("ResetPwdSurl");
                ////String resetPwdFurl = formattedParameters.get("ResetPwdFurl");
                //if (pubBaseResponseDto.getAcceptStatus().equalsIgnoreCase(RequestConstant.AcceptStatus.SUCCESS)) {
                //    modelMap.put("AcceptStatus", RequestConstant.AcceptStatus.SUCCESS);
                //    return new ModelAndView(new RedirectView(resetPwdSurl), modelMap);
                //} else {
                //    modelMap.put("AcceptStatus", RequestConstant.AcceptStatus.FAIL);
                //    modelMap.put("Status", RequestConstant.AcceptStatus.FAIL);
                //    return new ModelAndView(new RedirectView(resetPwdFurl), modelMap);
                //}
                //交易描述字段存放的返回的from表单数据
                if (null != pubBaseResponseDto && null != pubBaseResponseDto.getTradeMemo() && pubBaseResponseDto.getTradeMemo().trim().startsWith("<form")) {
                    logger.info("==== 页面FORM表单跳转数据 ====" + pubBaseResponseDto.getTradeMemo());
                    // chrome兼容
                    response.setContentType("text/html;charset=utf-8");
                    response.getWriter().write(pubBaseResponseDto.getTradeMemo());
                }
            }
            //交易描述字段存放的返回的文件名称,扩展字段存放下载文件字符
            if ("DPT_HSB_API_EVE_FILE".equals(serviceName) || "DPT_HSB_API_ALEVE_FILE".equals(serviceName)) {
                if (null != pubBaseResponseDto && null != pubBaseResponseDto.getTradeMemo()) {
                    ////文件名编码,解决乱码问题
                    String fileName = pubBaseResponseDto.getTradeMemo();
                    encodeURIComponent(fileName);
                    setFileDownloadHeader(response, fileName);
                    ////文件下载
                    OutputStream out = response.getOutputStream();
                    out.write((byte[]) pubBaseResponseDto.getExpandAttribute().get("files"));
                }
            }
            if (pubBaseResponseDto != null) {
                // 统一处理
                respSuccess(response, pubBaseRequestDto, pubBaseResponseDto);
            }
        } catch (Exception e) {
            e.printStackTrace();
            if (e instanceof ErrorCodeException) {
                logger.error("ErrorCode:" + ((ErrorCodeException) e).getErrorCode() + ";"
                        + "ErrorMsg:" + ((ErrorCodeException) e).getErrorMsg()
                        + ";Memo:" + ((ErrorCodeException) e).getMemo(), e);
                respError(response, (ErrorCodeException) e, ((ErrorCodeException) e).getMemo(), pubBaseRequestDto, pubBaseResponseDto);
            } else {
                logger.error("系统错误", e);
                respError(response, CommonDefinedException.SYSTEM_ERROR, "系统错误", pubBaseRequestDto, pubBaseResponseDto);
            }
            return null;
        }
        return null;
    }

    /**
     * 验签
     *
     * @param pubBaseRequestDto
     * @param charset
     * @param formattedParameters
     * @throws CommonException
     */
    private void verify(PubBaseRequestDto pubBaseRequestDto, Charset charset,
                        Map<String, String> formattedParameters) throws CommonException {
        boolean verifyResult = false;
        String signContent = MagCore.createLinkString(
                MagCore.paraFilter(formattedParameters), false);

        if (logger.isInfoEnabled()) {
            logger.info("verify signature: { content:" + signContent
                    + ", signMsg:" + pubBaseRequestDto.getSign() + "}");
        }

        verifyResult = verifyService.verify(pubBaseRequestDto.getMerId(), signContent, pubBaseRequestDto.getSign(),
                charset.name(), pubBaseRequestDto.getSignType());
        if (!verifyResult) {
            // 验签未通过
            logger.error("ErrorCode:" + CommonDefinedException.ILLEGAL_SIGN.getErrorCode() + ";"
                    + "ErrorMsg:" + CommonDefinedException.ILLEGAL_SIGN.getErrorMsg()
                    + ";request dosen't pass verify.");
            throw CommonDefinedException.ILLEGAL_SIGN;
        }
        if (logger.isDebugEnabled()) {
            logger.debug("invoke verify end:" + verifyResult);
        }
    }

    private Charset getEncoding(HttpServletRequest request)
            throws CommonException {
        Charset utf8Charset = Charset.forName("UTF-8");
        String inputCharset = request.getParameter(RequestConstant.INPUT_CHARSET);
        if (StringUtil.isEmpty(inputCharset)) {
            CommonException exp = CommonDefinedException.INPUT_CHARSET_ERROR;
            exp.setMemo("编码类型不能为空");
            throw exp;
        }
        if ("UTF-8".equalsIgnoreCase(inputCharset)) {
            return utf8Charset;
        }
        CommonException exp = CommonDefinedException.INPUT_CHARSET_ERROR;
        exp.setMemo("无法识别编码类型:" + inputCharset);
        throw exp;
    }


    /**
     * 取得service并验证支付方式
     *
     * @param parameters
     * @return
     * @throws Exception
     */
    private String getServiceName(Map<String, String> parameters)
            throws Exception {
        String serviceName = parameters.get(RequestConstant.SERVICE);
        String MERID = parameters.get(RequestConstant.MER_ID);
        if (StringUtil.isEmpty(MERID)) {
            CommonException exp = CommonDefinedException.REQUIRED_FIELD_NOT_EXIST;
            exp.setMemo("合作者身份ID");
            throw exp;
        } else if (MERID.length() > 32) {
            CommonException exp = CommonDefinedException.FIELD_LENGTH_EXCEEDS_LIMIT;
            exp.setMemo("合作者身份ID");
            throw exp;
        }
        if (StringUtil.isEmpty(serviceName)) {
            CommonException exp = CommonDefinedException.REQUIRED_FIELD_NOT_EXIST;
            exp.setMemo("接口名称");
            throw exp;
        }
        ServiceKind service = ServiceKind.getByCode(serviceName);

        if (service == null) {
            throw CommonDefinedException.ILLEGAL_SERVICE;
        }
        return serviceName;

    }


    /**
     * 统一成功处理
     *
     * @param response
     * @param req
     * @param resp
     * @throws Exception
     */
    private void respSuccess(HttpServletResponse response, PubBaseRequestDto req, PubBaseResponseDto resp)
            throws Exception {
        resp.setMerId(req.getMerId());
        resp.setTradeDate(req.getTradeDate());
        resp.setTradeTime(req.getTradeTime());
        resp.setCoinstChannel(req.getCoinstChannel());
        resp.setCoinstCode(req.getCoinstCode());
        resp.setESBSource(req.getESBSource());
        resp.setAcceptStatus(RequestConstant.AcceptStatus.SUCCESS);
        resp.setRetCode(RequestConstant.SYSTEM_SUCCESS);
        resp.setRetMsg("交易成功");
        resp.setInputCharset("UTF-8");
        response.setHeader("content-type", "text/html;charset=UTF-8");
        response.setHeader("Access-Control-Allow-Origin", "*");
        String respMes = this.sign(resp);
        response.getWriter().write(respMes);
    }

    /**
     * 统一错误处理
     *
     * @param response
     * @param e
     * @param memo
     * @throws Exception
     */
    private void respError(HttpServletResponse response, ErrorCodeException e,
                           String memo, PubBaseRequestDto req, PubBaseResponseDto resp) throws Exception {
        resp.setMerId(req.getMerId());
        resp.setTradeDate(req.getTradeDate());
        resp.setTradeTime(req.getTradeTime());
        resp.setCoinstChannel(req.getCoinstChannel());
        resp.setCoinstCode(req.getCoinstCode());
        resp.setESBSource(req.getESBSource());
        resp.setAcceptStatus(RequestConstant.AcceptStatus.FAIL);
        resp.setInputCharset("UTF-8");
        resp.setRetCode(e.getErrorCode());
        resp.setRetMsg(e.getErrorMsg());
        resp.setTradeMemo(StringUtils.isNotEmpty(memo) ? memo : "");
        response.setCharacterEncoding("UTF-8");
        response.setHeader("content-type", "text/html;charset=UTF-8");
        response.setHeader("Access-Control-Allow-Origin", "*");
        String respMes = this.sign(resp);
        response.getWriter().write(respMes);
    }

    private Map<String, String> auniXSS(Map<String, String> reqMap) {
        Map<String, String> result = new HashMap<String, String>(reqMap.size());
        for (Map.Entry<String, String> entry : reqMap.entrySet()) {
            if (entry.getValue() == null) {
                result.put((String) entry.getKey(), null);
            } else {
                String value = AuniXSS.encode(entry.getValue());
                result.put((String) entry.getKey(), value);
            }
        }
        return result;
    }

    /**
     * 返回参数加签
     *
     * @param resp
     * @return
     * @throws Exception
     * @throws Exception
     */
    private String sign(PubBaseResponseDto resp) throws Exception {
        Map<String, String> map = new HashMap<String, String>();
        String respJsonSrc = JSON.toJSONString(resp);
        JSONObject respJson = JSONObject.fromObject(respJsonSrc);
        Iterator<String> it = respJson.keys();
        while (it.hasNext()) {
            String k = it.next();
            String v = respJson.getString(k);
            map.put(k, v);
        }
        String charset = map.get("InputCharset");
        if (StringUtils.isEmpty(charset)) {
            charset = "UTF-8";
        }
        String signType = "RSA";
        String signKey = jobs.queryMerPrivateKey().getPrivateKey();
        Map<String, String> result = MagCore.buildRequestPara(map, signType,
                signKey, charset);
        return JSON.toJSONString(result);
    }

    /**
     * 从HttpServletRequest对象中获取客户端的真实ip并打印到前置网关日志
     *
     * @param request
     */
    private String getIpFromReq(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        ip = ip.equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip;
        return ip;
    }

    /**
     * <pre>
     * 浏览器下载文件时需要在服务端给出下载的文件名,当文件名是ASCII字符时没有问题
     * 当文件名有非ASCII字符时就有可能出现乱码
     *
     * 这里的实现方式参考这篇文章
     * http://blog.robotshell.org/2012/deal-with-http-header-encoding-for-file-download/
     *
     * 最终设置的response header是这样:
     *
     * Content-Disposition: attachment;
     *                      filename="encoded_text";
     *                      filename*=utf-8''encoded_text
     *
     * 其中encoded_text是经过RFC 3986的“百分号URL编码”规则处理过的文件名
     * </pre>
     * @param response
     * @param filename
     * @return
     */
    public static void setFileDownloadHeader(HttpServletResponse response, String filename) {
        String headerValue = "attachment;";
        headerValue += " filename=\"" + encodeURIComponent(filename) + "\";";
        headerValue += " filename*=utf-8''" + encodeURIComponent(filename);
        response.setHeader("Content-Disposition", headerValue);
    }

    /**
     * <pre>
     * 符合 RFC 3986 标准的“百分号URL编码”
     * 在这个方法里,空格会被编码成%20,而不是+
     * 和浏览器的encodeURIComponent行为一致
     * </pre>
     *
     * @param value
     * @return
     */
    public static String encodeURIComponent(String value) {
        try {
            return URLEncoder.encode(value, "UTF-8").replaceAll("\\+", "%20");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
    }

}

service类,需要加上@ServiceRoute(name = "DPT_HSB_API_ALEVE_FILE")@Configuration注解

package com.netfinworks.mag.service;

import com.alibaba.fastjson.JSON;
import com.chanpay.ppd.dpt.api.mch.dto.QueryMchAuthRequest;
import com.chanpay.ppd.dpt.api.mch.dto.QueryMchAuthResponse;
import com.chanpay.ppd.dpt.api.mch.facade.IMchAuthFacade;
import com.netfinworks.mag.annotation.ServiceRoute;
import com.netfinworks.mag.constant.RequestConstant;
import com.netfinworks.mag.domain.AlEveFileRequest;
import com.netfinworks.mag.domain.base.PubBaseResponseDto;
import com.netfinworks.mag.exception.CommonDefinedException;
import com.netfinworks.mag.exception.ErrorCodeException.CommonException;
import com.netfinworks.mag.helper.RequestHelper;
import com.netfinworks.mag.helper.WebServiceHelper;
import com.netfinworks.mag.service.base.MagServiceBase;
import com.netfinworks.mag.util.SftpService;
import com.netfinworks.mag.util.StreamUtils;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import java.io.InputStream;
import java.util.Map;

/**
 * Created by jiji on 2017/7/15.
 */
@ServiceRoute(name = "DPT_HSB_API_ALEVE_FILE")
@Configuration
public class AlEveFileService extends MagServiceBase {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private SftpService sftpService;
    @Autowired
    private IMchAuthFacade mchAuthFacade;
    @Autowired
    private WebServiceHelper webServiceHelper;

    public PubBaseResponseDto process(Map<String, String> paraMap) throws Exception {
        getLogger().info("==== 全流水文件接口 ====");
        PubBaseResponseDto response = this.handle(paraMap);
        return response;
    }

    private PubBaseResponseDto handle(Map<String, String> paraMap) throws Exception {
        String cardProdNo = null;
        PubBaseResponseDto response = new PubBaseResponseDto();
        AlEveFileRequest request = (AlEveFileRequest) RequestHelper.convertFromMap(paraMap);
        /**参数校验 -- 校验一些必输信息 以及字段长度限制*/
        validaPara(request);
        QueryMchAuthRequest queryMchAuthRequest = new QueryMchAuthRequest();
        queryMchAuthRequest.setMerId(request.getMerId());
        webServiceHelper.requestWrapper(queryMchAuthRequest);
        QueryMchAuthResponse queryMchAuthResponse = mchAuthFacade.queryMchAuth(queryMchAuthRequest);
        if (null != queryMchAuthResponse && null != queryMchAuthResponse.getMchAuthList() && queryMchAuthResponse.getMchAuthList().size() > 0) {
            if (StringUtils.isNotEmpty(queryMchAuthResponse.getMchAuthList().get(0).getCardProdNo())) {
                cardProdNo = queryMchAuthResponse.getMchAuthList().get(0).getCardProdNo();
            } else {
                CommonException exp = CommonDefinedException.CARD_PRODNO_EXP;
                exp.setMemo("商户配置异常,请配置产品编码");
                throw exp;
            }

        } else {
            CommonException exp = CommonDefinedException.CARD_PRODNO_EXP;
            exp.setMemo("商户配置异常,请配置产品编码");
            throw exp;
        }
        Map<String, byte[]> map = new HashedMap();
        logger.info("交易明细流水文件接口请求参数:" + JSON.toJSONString(request));
        String files = sftpService.getFiles(request.getMerId(), request.getEveDate());
        String fileName = RequestConstant.HS_BANK_CODE + "-" + "ALEVE" + cardProdNo + "-" + request.getEveDate();
        if (StringUtils.isNotEmpty(files)) {
            InputStream inputStream = StreamUtils.StringTOInputStream(files);
            byte[] bi = StreamUtils.inputStream2Byte(inputStream);
            response.setTradeMemo(fileName);
            map.put("files", bi);
            response.setExpandAttribute(map);
        } else {
            CommonException exp = CommonDefinedException.FILE_IS_NOT_EXISTS;
            exp.setMemo("文件不存在");
            throw exp;
        }
        return response;
    }
}

  

定时任务类:

package com.netfinworks.mag.service.job;

import com.alibaba.fastjson.JSONObject;
import com.chanpay.ppd.dpt.api.mch.dto.MchAuth;
import com.chanpay.ppd.dpt.api.mch.dto.QueryMchAuthRequest;
import com.chanpay.ppd.dpt.api.mch.dto.QueryMchAuthResponse;
import com.chanpay.ppd.dpt.api.mch.facade.IMchAuthFacade;
import com.chanpay.ppd.dpt.api.security.dto.QueryMerPublicKeyRequest;
import com.chanpay.ppd.dpt.api.security.dto.QueryMerPublicKeyResponse;
import com.chanpay.ppd.dpt.api.security.dto.QueryPayPrivateKeyRequest;
import com.chanpay.ppd.dpt.api.security.dto.QueryPayPrivateKeyResponse;
import com.chanpay.ppd.dpt.api.security.facade.ISecurityFacade;
import com.netfinworks.mag.constant.RequestConstant;
import com.netfinworks.mag.exception.CommonDefinedException;
import com.netfinworks.mag.exception.ErrorCodeException.CommonException;
import com.netfinworks.mag.helper.WebServiceHelper;
import com.netfinworks.mag.util.tools.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

@Service
@Configuration
@ConfigurationProperties(prefix = "job.task")
public class Jobs {

    private static Logger logger = LoggerFactory.getLogger(Jobs.class);

    public static final String CACHE_NAME = "merInfo";

    public final static long TOW_Hours = 2 * 60 * 60 * 1000;
    //public final static long TOW_Hours = 60 * 1000;

    @Autowired
    private ISecurityFacade securityFacade;

    @Autowired
    private WebServiceHelper webServiceHelper;

    @Autowired
    private IMchAuthFacade mchAuthFacade;

    /**
     * fixedRate就是每多少分钟一次,不论你业务执行花费了多少时间,我都是1分钟执行1次
     */
    @Scheduled(fixedRate = TOW_Hours)
    @CacheEvict(value = CACHE_NAME, allEntries = true)
    public void fixedRateJob() {
        System.out.println(">>fixedRate执行,清空缓存...." + DateUtils.getDateStr());
    }


    @Cacheable(value = CACHE_NAME)
    public QueryMerPublicKeyResponse queryMerPublicKey(String merId) throws Exception {
        QueryMchAuthRequest queryMchAuthRequest = new QueryMchAuthRequest();
        queryMchAuthRequest.setMerId(merId);
        webServiceHelper.requestWrapper(queryMchAuthRequest);
        QueryMchAuthResponse queryMchAuthResponse = mchAuthFacade.queryMchAuth(queryMchAuthRequest);
        if (null != queryMchAuthResponse && null != queryMchAuthResponse.getMchAuthList() && queryMchAuthResponse.getMchAuthList().size() > 0) {
            for (MchAuth mchAuth : queryMchAuthResponse.getMchAuthList()) {
                if (mchAuth.getIsOpen().equals(RequestConstant.MchAuthStatus.N)) {
                    throw CommonDefinedException.ILLEGAL_ACCESS_SWITCH_SYSTEM;
                }
            }
        } else {
            //请求的服务,不在商户配置中
            throw CommonDefinedException.ILLEGAL_ACCESS_SWITCH_SYSTEM;
        }
        QueryMerPublicKeyRequest queryMerPublicKeyRequest = new QueryMerPublicKeyRequest();
        webServiceHelper.requestWrapper(queryMerPublicKeyRequest);
        queryMerPublicKeyRequest.setMerId(merId);
        logger.info("调用查询商户公钥配置请求对象:" + JSONObject.toJSONString(queryMerPublicKeyRequest));
        QueryMerPublicKeyResponse queryMerPublicKeyResponse = securityFacade.queryMerPublicKey(queryMerPublicKeyRequest);
        logger.info("调用查询商户公钥配置响应对象:" + (null != queryMerPublicKeyResponse ? JSONObject.toJSONString(queryMerPublicKeyResponse) : queryMerPublicKeyResponse));
        // 商户服务
        if (null != queryMerPublicKeyResponse && queryMerPublicKeyResponse.getRespCode().equals(RequestConstant.DPTFacade.SUCCESS)) {
            return queryMerPublicKeyResponse;
        } else {
            CommonException exp = CommonDefinedException.QUERY_MER_KEY_EXP;
            exp.setMemo("查询商户公钥失败");
            throw exp;
        }
    }

    @Cacheable(value = CACHE_NAME)
    public QueryPayPrivateKeyResponse queryMerPrivateKey() throws Exception {
        QueryPayPrivateKeyRequest queryPayPrivateKeyRequest = new QueryPayPrivateKeyRequest();
        webServiceHelper.requestWrapper(queryPayPrivateKeyRequest);
        logger.info("调用查询商户私钥配置请求对象:" + JSONObject.toJSONString(queryPayPrivateKeyRequest));
        QueryPayPrivateKeyResponse queryPayPrivateKeyResponse = securityFacade.queryPayPrivateKey(queryPayPrivateKeyRequest);
        logger.info("调用查询商户私钥配置响应对象:" + (null != queryPayPrivateKeyResponse ? JSONObject.toJSONString(queryPayPrivateKeyResponse) : queryPayPrivateKeyResponse));
        // 商户服务
        if (null != queryPayPrivateKeyResponse && queryPayPrivateKeyResponse.getRespCode().equals(RequestConstant.DPTFacade.SUCCESS)) {
            return queryPayPrivateKeyResponse;
        } else {
            CommonException exp = CommonDefinedException.QUERY_MER_KEY_EXP;
            exp.setMemo("查询商户私钥失败");
            throw exp;
        }
    }
}

相关的主要类差不多就介绍完了,然后就可以启动调试了。

相关其他配置文件的动态打包部署可以参考链接:https://github.com/jiji87432/springboot-dubbox

启动相关脚本:https://github.com/jiji87432/nginx_sh

 

  • 大小: 541.9 KB
  • 大小: 454.1 KB
  • 大小: 526.3 KB
分享到:
评论

相关推荐

    springboot学习思维笔记.xmind

    SpringMVC项目快速搭建 构建Maven项目 日志配置 演示页面 Spring MVC配置 Web配置 简单控制器 运行 Spring MVC的常用注解 @Controller @RequestMapping @ResponseBody @...

    基于SSM洗衣店预约管理系统可升级SpringBoot毕业源码案例设计.zip

    1. **依赖管理**:将Spring、SpringMVC、MyBatis的相关依赖替换为SpringBoot对应的starter模块。 2. **配置简化**:将XML配置文件转换为Java配置类或YAML/Properties配置。 3. **启动器和自动配置**:利用SpringBoot...

    SpringMVC基础篇笔记.docx基础篇笔记.docx

    - **设计理念**:SpringMVC通过一套MVC注解,让普通的POJO(Plain Old Java Object)类可以变成处理HTTP请求的控制器,而无需实现任何特定的接口。 - **特点**: - 支持REST风格的URL请求。 - 具有松散耦合、可...

    基于SpringBoot+Mybatis博客论坛交流平台网设计毕业源码案例设计.zip

    在这个项目中,开发者利用了SpringBoot的快速开发特性以及Mybatis的灵活数据访问能力,为用户提供了一个功能完善的在线讨论和分享知识的环境。以下是这个项目涉及到的主要知识点: 1. **SpringBoot框架**:...

    JSP基于SSM网上相片冲印系统可升级SpringBoot毕业源码案例设计.zip

    本设计旨在构建一个基于JSP的SSM(Spring、SpringMVC、MyBatis)网上相片冲印系统,并探讨其升级至SpringBoot的可能性,为毕业设计提供了一个实用且具有挑战性的项目案例。 首先,SSM框架是Java Web开发中的主流...

    springMVC概括文档

    - **响应数据转换 JSON**:使用 `@ResponseBody` 或 `@RestController` 注解,配合 Jackson 或者 Gson 库,自动将 Java 对象转换为 JSON 格式返回。 Spring MVC 提供了一套完整的 MVC 实现,使得开发者能够高效地...

    基于springboot医疗报销系统源码数据库.doc

    因此,开发一个基于SpringBoot框架的医疗报销系统显得尤为重要。该系统旨在通过自动化手段简化报销流程,提高数据处理速度和准确性。 #### 系统架构与技术选型 本医疗报销系统采用了B/S三层架构模式,即浏览器/...

    JSP_SSM实验室预约设备管理系统可升级SpringBoot源码案例设计.zip

    【JSP_SSM实验室预约设备管理系统可升级SpringBoot源码案例设计】 这是一个基于Java Web的实验室设备预约管理系统,采用经典的SSM(Spring...同时,对于想要升级到SpringBoot的开发者,这也是一个实践转换的绝佳机会。

    基于ssm电影网站.zip

    SpringMVC通过DispatcherServlet接收HTTP请求,然后根据请求信息调用相应的控制器(Controller),控制器处理请求并返回ModelAndView对象,最后视图解析器将ModelAndView转换为用户可以看到的视图。 【MyBatis】 ...

    基于ssm的游戏美术外包管理信息系统.zip

    【SSM游戏美术外包管理信息系统】是一个以Java技术为核心的毕业设计项目,主要采用了Spring、SpringMVC和MyBatis三个框架的集成,即SSM框架。这个系统旨在为游戏美术外包提供一个高效、便捷的管理平台,涵盖了项目...

    基于ssm+jsp个体户商城系统.zip

    开发者可以在HTML页面中嵌入Java代码,通过JSP引擎将这些代码转换为Servlet执行,从而生成动态内容。在这个系统中,JSP可能用于呈现用户界面和接收用户输入。 7. **数据库管理**:为了存储用户信息、商品数据、订单...

    基于ssm+jsp学费管理系统源码数据库文档.zip

    这是一个基于SSM(Spring、SpringMVC、MyBatis)框架和JSP技术开发的学费管理系统源码及数据库文档的项目。SSM是Java Web开发中常用的一个集成框架,它结合了Spring的核心特性、SpringMVC的Web层处理以及MyBatis的...

    基于SSM+vue的视频播放系统.zip

    这是一个基于SSM(Spring、SpringMVC、MyBatis)框架和Vue.js前端技术实现的视频播放系统项目。该项目可能包含以下主要知识点: 1. **Spring框架**:Spring是Java领域的一个核心框架,用于简化企业级应用开发。它...

    基于ssm+jsp社区再就业培训管理系统.zip

    JSP文件会被Web容器(如Tomcat)转换为Servlet,并负责视图的展示。 **5. SpringBoot** 虽然标题未直接提及SpringBoot,但它是现代化Java Web开发的常用选择。SpringBoot简化了Spring应用的初始搭建以及配置工作,...

    基于ssm微信小程序的短视频系统源码数据库.zip

    标题中的“基于ssm微信小程序的短视频系统源码数据库”表明这是一个使用SSM(Spring、SpringMVC、MyBatis)框架开发的微信小程序项目,主要用于实现短视频的上传、浏览和分享功能。该项目还包含了数据库的相关代码或...

    leetcode下载-blogNote:个人博客学习笔记

    -SpringMVC源码分析之参数如何自动转换为实体类 Spring MVC学习笔记(五) -SpringMVC源码分析之参数handleMapping初始化如何映射URL //todo 配置文件顺序加载还未分析 SpringBoot学习笔记(五)-SpringBoot如何启动内嵌...

    基于ssm超市会员(积分)管理系统.zip

    - **积分获取**:会员通过购物或其他活动获得积分,如消费金额按比例转换为积分。 - **积分查询**:会员可以随时查看自己的积分余额和历史积分记录。 - **积分兑换**:设置积分兑换规则,如兑换商品、优惠券等,...

    基于ssm+mysql的个性化电子相册设计源码数据库论文.docx

    2. **相册上传**:用户可以上传照片到指定的相册中,系统应支持批量上传,同时考虑到用户体验,可能还需要提供图片压缩、格式转换等辅助功能。 3. **相册评价**:用户之间可以对相册进行评价和互动,增强了社交属性...

    基于ssm+jsp的医院门诊挂号系统源码数据库.doc

    JSP 文件最终会被转换成 Servlet 类,由服务器执行。 - 在本系统中,JSP 主要用于展示用户界面,处理用户的请求并响应数据。 2. **SSM (Spring + SpringMVC + MyBatis)**: - **Spring**:是 Java 领域中最著名的...

Global site tag (gtag.js) - Google Analytics