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
相关推荐
SpringMVC项目快速搭建 构建Maven项目 日志配置 演示页面 Spring MVC配置 Web配置 简单控制器 运行 Spring MVC的常用注解 @Controller @RequestMapping @ResponseBody @...
1. **依赖管理**:将Spring、SpringMVC、MyBatis的相关依赖替换为SpringBoot对应的starter模块。 2. **配置简化**:将XML配置文件转换为Java配置类或YAML/Properties配置。 3. **启动器和自动配置**:利用SpringBoot...
- **设计理念**:SpringMVC通过一套MVC注解,让普通的POJO(Plain Old Java Object)类可以变成处理HTTP请求的控制器,而无需实现任何特定的接口。 - **特点**: - 支持REST风格的URL请求。 - 具有松散耦合、可...
在这个项目中,开发者利用了SpringBoot的快速开发特性以及Mybatis的灵活数据访问能力,为用户提供了一个功能完善的在线讨论和分享知识的环境。以下是这个项目涉及到的主要知识点: 1. **SpringBoot框架**:...
本设计旨在构建一个基于JSP的SSM(Spring、SpringMVC、MyBatis)网上相片冲印系统,并探讨其升级至SpringBoot的可能性,为毕业设计提供了一个实用且具有挑战性的项目案例。 首先,SSM框架是Java Web开发中的主流...
- **响应数据转换 JSON**:使用 `@ResponseBody` 或 `@RestController` 注解,配合 Jackson 或者 Gson 库,自动将 Java 对象转换为 JSON 格式返回。 Spring MVC 提供了一套完整的 MVC 实现,使得开发者能够高效地...
因此,开发一个基于SpringBoot框架的医疗报销系统显得尤为重要。该系统旨在通过自动化手段简化报销流程,提高数据处理速度和准确性。 #### 系统架构与技术选型 本医疗报销系统采用了B/S三层架构模式,即浏览器/...
【JSP_SSM实验室预约设备管理系统可升级SpringBoot源码案例设计】 这是一个基于Java Web的实验室设备预约管理系统,采用经典的SSM(Spring...同时,对于想要升级到SpringBoot的开发者,这也是一个实践转换的绝佳机会。
SpringMVC通过DispatcherServlet接收HTTP请求,然后根据请求信息调用相应的控制器(Controller),控制器处理请求并返回ModelAndView对象,最后视图解析器将ModelAndView转换为用户可以看到的视图。 【MyBatis】 ...
【SSM游戏美术外包管理信息系统】是一个以Java技术为核心的毕业设计项目,主要采用了Spring、SpringMVC和MyBatis三个框架的集成,即SSM框架。这个系统旨在为游戏美术外包提供一个高效、便捷的管理平台,涵盖了项目...
开发者可以在HTML页面中嵌入Java代码,通过JSP引擎将这些代码转换为Servlet执行,从而生成动态内容。在这个系统中,JSP可能用于呈现用户界面和接收用户输入。 7. **数据库管理**:为了存储用户信息、商品数据、订单...
这是一个基于SSM(Spring、SpringMVC、MyBatis)框架和JSP技术开发的学费管理系统源码及数据库文档的项目。SSM是Java Web开发中常用的一个集成框架,它结合了Spring的核心特性、SpringMVC的Web层处理以及MyBatis的...
这是一个基于SSM(Spring、SpringMVC、MyBatis)框架和Vue.js前端技术实现的视频播放系统项目。该项目可能包含以下主要知识点: 1. **Spring框架**:Spring是Java领域的一个核心框架,用于简化企业级应用开发。它...
JSP文件会被Web容器(如Tomcat)转换为Servlet,并负责视图的展示。 **5. SpringBoot** 虽然标题未直接提及SpringBoot,但它是现代化Java Web开发的常用选择。SpringBoot简化了Spring应用的初始搭建以及配置工作,...
标题中的“基于ssm微信小程序的短视频系统源码数据库”表明这是一个使用SSM(Spring、SpringMVC、MyBatis)框架开发的微信小程序项目,主要用于实现短视频的上传、浏览和分享功能。该项目还包含了数据库的相关代码或...
-SpringMVC源码分析之参数如何自动转换为实体类 Spring MVC学习笔记(五) -SpringMVC源码分析之参数handleMapping初始化如何映射URL //todo 配置文件顺序加载还未分析 SpringBoot学习笔记(五)-SpringBoot如何启动内嵌...
- **积分获取**:会员通过购物或其他活动获得积分,如消费金额按比例转换为积分。 - **积分查询**:会员可以随时查看自己的积分余额和历史积分记录。 - **积分兑换**:设置积分兑换规则,如兑换商品、优惠券等,...
2. **相册上传**:用户可以上传照片到指定的相册中,系统应支持批量上传,同时考虑到用户体验,可能还需要提供图片压缩、格式转换等辅助功能。 3. **相册评价**:用户之间可以对相册进行评价和互动,增强了社交属性...
JSP 文件最终会被转换成 Servlet 类,由服务器执行。 - 在本系统中,JSP 主要用于展示用户界面,处理用户的请求并响应数据。 2. **SSM (Spring + SpringMVC + MyBatis)**: - **Spring**:是 Java 领域中最著名的...