秒殺システムページ最適化技術商品詳細ページ静的化(前後端分離)


ページの静的化+前後の分離
  • 常用技術AngularJS、Vue.js
  • の利点:ブラウザのキャッシュ
  • を利用する
    上記の方法は複雑で,jQueryを用いてページの静的化をシミュレートするだけである.
    ユーザーのブラウザにページを直接キャッシュするメリット:ユーザーがデータにアクセスするときは、サーバを要求することなく、ローカルキャッシュで必要なページキャッシュを直接取得することができます.
  • 未作ページ静化:あるページを要求し、キャッシュにアクセスし、キャッシュにあるかどうかを確認し、キャッシュに直接戻りがあるかどうかを確認し、キャッシュにない場合は、htmlページにデータをレンダリングしてキャッシュに保存し、htmlページ全体をクライアントに表示します.
  • はページの静的化を行いました:初めてバックグラウンドでレンダリングするhtmlページを要求して、それからの要求はすべて直接ユーザーのローカルブラウザのキャッシュのhtmlページにアクセスして、静的な資源、それからフロントエンドはAjaxを通じてバックエンドにアクセスして、ページの表示するデータを取得して帰るだけでいいです.

  • 商品詳細ページの静的化以前の操作では、商品詳細ページをredisキャッシュしました.このインタフェースは、対応する製品詳細や秒殺カウントダウンなどの情報を示すだけで、いくつかの重要な情報を表示すればよいので、他のものは静的化することができます.この技術は、実際にはフロントエンドが2つの部分に分かれており、一部は変更されないhtmlブロックであり、もう1つはデータであり、バックエンドがフロントエンドにデータを転送すれば、ajax技術を用いてデータを要求することができる.
    ブラウザ側でキャッシュを行う、キャッシュ時間を制御するためにアプリケーション.propertiesに静的リソース構成項目を追加します.
    #static        ,        css,js,    
    #spring.mvc.static-path-pattern=/static/**    spring.mvc.static-path-pattern=/**
    spring.resources.add-mappings=true
    spring.resources.cache-period=3600 
    spring.resources.chain.cache=true
    spring.resources.chain.enabled=true
    spring.resources.chain.gzipped=true 
    spring.resources.chain.html-application-cache=true
    spring.resources.static-locations=classpath:/static/ 
    

    staticリソースフォルダの下に静的リソースページファイルを新規作成します(.html形式で終わります).ここではなぜ使用できませんか.htmlファイルの末尾は、変更しないで引き続き使用するためです.html接尾辞、システムはデフォルトでtemplatesの下の同名のファイルを探して、だから私達はそれを修正して区別を示します
    GoodsDetailVoパッケージを定義して、ページに値を転送します.
    	/**
    	 *        
    	 */
    	 @Setter
    	 @Getter
    	public class GoodsDetailVo {
    		//         
    		private int status = 0;
    		//        
    		private int remailSeconds = 0;
    		private GoodsVo goodsVo;
    		private MiaoshaUser user;
    

    商品リストページ(goods_list.html)のジャンプロジックを改造し、ジャンプリクエスト前のリクエストパスを変更します.
    <td><a th:href="'/goods/to_detail/'+${goods.id}">  a>td>
    

    現在のリクエストパス:
    <td><a th:href="'/goods_detail.htm?goodsId='+${goods.id}">  a>td>
    

    私たちは今、サービス側にジャンプを要求する必要はありません.クライアントの静的リソースに直接行って、商品の詳細を要求します.detail.html、ここで接尾辞の名前を変更することに注意してください.
    以前の商品詳細ページを変更し、thymeleafが持つラベルを削除して、最も初期のhtml静的ページにします(現在、静的ページにはthymeleafは必要ありません)、idを使用して各コンポーネントを識別するように変更します.
    goodsに移動したばかりですdetail.htmページの場合、jsは初期化され、を実行します.
    $(function(){
    	getDetail();
    });
    

    getDetailメソッド:
    function getDetail(){
    	//getQueryString          
    	var goodsId=getQueryString("goodsId");
    	//alert(goodsId);
    	$.ajax({
    		url:"/goods/detail/"+goodsId,
    		type:"GET",
    		success:function(data){
    			if(data.code==0){		
    				//  render      							
    				render(data.data);
    			}else{
    				layer.msg(data.msg);
    			}
    		},
    		error:function(){
    			layer.msg("    !");
    		}
    	});		
    }
    

    getDetail()メソッドajax非同期リクエストバックグラウンドを使用してページに必要なデータを取得し、データを取得した後にrender()メソッドを呼び出して静的ページをレンダリングします.getDetailで最初のステップは、listページの商品詳細リクエストが
    <td><a th:href="'/goods_detail.htm?goodsId='+${goods.id}">  a>td>
    

    商品詳細はリンクをクリックして私たちの商品のgoodsIdが入っています.では、getQueryStringで要求パスurlのパラメータの値を取得します.
    function getQueryString(name) {
    		var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
    		var r = window.location.search.substr(1).match(reg);
    		if (r != null) {
    			return unescape(r[2]);
    		}
    		return null;
    	}
    

    パラメータを取得すると、バックエンドインタフェースを要求し、データを取得してレンダリングできます.
    function render(detail) {
    		//alert(detail.status);
    		var miaoshaStatus = detail.status;
    		var remailSeconds = detail.remailSeconds;
    		var goods = detail.goodsVo;
    		var user = detail.user;
    		if (user != null) {
    			//     
    			$("#userTip").hide();
    		}
    		$("#goodsName").text(goods.goodsName);
    		$("#goodsImg").attr("src", goods.goodsImg); //.text();
    		$("#startTime").text(goods.startDate); //      
    		$("#remailSeconds").val(remailSeconds);
    		$("#goodsId").val(goods.id);
    		$("#goodsPrice").text(goods.goodsPrice); //goodsStock----- stockCount
    		$("#miaoshaPrice").text(goods.miaoshaPrice);
    		$("#stockCount").text(goods.goodsStock);
    		countDown();
    	}
    

    カウントダウンcountDown()メソッド:
    function countDown(){
    	//           ,0-->      ,-1-->    ,remailSeconds>0-->     
    	var remailSeconds=$("#remailSeconds").val();
    	//alert("remailSeconds:"+remailSeconds);
    	var timeout;
    	
    	if(remailSeconds>0){//       ,       
    		$("#buyButton").attr("disabled",true);
    		$("#miaoshaTip").html("     :"+remailSeconds+" ");
    		//   
    		timeout=setTimeout(function(){
    			$("#countDown").text(remailSeconds-1);
    			$("#remailSeconds").val(remailSeconds-1);//remailSeconds  input
    			countDown();
    		},1000);//         
    		
    	}else if(remailSeconds==0){//      
    		$("#buyButton").attr("disabled",false);
    		if(timeout){//  timeout     
    			clearTimeout(timeout);
    		}
    		//      df1fab4272a24cdf9432adb9fd69cb38
    		$("#miaoshaTip").html("     ");
    	}else{
    		//  0   ,    ,            
    		$("#buyButton").attr("disabled",true);
    		$("#miaoshaTip").html("    ");
    	}
    }
    

    バックエンドGoodsControllerで商品詳細ページのリクエストを受信するインタフェースを次のコードに変更します:
    /**
     *            
     *      html
     *               
     * @param model
     * @param user
     * @param goodsId
     * @return
     */
    @RequestMapping(value="/detail/{goodsId}")  //produces="text/html"
    @ResponseBody
    public Result<GoodsDetailVo> toDetail_staticPage(Model model,MiaoshaUser user,
    		HttpServletRequest request,HttpServletResponse response,@PathVariable("goodsId")long goodsId) {//id   snowflake  
    	System.out.println("     /detail/{goodsId}");
    	model.addAttribute("user", user);
    	GoodsVo goodsVo=goodsService.getGoodsVoByGoodsId(goodsId);
    	model.addAttribute("goods", goodsVo);
    	//     ,          ,       
    	long start=goodsVo.getStartDate().getTime();
    	long end=goodsVo.getEndDate().getTime();
    	long now=System.currentTimeMillis();
    	//     
    	int status=0;
    	//       
    	int remailSeconds=0;
    	//        
    	if(now<start) {//      ,--->   
    		status=0;
    		remailSeconds=(int) ((start-now)/1000);  //     
    	}else if(now>end){ //      
    		status=2;
    		remailSeconds=-1;  //     
    	}else {//      
    		status=1;
    		remailSeconds=0;  //     
    	}
    	model.addAttribute("status", status);
    	model.addAttribute("remailSeconds", remailSeconds);
    	GoodsDetailVo gdVo=new GoodsDetailVo();
    	gdVo.setGoodsVo(goodsVo);
    	gdVo.setStatus(status);
    	gdVo.setRemailSeconds(remailSeconds);
    	gdVo.setUser(user);
    	//      ,    
    	return Result.success(gdVo);		
    }
    

    goods_detail.htmフルコード:
    
    <html>  
    <head>
    <meta charset="UTF-8"/>
    <title>    title>
    	
    	
    	<script type="text/javascript" src="/jquery-validation/lib/jquery-1.11.1.js">script>
    	<link type="text/css" rel="stylesheet" href="/bootstrap/css/bootstrap.css"/>
    	<script type="text/javascript" src="/bootstrap/js/bootstrap.min.js">script>
    	
    	<script type="text/javascript" src="/layer/layer.js">script>
    head
    >
    	<div class="panel panel-default">
    		<div class="panel-heading">      div>
    		<div class="panel-body"> 
    			<span id="userTip">span>
    			<span>         。。。span>
    			<input type="hidden" id="goodsId" >  
    		div>
    		<table class="table" id="goodslist">
    		<tr>
    			<td>    td>
    			<td colspan="3" id="goodsName">td>
    		tr>
    		<tr>
    			<td>    td>
    			<td colspan="3"><img id="goodsImg" width="80" height="60">img>td>
    		tr>
    		<tr>
    			<td>      td>
    			<td id="startTime">td>
    			<td id="">
    				
    				<input type="hidden" id="remailSeconds">input>			
    				<span id="miaoshaTip">span>				
    			td>
    			<td>
    				<form id="miaoshaForm" method="post" action="/miaosha/do_miaosha">
    					<button class="btn btn-primary btn-block" type="submit" id="buyButton">    button>
    					<input type="hidden" name="goodsId" id="goodsId">input>
    				form>
    			td>
    		tr>
    		<tr>
    			<td>    td>
    			<td colspan="3" id="goodsPrice">td>
    		tr>
    		<tr>
    			<td>   td>
    			<td colspan="3" id="miaoshaPrice">td>
    		tr>
    		<tr>
    			<td>    td>
    			<td colspan="3" id="stockCount">td>
    		tr>				
    		table>
    	div>	
    body>
    <script type="text/javascript">
    	//      
    	function getMiaoshaPath(){
    		var goodsId=$("#goodsId").val();
    	}
    	//   
    	function getMiaoshaResult(goodsId){
    		$.ajax({
    			url:"/miaosha/result",
    			type:"GET",
    			data:{
    				goodsId:$("#goodsId").val()
    			},
    			success:function(data){
    				if(data.code==0){
    					var result=data.data;
    					if(result<0){
    						layer.msg("  ,    !");
    					}else if(result==0){
    						//    
    						setTimeout(function(){
    							getMiaoshaResult(goodsId);	
    						},50);//50ms      
    						layer.msg(data.msg);
    					}else{
    						layer.confirm("   ,    !    ?",{btn:["  ","  "]},
    								function(){
    								//    ,      
    								window.location.href="order_detail.htm?orderId="+result;	
    						},
    								function(){
    								layer.closeAll();
    						});
    					}
    					
    					//  
    					//getMiaoshaResult($("#goodsId").val());
    				}else{
    					layer.msg(data.msg);
    				}
    			},
    			error:function(){
    				layer.msg("    !");
    			}
    			//token  cookie   ,      
    			
    		});
    	}
    	function doMiaosha(){
    		alert("  !");
    		$.ajax({
    			url:"/miaosha/do_miaosha_ajaxcache",
    			type:"POST",
    			data:{
    				goodsId:$("#goodsId").val()
    				
    			},
    			success:function(data){
    				if(data.code==0){
    					//    ,      
    					//window.location.href="order_detail.htm?orderId="+data.data.id;	
    					//  
    					getMiaoshaResult($("#goodsId").val());
    				}else{
    					layer.msg(data.msg);
    				}
    			},
    			error:function(){
    				layer.msg("    !");
    			}
    			//token  cookie   ,      
    			
    		});
    	}
    	$(function(){
    		//countDown();
    		getDetail();
    	});
    	
    	//    --------5-17
    	function render(detail){
    		//alert(detail.status);
    		var miaoshaStatus=detail.status;
    		var remailSeconds=detail.remailSeconds;
    		var goods=detail.goodsVo;
    		var user=detail.user;
    		if(user!=null){
    			//     
    			$("#userTip").hide();
    		}
    		$("#goodsName").text(goods.goodsName);
    		$("#goodsImg").attr("src",goods.goodsImg);    //.text();
    		$("#startTime").text(goods.startDate);		//      
    		$("#remailSeconds").val(remailSeconds);
    		$("#goodsId").val(goods.id);
    		$("#goodsPrice").text(goods.goodsPrice);		//goodsStock----- stockCount
    		$("#miaoshaPrice").text(goods.miaoshaPrice);
    		$("#stockCount").text(goods.goodsStock);
    		countDown();
    	}
    	
    	function getQueryString(name){
    		var reg=new RegExp("(^|&)"+name+"=([^&]*)(&|$)");
    		var r=window.location.search.substr(1).match(reg);
    		if(r!=null){
    			return unescape(r[2]);
    		}
    		return null;
    	}
    	
    	
    	function getDetail(){
    		var goodsId=getQueryString("goodsId");
    		//alert(goodsId);
    		$.ajax({
    			url:"/goods/detail/"+goodsId,
    			type:"GET",
    			success:function(data){
    				if(data.code==0){										
    					render(data.data);
    				}else{
    					layer.msg(data.msg);
    				}
    			},
    			error:function(){
    				layer.msg("    !");
    			}
    		});
    		
    	}
    	
    	function countDown(){
    		//           ,0-->      ,-1-->    ,remailSeconds>0-->     
    		var remailSeconds=$("#remailSeconds").val();
    		//alert("remailSeconds:"+remailSeconds);
    		var timeout;
    		
    		if(remailSeconds>0){//       ,       
    			$("#buyButton").attr("disabled",true);
    			$("#miaoshaTip").html("     :"+remailSeconds+" ");
    			//   
    			timeout=setTimeout(function(){
    				$("#countDown").text(remailSeconds-1);
    				$("#remailSeconds").val(remailSeconds-1);//remailSeconds  input
    				countDown();
    			},1000);//         
    			
    		}else if(remailSeconds==0){//      
    			$("#buyButton").attr("disabled",false);
    			if(timeout){//  timeout     
    				clearTimeout(timeout);
    			}
    			//      df1fab4272a24cdf9432adb9fd69cb38
    			$("#miaoshaTip").html("     ");
    		}else{
    			//  0   ,    ,            
    			$("#buyButton").attr("disabled",true);
    			$("#miaoshaTip").html("    ");
    		}
    	}
    script>
    html>