妇联网站建设背景,网站做微信支付宝支付宝,常州第一门户网,windows系统怎么做ppt下载网站登录方式调整第1步#xff1a;从zmall-common的pom.xml中移除spring-session-data-redis依赖注意#xff1a;本章节中不采用spring-session方式#xff0c;改用redis直接存储用户登录信息#xff0c;主要是为了方便之后的jmeter压测#xff1b;2#xff09;这里只注释调用…登录方式调整第1步从zmall-common的pom.xml中移除spring-session-data-redis依赖注意本章节中不采用spring-session方式改用redis直接存储用户登录信息主要是为了方便之后的jmeter压测2这里只注释调用spring-session的依赖保留redis的依赖第2步在zmall-common公共模块中定义RedisConfig配置类Configuration
public class RedisConfig {Beanpublic RedisTemplateString,Object restTemplate(RedisConnectionFactory redisConnectionFactory){RedisTemplateString,Object redisTemplatenew RedisTemplate();//String类型Key序列化redisTemplate.setKeySerializer(new StringRedisSerializer());//String类型Value序列化redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());//Hash类型Key序列化redisTemplate.setHashKeySerializer(new StringRedisSerializer());//Hash类型Value序列化redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());redisTemplate.setConnectionFactory(redisConnectionFactory);return redisTemplate;}
}这里一定要注意最后在将RedisConnectionFactory设置到RedisTemplate中不要在最前做该步操作不然会导致String和Hash类型的序列化无效将采用默认的JdkSerializationRedisSerializer进行序列化从而导致保存的key前缀出现乱码问题。细心细心细心o(╥﹏╥)o参考地址https://blog.csdn.net/hunger_wang/article/details/118713579?spm1001.2014.3001.5501第3步在zmall-common公共模块中配置redis相关服务IRedisServciepublic interface IRedisService {/*** 将登陆用户对象保存到Redis中并以token来命名* param token* param user*/void setUserToRedis(String token, User user);/*** 根据token令牌从Redis中获取User对象* param token* return*/User getUserByToken(String token);
}RedisServcieImpleService
public class RedisServiceImpl implements IRedisService {Autowiredprivate RedisTemplateString,Object redisTemplate;Overridepublic void setUserToRedis(String token, User user) {String keyuser:token;redisTemplate.boundValueOps(key).set(user,7200,TimeUnit.SECONDS);}Overridepublic User getUserByToken(String token) {return (User) redisTemplate.opsForValue().get(user:token);}
}用户登录成功后将用户对象保存到Redis中并设置超时时间7200秒。第4步在zmall-common公共模块中配置配置自定义参数解析UserArgumentResolver、WebConfigUserArgumentResolver/*** 自定义用户参数类*/
Component
public class UserArgumentResolver implements HandlerMethodArgumentResolver {Autowiredprivate IRedisService redisService;/*** 只有supportsParameter方法执行返回true才能执行下面的resolveArgument方法* param methodParameter* return*/Overridepublic boolean supportsParameter(MethodParameter methodParameter) {Class? type methodParameter.getParameterType();return type User.class;}Overridepublic Object resolveArgument(MethodParameter methodParameter,ModelAndViewContainer modelAndViewContainer,NativeWebRequest nativeWebRequest,WebDataBinderFactory webDataBinderFactory) throws Exception {HttpServletRequest req (HttpServletRequest) nativeWebRequest.getNativeRequest();//从cookie获取token令牌String token CookieUtils.getCookieValue(req, token);//判断cookie中的token令牌是否为空if(StringUtils.isEmpty(token))throw new BusinessException(JsonResponseStatus.TOKEN_ERROR);//根据token令牌获取redis中存储的user对象方便jmeter测试User user redisService.getUserByToken(token);if(nulluser)throw new BusinessException(JsonResponseStatus.TOKEN_ERROR);return user;}
}WebConfigComponent
public class WebConfig implements WebMvcConfigurer {Autowiredprivate UserArgumentResolver userArgumentResolver;Overridepublic void addArgumentResolvers(ListHandlerMethodArgumentResolver resolvers) {resolvers.add(userArgumentResolver);}Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {//添加静态资源访问映射//registry.addResourceHandler(/static/**)// .addResourceLocations(classpath:/static/);}
}第5步用户登录业务调整将spring-session方式更改为redis方式存储登录用户信息。//5.通过UUID生成token令牌并保存到cookie中
String token UUID.randomUUID().toString().replace(-,);
//将随机生成的Token令牌保存到Cookie中并设置1800秒超时时间
CookieUtils.setCookie(req,resp,token,token,7200);
//6.将token令牌与spring session进行绑定并存入redis中
//HttpSession session req.getSession();
//session.setAttribute(token,us);
//将token令牌与user绑定后存储到redis中方便jmeter测试
redisService.setUserToRedis(token,us);这里采用Redis方式直接存储登录用户信息只为后续使用Jmeter压测时提供便利。正常运行使用项目还是可以使用spring-session方式。第6步修改商品服务zmall-product模块中的index方法将之前从HttpSession中获取登录用户信息改换成User对象参数方式RequestMapping(/index.html)public String index(Model model, User user){ System.out.println(user);}在调用index方法之前先由自定义的参数解析器进行参数解析并返回解析结果User所以在这里可直接在方法参数中获取的User对象。第7步重启zmall-user和zmall-product模块完成用户登录后直接在浏览器地址栏输入http://zmall.com/product-serv/index.html查看zmall-product模块中的控制台是否已经获取到登录用户对象信息。生成秒杀订单绑定秒杀商品添加sellDetail.html页面到zmall-product模块中实现首页秒杀商品展示必须保证秒杀商品状态为已激活、且秒杀商品的活动时间为有效时间范围之内。index.html #if kills??#list kills as gdiv classsell_${g_index?if_exists1}div classsb_imga href${ctx}/sellDetail.html?pid${g.item_id}img src${g.fileName} width242 height356 //a/divdiv classs_pricespan${g.price}/span/divdiv classs_nameh2a href${ctx}/sellDetail.html?pid${g.item_id}${g.name}/a/h2倒计时span1200/span 时 span30/span 分 span28/span 秒/div/div/#list/#ifsellDetail.htmltable border0 stylewidth:100%; margin-bottom:50px; cellspacing0 cellpadding0tr valigntoptd width315div classlim_name${(prod.name)!}/divdiv classlim_pricespan classch_txt${(prod.price)!}/spana hrefjavascript:void(0); classch_a pid${(prod.item_id)!} price${(prod.price)!}抢购/a/divdiv classlim_ctable border0 stylewidth:100%; color:#888888; cellspacing0 cellpadding0trtd width35%市场价 /tdtd width65%折扣/td/trtr stylefont-family:Microsoft YaHei;td styletext-decoration:line-through;${(prod.price)!}/tdtd8.0/td/tr/table/divdiv classlim_cdiv classdes_choicespan classfl型号/spanulli classchecked30mldiv classch_img/div/lili50mldiv classch_img/div/lili100mldiv classch_img/div/li/ul/divdiv classdes_choicespan classfl颜色/spanulli红色div classch_img/div/lili classchecked白色div classch_img/div/lili黑色div classch_img/div/li/ul/div/divdiv classlim_cspan classfl数量/spaninput typetext value${(prod.total)!} classlim_ipt //divdiv classlim_clock距离团购结束还有br /span1200 时 30 分 28 秒/span/div/tdtd width525 aligncenter styleborder-left:1px solid #eaeaea;img src${(prod.fileName)!} width460 height460 //td/tr/tableweb层RequestMapping(/index.html)public ModelAndView toIndex(User user){System.out.println(user JSON.toJSONString(user));ModelAndView mvnew ModelAndView();//获取热卖商品列表ListProduct hot productService.list(new QueryWrapperProduct().orderByDesc(hot).last(limit 4));//获取显示秒杀商品ListMapString, Object maps productService.queryKillProdNews();mv.addObject(kills,maps);mv.addObject(hots,hot);mv.setViewName(index);return mv;}service层public interface IProductService extends IServiceProduct {void updateStock(Integer pid,Integer num);/*** 首页显示秒杀商品查询* return*/ListMapString,Object queryKillProdNews();/*** 根据商品ID查询秒杀商品信息* param pid 秒杀商品ID* return*/MapString,Object queryKillProdById(Integer pid);
}Overridepublic ListMapString, Object queryKillProdNews() {return productMapper.queryKillProdNews();}Overridepublic MapString, Object queryKillProdById(Integer pid) {return productMapper.queryKillProdById(pid);}mapper层Repository
public interface ProductMapper extends BaseMapperProduct {
// MapKey(queryKillProdNews)ListMapString,Object queryKillProdNews();MapString,Object queryKillProdById(Integer pid);
}productMapper.xmlselect idqueryKillProdNews resultTypejava.util.Mapselectk.id,k.item_id,p.name,p.price,p.fileNamefromzmall_kill k,zmall_product pwhere k.item_idp.id andk.is_active1 and(now() between start_time and end_time)order by k.create_time desclimit 4/selectselect idqueryKillProdById resultTypejava.util.Mapselectk.id,k.item_id,k.total,p.name,p.price,p.fileNamefromzmall_kill k,zmall_product pwhere k.item_idp.id and k.is_active1 and item_id#{value}/select查看秒杀商品点击限时秒杀中的秒杀商品根据秒杀商品ID查询秒杀商品详情信息并跳转到sellDetail.html页面展示秒杀商品信息。RequestMapping(/sellDetail.html)public String sellDetail(RequestParam Integer pid, Model model){//根据商品ID查询秒杀商品信息MapString, Object prod productService.queryKillProdById(pid);model.addAttribute(prod,prod);return sellDetails;}订单秒杀移除seata相关第1步先注释掉zmall-order和zmall-product模块中的seata依赖第2步分别删掉zmall-order和zmall-product模块中resources目录下的bootstrap.xml和register.conf文件seata分布式事务进行jmeter压测秒杀订单接口效率太低1000个并发请求吞吐量为4.5/so(╥﹏╥)o生成秒杀订单将SnowFlake雪花ID生成工具类导入到zmall-common模块中utils然后再生成秒杀订单时使用雪花ID来充当秒杀订单编号在zmall-order模块中完成秒杀订单生成工作。IOrderServicepublic interface IOrderService extends IServiceOrder {Order createOrder(Integer pid,Integer num);/*** 生成秒杀订单* param user 登陆用户对象* param pid 秒杀商品ID* param price 秒杀商品价格* return*/JsonResponseBody? createKillOrder(User user, Integer pid, Float price);
}OrderServiceImplAutowired
private KillServiceImpl killService;
Autowired
private OrderDetailServiceImpl orderDetailService;TransactionalOverridepublic JsonResponseBody? createKillOrder(User user, Integer pid, Float price) {//1.根据秒杀商品编号获取秒杀商品库存是否为空Kill kill killService.getOne(new QueryWrapperKill().eq(item_id,pid));if(kill.getTotal()1)throw new BusinessException(JsonResponseStatus.STOCK_EMPTY);//2.秒杀商品库存减一killService.update(new UpdateWrapperKill().eq(item_id,pid).setSql(totaltotal-1));//3.生成秒杀订单及订单项SnowFlake snowFlakenew SnowFlake(2,3);Long orderIdsnowFlake.nextId();int orderIdInt new Long(orderId).intValue();//创建订单Order ordernew Order();order.setUserId(user.getId());order.setLoginName(user.getLoginName());order.setCost(price);order.setSerialNumber(orderIdInt);this.save(order);//创建订单项OrderDetail orderDetailnew OrderDetail();orderDetail.setOrderId(orderIdInt);orderDetail.setProductId(pid);orderDetail.setQuantity(1);orderDetail.setCost(price);orderDetailService.save(orderDetail);return new JsonResponseBody();}OrderControllerRequestMapping(/createKillOrder/{pid}/{price})ResponseBodypublic JsonResponseBody? createKillOrder(User user,PathVariable(pid) Integer pid,PathVariable(price) Float price){return orderService.createKillOrder(user,pid,price);}前端页面秒杀测试在sellDetail.html页面中添加订单秒杀JS方法。script$(function(){$(.ch_a).click(function(){let pid$(this).attr(alt);console.log(pid);$.post(http://zmall.com/order-serv/createKillOrder,{pid:pid},function(rs){console.log(rs);if(rs.code200)alert(秒杀成功);elsealert(rs.msg);},json);});});
/script这里虽然已经能正常展示秒杀效果但是还是存在很多问题比如重复抢购问题等等问题。注意 $.post(http://user.zmall.com/userLogin,{loginName:loginName,password:password},function(rs){console.log(rs);if(rs.code200){location.hrefhttp://product.zmall.com/index.html;}else{alert(rs.msg);}},json);post方式不能跨二级域名发送请求location.href可以跨二级域名发送请求$(function(){$(.ch_a).click(function(){let pid$(this).attr(pid);let price$(this).attr(price);console.log(pid%s,price%s,pid,price);$.post(http://zmall.com/order-serv/createKillOrder/pid/price,{},function(rs){console.log(rs);if(rs.code200)alert(秒杀成功);elsealert(rs.msg);},json);});});$.post(http://zmall.com/order-serv/createKillOrder/pid/price,{},function(rs){});能够正常访问$.post(http://order.zmall.com/createKillOrder/pid/price,{},function(rs){});则会出现跨域问题