秒殺システムページ最適化技術商品詳細ページ静的化(前後端分離)
86309 ワード
ページの静的化+前後の分離常用技術AngularJS、Vue.js の利点:ブラウザのキャッシュ を利用する
上記の方法は複雑で,jQueryを用いてページの静的化をシミュレートするだけである.
ユーザーのブラウザにページを直接キャッシュするメリット:ユーザーがデータにアクセスするときは、サーバを要求することなく、ローカルキャッシュで必要なページキャッシュを直接取得することができます.未作ページ静化:あるページを要求し、キャッシュにアクセスし、キャッシュにあるかどうかを確認し、キャッシュに直接戻りがあるかどうかを確認し、キャッシュにない場合は、htmlページにデータをレンダリングしてキャッシュに保存し、htmlページ全体をクライアントに表示します. はページの静的化を行いました:初めてバックグラウンドでレンダリングするhtmlページを要求して、それからの要求はすべて直接ユーザーのローカルブラウザのキャッシュのhtmlページにアクセスして、静的な資源、それからフロントエンドはAjaxを通じてバックエンドにアクセスして、ページの表示するデータを取得して帰るだけでいいです.
商品詳細ページの静的化以前の操作では、商品詳細ページをredisキャッシュしました.このインタフェースは、対応する製品詳細や秒殺カウントダウンなどの情報を示すだけで、いくつかの重要な情報を表示すればよいので、他のものは静的化することができます.この技術は、実際にはフロントエンドが2つの部分に分かれており、一部は変更されないhtmlブロックであり、もう1つはデータであり、バックエンドがフロントエンドにデータを転送すれば、ajax技術を用いてデータを要求することができる.
ブラウザ側でキャッシュを行う、キャッシュ時間を制御するためにアプリケーション.propertiesに静的リソース構成項目を追加します.
staticリソースフォルダの下に静的リソースページファイルを新規作成します(.html形式で終わります).ここではなぜ使用できませんか.htmlファイルの末尾は、変更しないで引き続き使用するためです.html接尾辞、システムはデフォルトでtemplatesの下の同名のファイルを探して、だから私達はそれを修正して区別を示します
GoodsDetailVoパッケージを定義して、ページに値を転送します.
商品リストページ(goods_list.html)のジャンプロジックを改造し、ジャンプリクエスト前のリクエストパスを変更します.
現在のリクエストパス:
私たちは今、サービス側にジャンプを要求する必要はありません.クライアントの静的リソースに直接行って、商品の詳細を要求します.detail.html、ここで接尾辞の名前を変更することに注意してください.
以前の商品詳細ページを変更し、thymeleafが持つラベルを削除して、最も初期のhtml静的ページにします(現在、静的ページにはthymeleafは必要ありません)、idを使用して各コンポーネントを識別するように変更します.
goodsに移動したばかりですdetail.htmページの場合、jsは初期化され、を実行します.
getDetailメソッド:
getDetail()メソッドajax非同期リクエストバックグラウンドを使用してページに必要なデータを取得し、データを取得した後にrender()メソッドを呼び出して静的ページをレンダリングします.getDetailで最初のステップは、listページの商品詳細リクエストが
商品詳細はリンクをクリックして私たちの商品のgoodsIdが入っています.では、getQueryStringで要求パスurlのパラメータの値を取得します.
パラメータを取得すると、バックエンドインタフェースを要求し、データを取得してレンダリングできます.
カウントダウンcountDown()メソッド:
バックエンドGoodsControllerで商品詳細ページのリクエストを受信するインタフェースを次のコードに変更します:
goods_detail.htmフルコード:
上記の方法は複雑で,jQueryを用いてページの静的化をシミュレートするだけである.
ユーザーのブラウザにページを直接キャッシュするメリット:ユーザーがデータにアクセスするときは、サーバを要求することなく、ローカルキャッシュで必要なページキャッシュを直接取得することができます.
商品詳細ページの静的化以前の操作では、商品詳細ページを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>