Javaのスパイクシリーズ(2) - 静的なページのテクノロジー


序文

コード断片は、サーバー、クライアントのレンダリング、3通りの方法で記述されたオブジェクト・キャッシュをレンダリングすることによって導入されています。
参照のためのフラグメント、サービスシナリオに応じて自己適応を達成する必要がありますが、考え方は同じです。




まず、サーバー側のレンダリング


1、インターフェースは、HTMLページを設定するために返します

@Autowired
ThymeleafViewResolver thymeleafViewResolver;
@Autowired
ApplicationContext applicationContext;

@RequestMapping(value="/to_list", produces="text/html")
@ResponseBody
public String goodsList() {
    // 业务逻辑
}


2、キャッシュが開始を取得し、そこに返します。

//取缓存
String html = redisService.get(GoodsKey.getGoodsList, "", String.class);
if(!StringUtils.isEmpty(html)) {
    return html;
}


3、キャッシュなし、手動でそれをレンダリングします。

springboot1.5.x言葉遣い:

List<GoodsVo> goodsList = goodsService.listGoodsVo();
model.addAttribute("goodsList", goodsList);
SpringWebContext ctx = new SpringWebContext(request,response, request.getServletContext(),request.getLocale(), model.asMap(), applicationContext );
//手动渲染
html = thymeleafViewResolver.getTemplateEngine().process("goods_list", ctx);

springboot2.x言葉遣い:

WebContext ctx = new WebContext(request, response, request.getServletContext(),  request.getLocale(), model.asMap());
//手动渲染
html = thymeleafViewResolver.getTemplateEngine().process("goods_list", ctx);


図4は、最終的なレンダリングコンテンツはRedisのに加え

if(!StringUtils.isEmpty(html)) {
    redisService.set(GoodsKey.getGoodsList, "", html);
}




第二に、クライアントのレンダリング(商品の詳細ページ)


1は、静的なHTMLのパスを変更するためのパスを見つけるために、製品の詳細ページにジャンプします。

製品一覧ページでは、動的パスの詳細ページにジャンプを見つける直接サフィックスHTMLテンプレートにアクセスできるようapplication.propertiesは、一般的に構成されるため、HTMLは、あなたができる言葉ではない、サフィックスHTMまたはSHTML、静的パスを変更しますフォルダ。
コードの詳細は、静的なページgoods_detail.htmにリンクしていることに注意してください:

<body>

<div class="panel panel-default" style="height:100%;background-color:rgba(222,222,222,0.8)">
  <div class="panel-heading">秒杀商品列表</div>
  <table class="table" id="goodslist">
    <tr><td>商品名称</td><td>商品图片</td><td>商品原价</td><td>秒杀价</td><td>库存数量</td><td>详情</td></tr>
    <tr  th:each="goods,goodsStat : ${goodsList}">  
                <td th:text="${goods.goodsName}"></td>  
                <td ><img th:src="@{${goods.goodsImg}}" width="100" height="100" /></td>  
                <td th:text="${goods.goodsPrice}"></td>  
                <td th:text="${goods.miaoshaPrice}"></td>  
                <td th:text="${goods.stockCount}"></td>
                <td><a th:href="'/goods_detail.htm?goodsId='+${goods.id}">详情</a></td>  
     </tr>  
  </table>
</div>
</body>


図2に示すように、パス1によれば、goods_detail.htmファイル下に新しい静的ディレクトリ、オリジナル動的ページテンプレート言語は、静的ファイルにデータをレンダリングするために、AJAXを使用し、次に、ID =「XX」で除去し、置換されています。

オリジナル動的ページ:

<div class="panel panel-default">
  <div class="panel-heading">秒杀商品详情</div>
  <div class="panel-body">
    <span th:if="${user eq null}"> 您还没有登录,请登陆后再操作<br/></span>
    <span>没有收货地址的提示。。。</span>
  </div>
  <table class="table" id="goodslist">
    <tr>  
        <td>商品名称</td>  
        <td colspan="3" th:text="${goods.goodsName}"></td> 
     </tr>  
     <tr>  
        <td>商品图片</td>  
        <td colspan="3"><img th:src="@{${goods.goodsImg}}" width="200" height="200" /></td>  
     </tr>
     <tr>  
        <td>秒杀开始时间</td>  
        <td th:text="${#dates.format(goods.startDate, 'yyyy-MM-dd HH:mm:ss')}"></td>
        <td id="miaoshaTip">    
            <input type="hidden" id="remainSeconds" th:value="${remainSeconds}" />
            <span th:if="${miaoshaStatus eq 0}">秒杀倒计时:<span id="countDown" th:text="${remainSeconds}"></span>秒</span>
            <span th:if="${miaoshaStatus eq 1}">秒杀进行中</span>
            <span th:if="${miaoshaStatus eq 2}">秒杀已结束</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" th:value="${goods.id}" />
            </form>
        </td>
     </tr>
     <tr>  
        <td>商品原价</td>  
        <td colspan="3" th:text="${goods.goodsPrice}"></td>  
     </tr>
      <tr>  
        <td>秒杀价</td>  
        <td colspan="3" th:text="${goods.miaoshaPrice}"></td>  
     </tr>
     <tr>  
        <td>库存数量</td>  
        <td colspan="3" th:text="${goods.stockCount}"></td>  
     </tr>
  </table>
</div>

静的なページの後:あなたが見ることができ、動的なテンプレート言語は、直接JSによって割り当てられ、削除されます。

<div class="panel panel-default" style="height:100%;background-color:rgba(222,222,222,0.8)" >
  <div class="panel-heading">秒杀商品详情</div>
  <div class="panel-body">
    <span id="userTip"> 您还没有登录,请登陆后再操作<br/></span>
    <span>没有收货地址的提示。。。</span>
  </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="200" height="200" /></td>  
     </tr>
     <tr>  
        <td>秒杀开始时间</td>  
        <td id="startTime"></td>
        <td >   
            <input type="hidden" id="remainSeconds" />
            <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" />
            </form>-->
            <div class="row">
                <div class="form-inline">
                    <img id="verifyCodeImg" width="80" height="32"  style="display:none" onclick="refreshVerifyCode()"/>
                    <input id="verifyCode"  class="form-control" style="display:none"/>
                    <button class="btn btn-primary" type="button" id="buyButton"onclick="getMiaoshaPath()">立即秒杀</button>
                </div>
            </div>
            <input type="hidden" name="goodsId"  id="goodsId" />
        </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>

コアJSコード:

<script>

$(function(){
   getDetail();
});

function getDetail(){
   var goodsId = g_getQueryString("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 render(detail){
   var miaoshaStatus = detail.miaoshaStatus;
   var  remainSeconds = detail.remainSeconds;
   var goods = detail.goods;
   var user = detail.user;
   if(user){
      $("#userTip").hide();
   }
   $("#goodsName").text(goods.goodsName);
   $("#goodsImg").attr("src", goods.goodsImg);
   $("#startTime").text(new Date(goods.startDate).format("yyyy-MM-dd hh:mm:ss"));
   $("#remainSeconds").val(remainSeconds);
   $("#goodsId").val(goods.id);
   $("#goodsPrice").text(goods.goodsPrice);
   $("#miaoshaPrice").text(goods.miaoshaPrice);
   $("#stockCount").text(goods.stockCount);
   countDown(); // 判断秒杀开始状态
}

// 判断秒杀开始状态
function countDown(){
    var remainSeconds = $("#remainSeconds").val();
    var timeout;
    if(remainSeconds > 0){//秒杀还没开始,倒计时
       $("#buyButton").attr("disabled", true);
       $("#miaoshaTip").html("秒杀倒计时:"+remainSeconds+"秒");
        timeout = setTimeout(function(){
            $("#countDown").text(remainSeconds - 1);
            $("#remainSeconds").val(remainSeconds - 1);
            countDown();
        },1000);
    }else if(remainSeconds == 0){//秒杀进行中
        $("#buyButton").attr("disabled", false);
        if(timeout){
            clearTimeout(timeout);
        }
        $("#miaoshaTip").html("秒杀进行中");
        $("#verifyCodeImg").attr("src", "/miaosha/verifyCode?goodsId="+$("#goodsId").val());
        $("#verifyCodeImg").show();
        $("#verifyCode").show();
    }else{//秒杀已经结束
        $("#buyButton").attr("disabled", true);
        $("#miaoshaTip").html("秒杀已经结束");
        $("#verifyCodeImg").hide();
        $("#verifyCode").hide();
    }
}

</script>


図3は、サーバはJSON形式のデータを、データバインディングを行うには、静的なページを返すことに注意してください。




第三に、レンダリングクライアント(スパイク・インターフェース)

そして、第二の点を操作することは基本的に同じですが、また、動的なテンプレート言語の代わりにAJAXレンダリングを削除します。
異なった場所:
1)、さらにいくつかのspringboot構成;
2)GETとPOSTの違い、POSTはここで使用する必要があり、このような欠失などのいくつかのシーンは、ありますが、もし、このようなIDを削除GET = XXとして使用されるこのような文言,?その後、検索エンジンは自動的に削除を助けるためにスキャンし、その入力明記するようにしてくださいます。

1、springboot-1.5.xの構成

spring.resources.add-mappings=true #是否启用默认资源处理
spring.resources.cache-period= 3600 #缓存时间
spring.resources.chain.cache=true #是否在资源链中启用缓存
spring.resources.chain.enabled=true #是否启用Spring资源处理链。默认情况下,禁用,除非至少启用了一个策略。
spring.resources.chain.gzipped=true #是否对缓存压缩
spring.resources.chain.html-application-cache=true #是否启用HTML5应用程序缓存清单重写
spring.resources.static-locations=classpath:/static/ #静态资源的位置


2、公式設定springboot2.1.1

spring.resources.add-mappings=true # 是否启用默认资源处理
spring.resources.cache.cachecontrol.cache-private= # 表示响应消息是针对单个用户的,不能由共享缓存存储。
spring.resources.cache.cachecontrol.cache-public= # 表示任何缓存都可以存储响应
spring.resources.cache.cachecontrol.max-age= # 响应被缓存的最大时间,如果没有指定持续时间后缀,以秒为单位。
spring.resources.cache.cachecontrol.must-revalidate= # 表明,一旦缓存过期,在未与服务器重新验证之前,缓存不能使用响应。
spring.resources.cache.cachecontrol.no-cache= # 表示缓存的响应只有在服务器重新验证时才能重用
spring.resources.cache.cachecontrol.no-store= # 表示在任何情况下都不缓存响应
spring.resources.cache.cachecontrol.no-transform= # 指示中介(缓存和其他)它们不应该转换响应内容
spring.resources.cache.cachecontrol.proxy-revalidate= # 与“must-revalidate”指令的含义相同,只是它不适用于私有缓存。
spring.resources.cache.cachecontrol.s-max-age= # 响应被共享缓存缓存的最大时间,如果没有指定持续时间后缀,以秒为单位。
spring.resources.cache.cachecontrol.stale-if-error= # 当遇到错误时,响应可能使用的最大时间,如果没有指定持续时间后缀,以秒为单位。
spring.resources.cache.cachecontrol.stale-while-revalidate= # 如果没有指定持续时间后缀,则响应在过期后可以提供的最长时间(以秒为单位)。
spring.resources.cache.period= # 资源处理程序提供的资源的缓存周期。如果没有指定持续时间后缀,将使用秒。
spring.resources.chain.cache=true # 是否在资源链中启用缓存。
spring.resources.chain.compressed=false # 是否启用已压缩资源(gzip, brotli)的解析。
spring.resources.chain.enabled= # 是否启用Spring资源处理链。默认情况下,禁用,除非至少启用了一个策略。
spring.resources.chain.html-application-cache=false # 是否启用HTML5应用缓存清单重写。
spring.resources.chain.strategy.content.enabled=false # 是否启用内容版本策略。
spring.resources.chain.strategy.content.paths=/** # 应用于内容版本策略的以逗号分隔的模式列表。
spring.resources.chain.strategy.fixed.enabled=false # 是否启用固定版本策略。
spring.resources.chain.strategy.fixed.paths=/** # 用于固定版本策略的以逗号分隔的模式列表。
spring.resources.chain.strategy.fixed.version= # 用于固定版本策略的版本字符串。
spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/ # 静态资源的位置。


図3に示すように、第2のクリック点<今スパイク> JSメソッド呼び出しボタンgetMiaoshaPath()を次のように

<script>

function getMiaoshaPath(){
    var goodsId = $("#goodsId").val();
    g_showLoading();
    $.ajax({
        url:"/miaosha/path",
        type:"GET",
        data:{
            goodsId:goodsId,
            verifyCode:$("#verifyCode").val()
        },
        success:function(data){
            if(data.code == 0){
                var path = data.data;
                doMiaosha(path);
            }else{
                layer.msg(data.msg);
            }
        },
        error:function(){
            layer.msg("客户端请求有误");
        }
    });
}

function doMiaosha(path){
    $.ajax({
        url:"/miaosha/"+path+"/do_miaosha",
        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("客户端请求有误");
        }
    });
    
}

function getMiaoshaResult(goodsId){
    g_showLoading();
    $.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);
                    }, 200);
                }else{
                    layer.confirm("恭喜你,秒杀成功!查看订单?", {btn:["确定","取消"]},
                            function(){
                                window.location.href="/order_detail.htm?orderId="+result;
                            },
                            function(){
                                layer.closeAll();
                            });
                }
            }else{
                layer.msg(data.msg);
            }
        },
        error:function(){
            layer.msg("客户端请求有误");
        }
    });
}

</script>




第四に、オブジェクトキャッシュ

最も一般的に使用される基本的なキャッシング・ロジック:

  1. 失敗:、データキャッシュを取り始めるために得ることはありません、データベースから、成功の後、キャッシュにデータをフェッチするアプリケーション。
  2. ヒット:復帰後に採取されたキャッシュからのデータへのアプリケーションアクセスを。
  3. アップデート:データベースにデータを入れて、成功した後、キャッシュの無効化をしましょう。


    参照コード:
// 先查缓存,再查数据库。
public MiaoshaUser getById(long id) {
   //取缓存
   MiaoshaUser user = redisService.get(MiaoshaUserKey.getById, ""+id, MiaoshaUser.class);
   if(user != null) {
      return user;
   }
   //取数据库
   user = miaoshaUserDao.getById(id);
   if(user != null) {
      redisService.set(MiaoshaUserKey.getById, ""+id, user);
   }
   return user;
}

// 更新数据库后,缓存也要做同步更新。
public boolean updatePassword(String token, long id, String formPass) {
   //取user
   MiaoshaUser user = getById(id);
   if(user == null) {
      throw new GlobalException(CodeMsg.MOBILE_NOT_EXIST);
   }
   //更新数据库
   MiaoshaUser toBeUpdate = new MiaoshaUser();
   toBeUpdate.setId(id);
   toBeUpdate.setPassword(MD5Util.formPassToDBPass(formPass, user.getSalt()));
   miaoshaUserDao.update(toBeUpdate);
   //处理缓存
   redisService.delete(MiaoshaUserKey.getById, ""+id);
   user.setPassword(toBeUpdate.getPassword());
   redisService.set(MiaoshaUserKey.token, token, user);
   return true;
}




概要

  • サーバーレンダリング:テンプレートエンジン技術を使用するために、このようなキャッシュミドルウェアとして指定されたディレクトリやRedisのに静的なHTMLページを生成し、ディレクトリ内の静的なHTMLを直接指し示すページのアクセス・パス、このアプローチは、実際にはまだレンダリングするためにサーバーに属しています静的な方法。
  • クライアントのレンダリング:HTMLをレンダリングするために、元のテンプレート言語は、変更は、静的なファイル・ストレージ・パスを指定するには、ブラウザのキャッシュページを使用するように、純粋に静的なHTM / SHTML、その後、JS / AJAXレンダリングデータ、プラスの構成Spring構成ファイルであります道。これは、クライアントのレンダリングの分離、より良い性能の前後端に属する、推奨されます。
  • オブジェクトキャッシュ:オブジェクト・レベルのキャッシュは主にサービス内のオブジェクトの一部をキャッシュされ、我々はバッファをフェッチするために合理的な手順に従ってください、その後、データベースを取る必要があり、キャッシュが再びキャッシュされたオブジェクト、ノーリターン、データベースのデータ、そして最後に、データベースのデータを返しましたキャッシュに入れました。


    ます。http://blog.csdn.net/tTU1EvLDeLFq5btqiK/article/details/78693323あなたが興味キャッシュロジックがある場合は、このブログを参照することができます


おすすめ

転載: www.cnblogs.com/fulongyuanjushi/p/11367038.html