普通springmvc项目转换为springboot项目

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

2.开始动手:

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


普通springmvc项目转换为springboot项目_第1张图片
 

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

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

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

 
普通springmvc项目转换为springboot项目_第2张图片
 

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

web.xml的配置:

 




	mag-facade-web

	
		logbackConfigLocation
		file:///opt/pay/config/basis/mag-tzt/mag-logback.xml
	
	
		webAppRootKey
		com.netfinworks.mag
	
	
		dispatcher
		org.springframework.web.servlet.DispatcherServlet
		0
	
	
	    healthCheckDispatcher
	    com.netfinworks.common.monitor.web.servlet.HeathCheckDispatcherServlet
	    1
	

	
		dispatcher
		*.do
	
	
	    healthCheckDispatcher
	    /_health_check
	

	
	
		contextConfigLocation
		classpath:spring/applicationContext.xml
	
	
	
		org.springframework.web.context.ContextLoaderListener
	
	
		ch.qos.logback.ext.spring.web.LogbackConfigListener
	

    
        CharacterEncodingFilter
        org.springframework.web.filter.CharacterEncodingFilter
        
            encoding
            utf-8
        
    

    
        CharacterEncodingFilter
        /*
    

   dispatch-servlet的配置:




	
	
		
			
				file:///opt/pay/config/basis/mag-tzt/mag-app.properties
				file:///opt/pay/config/basis/mag-tzt/mag-sftp-config.properties
				
			
		
	

	
	
		
		
		
	
	
	
	
		
		
	
	
	
		
		
		
	
	
	
		
		
		
	

	
	

	
	

	
	
		
		
		
		
		
		
	
	
	
	
	
		
	
	
	
		
	
	
	
	

	
	

	

	

	
		
	

	
	
		
	
	
	
	
	
	
		
		
	
	

	
	
		
		
		
		
		
	
	
	
	
		
	

	
	
		
	
	
	
	
	
	
		
	
	
	
	
	
	
		
		
	
	
	
	
	
		
	

	

	
	
		
		
		
	

	
	
	
	
	
	

	
	
		
	
	
	
	
	
        
    
    
    
    
    
        
    
    
    
    
    
        
    
    
    
    

	
	
		
	
	
		
			
				CP101
			
		

		

		

		
		
			
				${netfinworksmq.java.naming.factory.initial}
				${netfinworksmq.java.naming.provider.url}
				${netfinworksmq.java.naming.security.principal}
				
				${netfinworksmq.java.naming.security.credentials}
				
			
		
		

		

	
	
		
	
	
	
		
	
	
		
	


	
	
		
		
		
		
		
		
		
		
		
		
	
	
	
		
		
		
		
		
	

	
	
	
		
		
		
		
	
	
	
	
	
		
	
	
		
	
	
		
	
	
		
	
	
		
	
	
		
	
	
		
	
	
	
	
		
		
	
	
	
		
	
	
		
		
		
	
	
	
	
	
	
    
    
		
		
    
    
    	
    
    
    
    
    
    
    
    
    
    
    
    
		
		
		
    
	
	
		
		
    
    
    
    	
	
    
    
	
	
		
		
		
    
	
	
	
	
	
	
	
	
	
	
	
	

	
		
	
	
	
	
	
	
	
	
	
		
	
	
		
		
		
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
		
	

	
		
	
	

    applicationContext.xml的配置:

 




    




 

 首先在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
     * -> dispatcher
     * -> CharacterEncodingFilter
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean encodingFilter() {
        CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter("UTF-8", true);
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(encodingFilter);
        List 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) {
        // 等价于, 对静态资源文件的访问, 将无法 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配置的
     * 
     * 
     * 
     * 不知道为什么,这也是spring boot的一个缺点(菜鸟觉得的)
     * 

* //* @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配置:


普通springmvc项目转换为springboot项目_第3张图片
 

入口类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 formattedParameters = new HashMap(
                    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 modelMap = new HashMap();
                ////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(" 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 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 auniXSS(Map reqMap) {
        Map result = new HashMap(reqMap.size());
        for (Map.Entry 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 map = new HashMap();
        String respJsonSrc = JSON.toJSONString(resp);
        JSONObject respJson = JSONObject.fromObject(respJsonSrc);
        Iterator 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 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;
    }

    /**
     * 
     * 浏览器下载文件时需要在服务端给出下载的文件名,当文件名是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编码”规则处理过的文件名
     * 
* @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); } /** *
     * 符合 RFC 3986 标准的“百分号URL编码”
     * 在这个方法里,空格会被编码成%20,而不是+
     * 和浏览器的encodeURIComponent行为一致
     * 
* * @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 paraMap) throws Exception {
        getLogger().info("==== 全流水文件接口 ====");
        PubBaseResponseDto response = this.handle(paraMap);
        return response;
    }

    private PubBaseResponseDto handle(Map 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 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

 

你可能感兴趣的:(项目重构)