高并发之thymeleaf页面缓存&URL缓存

业务说明:

为提供并发能力,将页面缓存在Redis的中,过期时间为60秒。

先准备好我们的Redis的类

package com.example.miaosha_xdp.redis;

import com.example.miaosha_xdp.entity.Goods;

public class GoodsKey extends BasePrefix {
    private GoodsKey(int expireTime, String prefix) {
        super(expireTime, prefix);
    }
    public static GoodsKey getGoodsList=new GoodsKey(60,"goods_list");
    public static GoodsKey getGoodsDetail=new GoodsKey(60,"goods_detail");
}

然后是我们控制层代码

这里有一个坑:

SpringWebContext

SpringWebContext在高版本中被删除了。

页面缓存

 @Autowired
    private RedisService redisService;
    @Autowired
    private ThymeleafViewResolver thymeleafViewResolver;
    @Autowired
    private ApplicationContext applicationContext;

    @RequestMapping(value = "/to_list", produces = "text/html")
    @ResponseBody
    public String to_login(HttpServletRequest request,HttpServletResponse response, Model model, User user) {
        model.addAttribute(user);
        //取缓存
        String html = redisService.get(GoodsKey.getGoodsList, "", String.class);
        //缓存里面有页面,直接返回
        if (!StringUtils.isEmpty(html)) {
            return html;
        }
        //没有页面,进行封装和渲染
        List<GoodsVo> goodsList = goodsService.listGoodsVo();
        model.addAttribute("goodsList", goodsList);
        SpringWebContextUtil webContext = new SpringWebContextUtil(request, response,
                request.getServletContext(), request.getLocale(), model.asMap(), applicationContext);
        //手动渲染
        html = thymeleafViewResolver.getTemplateEngine().process("goods_list", webContext);
        logger.info(html);

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

URL缓存

@RequestMapping(value = "/to_detail/{goodsId}", produces = "text/html")
    @ResponseBody
    public String detail(HttpServletResponse response,HttpServletRequest  request,User user, Model model, @PathVariable("goodsId") Long id) {
        model.addAttribute(user);
        //取缓存
        String html = redisService.get(GoodsKey.getGoodsDetail, "", String.class);
        //缓存里面有页面,直接返回
        if (!StringUtils.isEmpty(html)) {
            return html;
        }
        //手动渲染
        GoodsVo goods = goodsService.getGoodsVoByGoodsId(id);
        model.addAttribute("goods", goods);
        miaoshaDetail(model, goods);
        SpringWebContextUtil webContext = new SpringWebContextUtil(request, response,
                request.getServletContext(), request.getLocale(), model.asMap(), applicationContext);
        //手动渲染
        html = thymeleafViewResolver.getTemplateEngine().process("goods_detail", webContext);
        if (!StringUtils.isEmpty(html)) {
            redisService.set(GoodsKey.getGoodsDetail, "", html);
        }
        return html;
    }

    private void miaoshaDetail(Model model, GoodsVo goods) {
        long start = goods.getStartDate().getTime();
        long end = goods.getEndDate().getTime();
        long now = System.currentTimeMillis();

        int miaoshaStatus = 0;
        int remainSeconds = 0;

        if (now < start) {
            miaoshaStatus = 0;
            remainSeconds = (int) ((start - now) / 1000);
        } else if (now > end) {
            miaoshaStatus = 2;
            remainSeconds = -1;
        } else {
            miaoshaStatus = 1;
            remainSeconds = 0;
        }

        model.addAttribute("miaoshaStatus", miaoshaStatus);
        model.addAttribute("remainSeconds", remainSeconds);
    }

所所以需要自己重写SpringWebContext方法

package com.example.miaosha_xdp.util;

import org.springframework.context.ApplicationContext;
import org.thymeleaf.context.AbstractContext;
import org.thymeleaf.context.IWebContext;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Locale;
import java.util.Map;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;


public class SpringWebContextUtil  extends AbstractContext implements IWebContext {

    private final HttpServletRequest request;
    private final HttpServletResponse response;
    private final ServletContext servletContext;

    public static final String BEANS_VARIABLE_NAME = "beans";
    private static final ConcurrentHashMap<ApplicationContext, HashMap<String, Object>> variableMapPrototypes = new ConcurrentHashMap();
    private final ApplicationContext applicationContext;

    public SpringWebContextUtil(final HttpServletRequest request,
                                final HttpServletResponse response,
                                final ServletContext servletContext,
                                final Locale locale,
                                final Map<String, Object> variables,
                                final ApplicationContext appctx){
        super(locale,addSpringSpecificVariables(variables, appctx));
        this.request = request;
        this.response = response;
        this.servletContext = servletContext;
        this.applicationContext = appctx;

    }

    private static Map<String, Object> addSpringSpecificVariables(Map<String, ?> variables, ApplicationContext appctx) {
        HashMap<String, Object> variableMapPrototype = (HashMap)variableMapPrototypes.get(appctx);
        if (variableMapPrototype == null) {
            variableMapPrototype = new HashMap(20, 1.0F);
            ContexBeans beans = new ContexBeans(appctx);
            variableMapPrototype.put("beans", beans);
            variableMapPrototypes.put(appctx, variableMapPrototype);
        }

        Map newVariables;
        synchronized(variableMapPrototype) {
            newVariables = (Map)variableMapPrototype.clone();
        }

        if (variables != null) {
            newVariables.putAll(variables);
        }

        return newVariables;
    }

    public ApplicationContext getApplicationContext() {
        return this.applicationContext;
    }

    public HttpServletRequest getRequest() {
        return this.request;
    }

    public HttpSession getSession() {
        return this.request.getSession(false);
    }

    public HttpServletResponse getResponse() {
        return this.response;
    }

    public ServletContext getServletContext() {
        return this.servletContext;
    }
}

bean类也要自己写 

package com.example.miaosha_xdp.util;

import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import org.springframework.context.ApplicationContext;
import org.thymeleaf.util.Validate;

public class ContexBeans implements Map<String, Object> {
    private final ApplicationContext ctx;

    public ContexBeans(ApplicationContext ctx) {
        Validate.notNull(ctx, "Application Context cannot be null");
        this.ctx = ctx;
    }

    public boolean containsKey(Object key) {
        Validate.notNull(key, "Key cannot be null");
        return this.ctx.containsBean(key.toString());
    }

    public Object get(Object key) {
        Validate.notNull(key, "Key cannot be null");
        return this.ctx.getBean(key.toString());
    }

    public Set<String> keySet() {
        return new LinkedHashSet(Arrays.asList(this.ctx.getBeanDefinitionNames()));
    }

    public int size() {
        return this.ctx.getBeanDefinitionCount();
    }

    public boolean isEmpty() {
        return this.ctx.getBeanDefinitionCount() <= 0;
    }

    public boolean containsValue(Object value) {
        throw new UnsupportedOperationException("Method \"containsValue\" not supported in Beans object");
    }

    public Object put(String key, Object value) {
        throw new UnsupportedOperationException("Method \"put\" not supported in Beans object");
    }

    public void putAll(Map<? extends String, ?> m) {
        throw new UnsupportedOperationException("Method \"putAll\" not supported in Beans object");
    }

    public Object remove(Object key) {
        throw new UnsupportedOperationException("Method \"remove\" not supported in Beans object");
    }

    public void clear() {
        throw new UnsupportedOperationException("Method \"clear\" not supported in Beans object");
    }

    public Collection<Object> values() {
        throw new UnsupportedOperationException("Method \"values\" not supported in Beans object");
    }

    public Set<Entry<String, Object>> entrySet() {
        throw new UnsupportedOperationException("Method \"entrySet\" not supported in Beans object");
    }

}

猜你喜欢

转载自blog.csdn.net/weixin_42545256/article/details/84960872
今日推荐