【性能篇】解决项目痛点,优化性能

持续更新

一:内部系统页面响应慢

环境背景:jsp+springmvc+java+http接口+vue
应用场景:页面点开,一直转圈空白
优化:1、页面数据优先静态加载(vue前后端分离就不会有这问题),部分数据异步请求
2、后台分析调用对方接口,使用多线程调用,加快接口请求速度
3、分享对方接口响应时效,帮助对方修改

1、数据请求异步    
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>首页 - 个人选股系统 V5.87</title>
    <link href="/css/bootstrap.min.css" rel="stylesheet">
    <script src="/js/jquery-1.12.4.min.js"></script>
    <!-- <script>
        $(function(){
            $.ajax({
                // 配置ajax的参数
                // url:'请求数据的接口地址'
                url:'/index_data',
                // type:请求方式
                type:'get',
                // dataType:返回的数据格式 html  xml  ***json  text
                dataType: 'json',
                // data:{}  发送的数据
                // success:请求成功之后要执行的命令 -- 回调函数
                success: function(dat){
                    // 接收数据,显示数据
                    console.log(dat)
                    var str = '<tr><th>序号</th><th>股票代码</th><th>股票简称</th><th>涨跌幅</th><th>换手率</th><th>最新价(元)</th><th>前期高点</th><th>前期高点日期</th><th>添加自选</th></tr>';
                    // alert(dat)
                    // 遍历dat 一个表头 + 94个tr数据 -- 将这95个tr放到表格里面
                    for(var i=0;i<dat.length;i++)
                    {
                        // -1-- 字典对象里面的id值  00007 -- 字典里面的code值
                        str += '<tr><td>'+ dat[i].id +'</td><td>'+ dat[i].code+'</td><td>'+ dat[i].sname+'</td><td>10.01%</td><td>4.40%</td><td>全新好</td><td>16.05</td><td>2017-07-18</td><td><input type="button" value="添加" name="toAdd"></td></tr>';
                    }

                    $('.table').html( str )
                },
                // error 请求失败之后要执行的命令 -- 回调函数
                error: function(){
                    alert('请求超时')
                }
            })
        })
    </script> -->
    <!-- ajax函数内部工作中只配置基本参数,success拿到ajax函数的外面变成done(),error拿到ajax函数的外面变成fail() -->
    <!-- <script>
    $(function(){
        $.ajax({
            url:'/index_data',
            type:'get',
            dataType:'json'
        })
        .done(function(dat){
            // 成功
            var str = '<tr><th>序号</th><th>股票代码</th><th>股票简称</th><th>涨跌幅</th><th>换手率</th><th>最新价(元)</th><th>前期高点</th><th>前期高点日期</th><th>添加自选</th></tr>';
                    // alert(dat)
                    // 遍历dat 一个表头 + 94个tr数据 -- 将这95个tr放到表格里面
                    for(var i=0;i<dat.length;i++)
                    {
                        // -1-- 字典对象里面的id值  00007 -- 字典里面的code值
                        str += '<tr><td>'+ dat[i].id +'</td><td>'+ dat[i].code+'</td><td>'+ dat[i].sname+'</td><td>10.01%</td><td>4.40%</td><td>全新好</td><td>16.05</td><td>2017-07-18</td><td><input type="button" value="添加" name="toAdd"></td></tr>';
                    }

                    $('.table').html( str )
        })
        .fail(function(){
            alert('请求失败')
        })
    })
    </script> -->
    <script>
        $(function(){
            $.get('/index_data', function(dat){
                var str = '<tr><th>序号</th><th>股票代码</th><th>股票简称</th><th>涨跌幅</th><th>换手率</th><th>最新价(元)</th><th>前期高点</th><th>前期高点日期</th><th>添加自选</th></tr>';
                    // alert(dat)
                    // 遍历dat 一个表头 + 94个tr数据 -- 将这95个tr放到表格里面
                    for(var i=0;i<dat.length;i++)
                    {
                        // -1-- 字典对象里面的id值  00007 -- 字典里面的code值
                        str += '<tr><td>'+ dat[i].id +'</td><td>'+ dat[i].code+'</td><td>'+ dat[i].sname+'</td><td>10.01%</td><td>4.40%</td><td>全新好</td><td>16.05</td><td>2017-07-18</td><td><input type="button" value="添加" name="toAdd" data-code="'+dat[i].code+'"></td></tr>';
                    }

                    $('.table').html( str )
            }, 'json')


            // 增加关注
            // 添加按钮 单击,把股票code值发送到接口 -- 接口返回不要重复添加或关注成功文字
            // $('input').click(function(){
            //     alert(1)
            // })
            $('.table').delegate('input', 'click', function(){
                // alert(2)
                // k="v" 自定义html属性的形式获取code值

                // 访问自己这个input标签的data-code属性值即可
                // prop只能访问控制w3c定义的html属性,自定义的用attr函数访问和控制,attr和prop的用法完全相同
                // alert($(this).prop('data-code'))
                // alert($(this).attr('data-code'))
                var myCode = $(this).attr('data-code')
                $.ajax({
                    url:'/add_data',
                    type:'get',
                    dataType:'text',
                    data:{code: myCode}
                })
                .done(function(dat){
                    alert(dat)
                })
                .fail(function(){
                    alert('请求超时')
                })
            })

        })
    </script>
</head>

<body>
<div class="navbar navbar-inverse navbar-static-top ">
        <div class="container">
        <div class="navbar-header">
                <button class="navbar-toggle" data-toggle="collapse" data-target="#mymenu">
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                 </button>
                 <a href="#" class="navbar-brand">选股系统</a>
        </div>
        <div class="collapse navbar-collapse" id="mymenu">
                <ul class="nav navbar-nav">
                        <li class="active"><a href="">股票信息</a></li>
                        <li><a href="/center.html">个人中心</a></li>
                </ul>
        </div>
        </div>
</div>
<div class="container" id="container">

    <div class="container-fluid">
        <table class="table table-hover">           


            <!-- <tr><th>序号</th><th>股票代码</th><th>股票简称</th><th>涨跌幅</th><th>换手率</th><th>最新价()</th><th>前期高点</th><th>前期高点日期</th><th>添加自选</th></tr>
            <tr><td>1</td><td>000007</td><td>全新好</td><td>10.01%</td><td>4.40%</td><td>全新好</td><td>16.05</td><td>2017-07-18</td><td><input type="button" value="添加" name="toAdd"></td></tr>  -->


        </table>
    </div>
</div>

</body>
</html>
2、线程池,开启多线程
2.1 自定义线程池
 private ThreadPoolExecutor poolExecutor;

    /**
    * 利用@service和@postConstruct初始化线程池
    * @postConstruct无法注入,启动error(待解决)
    **/
    @PostConstruct
    private void init(){
        poolExecutor = new ThreadPoolExecutor(5,5,60L, TimeUnit.SECONDS,
                new SynchronousQueue<>(), (ThreadFactory) new LinkedBlockingQueue<Runnable>(),new ThreadPoolExecutor.CallerRunsPolicy());
    }
    /**
    * 开启线程调用
    **/
    public ResultMsg getMethod1(String mUrl, List<NameValuePair> nameValuePairList){
//        String mUrl =mNetwork+"queryOrderList";
//        MapCastNameValuePairUtil mapCastNameValuePairUtil=new MapCastNameValuePairUtil();
//        List<NameValuePair> nameValuePairList =mapCastNameValuePairUtil.mapcastNameValue(map1);
        //异步请求对方接口返回数据
        ResultMsg resultMsg= (ResultMsg) poolExecutor.submit(()->HttpClientTools.SendPost(mUrl,nameValuePairList,new NetPlatModel<PrizeOrder>()));
        return  resultMsg;
    }
2.2 使用内置线程,固定线程池

整理

  // Creates a thread pool that reuses a fixed number of threads
   ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
   CompletableFuture<ResultMsg> fl1 = CompletableFuture.supplyAsync(new Supplier<ResultMsg>() {
                @Override
                public ResultMsg get() {

                    return recordService.getPrize(mUrl,nameValuePairList);

                }
            }, fixedThreadPool
        );
        CompletableFuture<ResultMsg> fl2 = CompletableFuture.supplyAsync(new Supplier<ResultMsg>() {
                @Override
                public ResultMsg get() {

                    return recordService.getHMCPrize(hUrl,hnameValuePairList);
                }
            }, fixedThreadPool
        );
        ResultMsg resultMsg = null;
        ResultMsg resultMsg1 = null;
        try {
            resultMsg = fl1.get();
        } catch (InterruptedException e) {
           logger.error(e);
        } catch (ExecutionException e) {
            logger.error(e);
        } catch (Exception e) {
            logger.error(e);
        }
        try {
            resultMsg1 = fl2.get();
        } catch (InterruptedException e) {
            logger.error(e);
        } catch (ExecutionException e) {
            logger.error(e);
        } catch (Exception e) {
            logger.error(e);
        }

调用第三方接口(开启多线程请求,数据没有一致性。如果有,采用返回结果确定Future接受确定结果,再做请求)

  public ResultMsg getPrize(String Url, List<NameValuePair> nameValuePairList){
        LocalDateTime time1 =LocalDateTime.now();
        logger.info("会员中心活动及奖品兑换接口,开始时间:"+time1);
        ResultMsg resultMsg= HttpClientTools.SendPost(Url,nameValuePairList,new NetPlatModel<PrizeOrder>());
        LocalDateTime time2 =LocalDateTime.now();
        logger.info("会员中心活动及奖品兑换接口,结束时间:"+time2+",耗时:"+(time2.toInstant(ZoneOffset.of("+8")).toEpochMilli()-time1.toInstant(ZoneOffset.of("+8")).toEpochMilli()));
        return resultMsg;
    }
    public ResultMsg getHMCPrize(String Url, List<NameValuePair> nameValuePairList){
        LocalDateTime time1 =LocalDateTime.now();
        logger.info("HMC活动及奖品兑换接口,开始时间:"+time1);
        ResultMsg resultMsg= HttpClientTools.SendPost(Url,nameValuePairList,new NetPlatModel<HMCPrizeOrder>());
        LocalDateTime time2 =LocalDateTime.now();
        logger.info("HMC活动及奖品兑换接口,结束时间:"+time2+",耗时:"+(time2.toInstant(ZoneOffset.of("+8")).toEpochMilli()-time1.toInstant(ZoneOffset.of("+8")).toEpochMilli()));
        return resultMsg;
    }
 public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
@RequestMapping("prize")
    public ModelAndView queryPrize(HttpServletRequest request){
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
        IResponse responseData = new IResponse("/record/prizeList");
        ModelAndView view = request(responseData);
        String mobilephone=request.getParameter("mobilephone");
        String startDate=request.getParameter("startDate");
        String endDate=request.getParameter("endDate");
        String mStartDate =startDate+" 00:00";
        String hStartDate =startDate+" 00:00:00";
        String mEndDate =endDate+" 23:59";
        String hEndDate =endDate+" 23:59:59";

        HashMap map=new HashMap<String,String>(5);
        map.put("mobileCode",mobilephone);
        map.put("startDate",mStartDate);
        map.put("endDate",mEndDate);
        HashMap sysparam =new HashMap<String,String>(3);
        sysparam.put("channelSrc","CSS");
        String busiparamS= JSONUtils.toJSONString(map);
        String sysparamS=JSONUtils.toJSONString(sysparam);
        HashMap<String, String> map1 = new HashMap<>(5);
        map1.put("sysparam",sysparamS);
        map1.put("busiparam", busiparamS);
        map1.put("ifAcceptCacheData", "N");
        String mNetwork =Global.getProperty("hyzx_incrementService");
        String mUrl =mNetwork+"queryOrderList";
        MapCastNameValuePairUtil mapCastNameValuePairUtil=new MapCastNameValuePairUtil();
        List<NameValuePair> nameValuePairList =mapCastNameValuePairUtil.mapcastNameValue(map1);

        HashMap hMap =new HashMap<String,String>(5);
        hMap.put("mobileCode",mobilephone);
        hMap.put("orderStartDate",hStartDate);
        hMap.put("orderEndDate",hEndDate);
        String hbusiparamS= JSONUtils.toJSONString(hMap);
        HashMap<String, String> map2 = new HashMap<>(5);
        map2.put("sysparam",sysparamS);
        map2.put("busiparam", hbusiparamS);
        map2.put("ifAcceptCacheData", "N");
        String hNetwork =Global.getProperty("hyzx_HMC_MallService");
        String hUrl =hNetwork+"queryHmcOrderList";
        List<NameValuePair> hnameValuePairList =mapCastNameValuePairUtil.mapcastNameValue(map2);

        CompletableFuture<ResultMsg> fl1 = CompletableFuture.supplyAsync(new Supplier<ResultMsg>() {
                @Override
                public ResultMsg get() {

                    return recordService.getPrize(mUrl,nameValuePairList);

                }
            }, fixedThreadPool
        );
        CompletableFuture<ResultMsg> fl2 = CompletableFuture.supplyAsync(new Supplier<ResultMsg>() {
                @Override
                public ResultMsg get() {

                    return recordService.getHMCPrize(hUrl,hnameValuePairList);
                }
            }, fixedThreadPool
        );
        ResultMsg resultMsg = null;
        ResultMsg resultMsg1 = null;
        try {
            resultMsg = fl1.get();
        } catch (InterruptedException e) {
           logger.error(e);
        } catch (ExecutionException e) {
            logger.error(e);
        } catch (Exception e) {
            logger.error(e);
        }
        try {
            resultMsg1 = fl2.get();
        } catch (InterruptedException e) {
            logger.error(e);
        } catch (ExecutionException e) {
            logger.error(e);
        } catch (Exception e) {
            logger.error(e);
        }
/*
* 會員中心處理
* */
        ArrayList<PrizeOrder> PrizeOrderList=new ArrayList<PrizeOrder>();
        Map<Integer,String> PrizeOrderListhidden = new HashMap<Integer,String>();
        Map<String,String> addresshidden = new HashMap<String,String>();
        PrizeOrderListhidden.clear();
        if (null==resultMsg||null==resultMsg1){
//            view.addObject("prizeOrderMsg",new ResultMsg());
            view.addObject("Msg","N");
        }else{
            view.addObject("Msg","Y");
            if (resultMsg.isFlag()) {
                NetPlatModel result = (NetPlatModel) resultMsg.getResult();
                ArrayList<JSONObject> jsonObjects =result.getRespData();
                for(int i=0;i<jsonObjects.size();i++) {
                    PrizeOrder prizeOrder=jsonObjects.get(i).toJavaObject(PrizeOrder.class);
                    String moblie = prizeOrder.getReceiveCall();
                    PrizeOrderListhidden.put(PrizeOrderListhidden.size()+1,moblie);
                    moblie =DesensitizeUtil.mobile(moblie);
                    prizeOrder.setReceiveCall(moblie);
                    String address =prizeOrder.getShippingAddress();
                    addresshidden.put(prizeOrder.getOrderCode(),address);
                    if(StringUtil.isNotNull(address)) {
                        prizeOrder.setShippingAddress(DesensitizeUtil.address(address));
                    }
                    PrizeOrderList.add(prizeOrder);
                }
            }else {
                view.addObject("prizeOrderMsg",resultMsg);
            }
            /*
             * HMC處理
             * */
            if (resultMsg1.isFlag()) {
                NetPlatModel result1 = (NetPlatModel) resultMsg1.getResult();
                ArrayList<JSONObject> jsonList= result1.getRespData();
                if(jsonList!=null&&jsonList.size()>0){
                    for (int i=0;i<jsonList.size();i++) {
                        HMCPrizeOrder hmcPrizeOrder=jsonList.get(i).toJavaObject(HMCPrizeOrder.class);
                        PrizeOrder prizeOrder =new PrizeOrder(hmcPrizeOrder);
                        PrizeOrderList.add(prizeOrder);
                    }
                }
                for(int t=0; t<PrizeOrderList.size();t++){
                    PrizeOrderListhidden.put(PrizeOrderListhidden.size()+1,PrizeOrderList.get(t).getReceiveCall());
                    //手机号 脱敏
                    String moblie=PrizeOrderList.get(t).getReceiveCall();
                    String str =DesensitizeUtil.mobile(moblie);
                    PrizeOrderList.get(t).setReceiveCall(str);
                    //地址脱敏
                    String address =PrizeOrderList.get(t).getShippingAddress();
                    if(!addresshidden.containsKey(PrizeOrderList.get(t).getOrderCode())) {
                        addresshidden.put(PrizeOrderList.get(t).getOrderCode(),address);
                    }
                    if(address!=null){
                        logger.info("未脱敏"+address);
                        String add =DesensitizeUtil.address(address);
                        logger.info("已脱敏"+add);
                        PrizeOrderList.get(t).setShippingAddress(add);
                    }
                }
            }else {
                view.addObject("prizeOrderMsg",resultMsg1);
            }

        }
        fixedThreadPool.shutdown();
        view.addObject("prizeOrderList",PrizeOrderList);
        Global.setRemoteCache("PrizeOrderListhidden"+Global.getThreadUser().getUserCode(), PrizeOrderListhidden);
        Global.setRemoteCache("PrizeOrderaddresshidden"+Global.getThreadUser().getUserCode(), addresshidden);
        return view;
    }

3、对各个接口调用,打印时间。针对性的优化处理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值