code clean

This commit is contained in:
qiurunze123 2018-12-08 16:41:34 +08:00
parent df23e07856
commit 993280d5fd
31 changed files with 357 additions and 575 deletions

View File

@ -20,7 +20,7 @@
#### [提交合并代码规范](/docs/code-criterion.md)
>> 秒杀注意事项
> 秒杀注意事项
#### [1.如何解决卖超问题]()
--在sql加上判断防止数据边为负数
--数据库加唯一索引防止用户重复购买

View File

@ -1,4 +1,4 @@
package com.geekq.miaosha;
package com.geekq.miaosha.common;
import java.util.Date;
import java.util.concurrent.TimeUnit;

View File

@ -1,27 +0,0 @@
package com.geekq.miaosha.common;
/**
* 响应类
*/
public enum ResponseCode {
SUCCESS(0, "SUCCESS"),
ERROR(1, "ERROR"),
NEED_LOGIN(10, "NEED_LOGIN"),
ILLEGAL_ARGUMENT(2, "ILLEGAL_ARGUMENT");
private final int code;
private final String desc;
private ResponseCode(int code, String desc) {
this.code = code;
this.desc = desc;
}
public int getCode() {
return code;
}
public String getDesc() {
return desc;
}
}

View File

@ -1,78 +0,0 @@
package com.geekq.miaosha.common;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.io.Serializable;
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
//保证序列化的时候 不会有空
public class ServerResponse<T> implements Serializable {
private int status ;
private String msg ;
private T data ;
private ServerResponse( int status ){
this.status =status;
}
private ServerResponse( int status ,T data){
this.status =status;
this.data = data;
}
private ServerResponse( int status ,String msg ,T data){
this.status =status;
this.msg = msg ;
this.data = data;
}
private ServerResponse( int status ,String msg ){
this.status =status;
this.msg = msg ;
}
@JsonIgnore
public boolean isSuccess(){
return this.status == ResponseCode.SUCCESS.getCode();
}
public int getStatus() {
return status;
}
public String getMsg() {
return msg;
}
public T getData() {
return data;
}
public static <T> ServerResponse<T> createBySuccess(){
return new ServerResponse<T>(ResponseCode.SUCCESS.getCode());
}
public static <T> ServerResponse<T> createBySuccessMessage(String msg){
return new ServerResponse<T>(ResponseCode.SUCCESS.getCode(),msg);
}
public static <T> ServerResponse<T> createBySuccess(T data){
return new ServerResponse<T>(ResponseCode.SUCCESS.getCode(),data);
}
public static <T> ServerResponse<T> createBySuccess(String msg,T data){
return new ServerResponse<T>(ResponseCode.SUCCESS.getCode(),msg,data);
}
public static <T> ServerResponse<T> createByError(){
return new ServerResponse<T>(ResponseCode.ERROR.getCode(),ResponseCode.ERROR.getDesc());
}
public static <T> ServerResponse<T> createByErrorMessage(String errorMsg){
return new ServerResponse<T>(ResponseCode.ERROR.getCode(),errorMsg);
}
public static <T> ServerResponse<T> createByErrorCodeMessage(int errorCode , String errorMsg){
return new ServerResponse<T>(errorCode,errorMsg);
}
}

View File

@ -1,4 +1,4 @@
package com.geekq.miaosha;
package com.geekq.miaosha.common;
import java.util.ArrayList;
import java.util.List;

View File

@ -1,19 +1,65 @@
package com.geekq.miaosha.common.enums;
/**
* 普通返回类
* 1打头 系统系列错误
* 2 注册登录系列错误
* 3 check 系列错误
* 4 秒杀错误
* 5 商品错误
* 6 订单错误
* @author qiurunze
*/
public enum ResultStatus {
SUCCESS(0, "成功"),
FAILD(-1, "失败"),
EXCEPTION(-1, "系统异常"),
PARAM_ERROR(1000, "参数错误"),
SYSTEM_ERROR(1001, "系统错误"),
FILE_NOT_EXIST(1001, "文件不存在"),
FILE_NOT_DOWNLOAD(1002, "文件没有下载"),
FILE_NOT_GENERATE(1003, "文件没有生成"),
FILE_NOT_STORAGE(1004, "文件没有入库"),
SYSTEM_DB_ERROR(1005, "数据库系统错误"),
FILE_ALREADY_DOWNLOAD(1003, "文件已经下载"),
DATA_ALREADY_PEXISTS(1006, "数据已经存在");
PARAM_ERROR(10000, "参数错误"),
SYSTEM_ERROR(10001, "系统错误"),
FILE_NOT_EXIST(10002, "文件不存在"),
FILE_NOT_DOWNLOAD(10003, "文件没有下载"),
FILE_NOT_GENERATE(10004, "文件没有生成"),
FILE_NOT_STORAGE(10005, "文件没有入库"),
SYSTEM_DB_ERROR(10006, "数据库系统错误"),
FILE_ALREADY_DOWNLOAD(10007, "文件已经下载"),
DATA_ALREADY_PEXISTS(10008, "数据已经存在"),
/**
* 注册登录
*/
RESIGETR_SUCCESS(20000,"注册成功!"),
RESIGETER_FAIL(200001,"注册失败!"),
/**
* check
*/
BIND_ERROR (30001,"参数校验异常:%s"),
ACCESS_LIMIT_REACHED (30002,"请求非法!"),
REQUEST_ILLEGAL (30004,"访问太频繁!"),
SESSION_ERROR (30005,"Session不存在或者已经失效!"),
PASSWORD_EMPTY (30006,"登录密码不能为空!"),
MOBILE_EMPTY (30007,"手机号不能为空!"),
MOBILE_ERROR (30008,"手机号格式错误!"),
MOBILE_NOT_EXIST (30009,"手机号不存在!"),
PASSWORD_ERROR (30010,"密码错误!"),
/**
* 订单模块
*/
ORDER_NOT_EXIST(60001,"订单不存在"),
/**
* 秒杀模块
*/
MIAO_SHA_OVER(40001,"商品已经秒杀完毕"),
REPEATE_MIAOSHA(40002,"不能重复秒杀"),
MIAOSHA_FAIL(40003,"秒杀失败");
/**
* 商品模块
*/
private int code;
private String message;
@ -49,4 +95,8 @@ public enum ResultStatus {
public String toString() {
return this.getName();
}
private ResultStatus(Object... args) {
this.message = String.format(this.message, args);
}
}

View File

@ -8,10 +8,17 @@ public class AbstractResult {
private String message;
protected AbstractResult(ResultStatus status, String message) {
this.code = status.getCode();
this.status = status;
this.message = message;
}
protected AbstractResult(ResultStatus status) {
this.code = status.getCode();
this.message = status.getMessage();
this.status = status;
}
public static boolean isSuccess(AbstractResult result) {
return result != null && result.status == ResultStatus.SUCCESS && result.getCode() == ResultStatus.SUCCESS.getCode();
}
@ -37,7 +44,6 @@ public class AbstractResult {
this.status = ResultStatus.SUCCESS;
return this;
}
public ResultStatus getStatus() {
return this.status;
}

View File

@ -1,45 +0,0 @@
package com.geekq.miaosha.common.resultbean;
import com.geekq.miaosha.common.enums.ResultStatus;
import java.io.Serializable;
public class Result<T> extends AbstractResult implements Serializable {
private static final long serialVersionUID = 867933019328199779L;
private T value;
private Integer count;
protected Result(ResultStatus status, String message) {
super(status, message);
}
public static <T> Result<T> build() {
return new Result(ResultStatus.SUCCESS, (String)null);
}
public static <T> Result<T> build(String message) {
return new Result(ResultStatus.SUCCESS, message);
}
public T getValue() {
return this.value;
}
public void setValue(T value) {
this.value = value;
}
public Integer getCount() {
return this.count;
}
public void setCount(Integer count) {
this.count = count;
}
public void success(T value) {
this.success();
this.value = value;
this.count = 0;
}
}

View File

@ -0,0 +1,54 @@
package com.geekq.miaosha.common.resultbean;
import com.geekq.miaosha.common.enums.ResultStatus;
import com.geekq.miaosha.result.CodeMsg;
import com.geekq.miaosha.result.Result;
import java.io.Serializable;
public class ResultGeekQ<T> extends AbstractResult implements Serializable {
private static final long serialVersionUID = 867933019328199779L;
private T data;
private Integer count;
protected ResultGeekQ(ResultStatus status, String message) {
super(status, message);
}
protected ResultGeekQ(ResultStatus status) {
super(status);
}
public static <T> ResultGeekQ<T> build() {
return new ResultGeekQ(ResultStatus.SUCCESS, (String)null);
}
public static <T> ResultGeekQ<T> build(String message) {
return new ResultGeekQ(ResultStatus.SUCCESS, message);
}
public static <T> ResultGeekQ<T> error(ResultStatus status) {
return new ResultGeekQ<T>(status);
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Integer getCount() {
return this.count;
}
public void setCount(Integer count) {
this.count = count;
}
public void success(T value) {
this.success();
this.data = value;
this.count = 0;
}
}

View File

@ -1,16 +1,14 @@
package com.geekq.miaosha.dao;
import java.sql.SQLException;
import javax.sql.DataSource;
package com.geekq.miaosha.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import javax.sql.DataSource;
import java.sql.SQLException;
@Configuration
@ConfigurationProperties(prefix="spring.datasource")

View File

@ -24,17 +24,9 @@ public class UserArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest webRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
// HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
// HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
//
// String paramToken = request.getParameter(MiaoShaUserService.COOKIE_NAME_TOKEN);
// String cookieToken = getCookieValue(request, MiaoShaUserService.COOKIE_NAME_TOKEN);
// if(StringUtils.isEmpty(cookieToken) && StringUtils.isEmpty(paramToken)) {
// return null;
// }
// String token = StringUtils.isEmpty(paramToken)?cookieToken:paramToken;
// return userService.getByToken(response, token);
//threadlocal 存储线程副本 保证线程不冲突
/**
* threadlocal 存储线程副本 保证线程不冲突
*/
return UserContext.getUser();
}

View File

@ -13,19 +13,19 @@ import java.util.List;
public class WebConfig extends WebMvcConfigurerAdapter {
@Autowired
UserArgumentResolver userArgumentResolver;
UserArgumentResolver resolver;
@Autowired
private AccessInterceptor accessInterceptor;
private AccessInterceptor interceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
super.addInterceptors(registry);
registry.addInterceptor(accessInterceptor);
registry.addInterceptor(interceptor);
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(userArgumentResolver);
argumentResolvers.add(resolver);
}
}

View File

@ -1,76 +0,0 @@
package com.geekq.miaosha.controller;
import com.geekq.miaosha.domain.User;
import com.geekq.miaosha.redis.RedisService;
import com.geekq.miaosha.redis.Userkey;
import com.geekq.miaosha.result.CodeMsg;
import com.geekq.miaosha.result.Result;
import com.geekq.miaosha.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;
@Controller
@RequestMapping("/demo")
public class DemoController {
@Autowired
private UserService userService ;
@Autowired
private RedisService redisService;
@RequestMapping("/")
@ResponseBody
String home(){
return "hello world" ;
}
@RequestMapping("/user")
@ResponseBody
public Result<User> user(){
User user = userService.getById(1);
return Result.success(user) ;
}
@RequestMapping("/hello")
@ResponseBody
public Result<String> hello(){
return Result.success("hello world!");
}
@RequestMapping("/helloError")
@ResponseBody
public Result<String> helloError(){
Map<String,String> map = new HashMap<String, String>() ;
map.put("a","1") ;
return Result.error(CodeMsg.SERVER_ERROR) ;
}
@RequestMapping("/thymeleaf")
public String thymeleaf(Model model ){
model.addAttribute("name","world") ;
return "hello" ;
}
@RequestMapping("/redis/set")
@ResponseBody
public Result<Boolean> redis(){
User user = userService.getById(1);
boolean ret = redisService.set(Userkey.getById,""+1,user);
return Result.success(ret);
}
@RequestMapping("/redis/get")
@ResponseBody
public Result<User> redisG(){
User user = redisService.get(Userkey.getById,""+1,User.class) ;
return Result.success(user) ;
}
}

View File

@ -1,5 +1,6 @@
package com.geekq.miaosha.controller;
import com.geekq.miaosha.common.resultbean.ResultGeekQ;
import com.geekq.miaosha.domain.MiaoshaUser;
import com.geekq.miaosha.redis.GoodsKey;
import com.geekq.miaosha.redis.RedisService;
@ -40,7 +41,7 @@ public class GoodsController {
private GoodsService goodsService;
@Autowired
ThymeleafViewResolver thymeleafViewResolver;
ThymeleafViewResolver viewResolver;
@Autowired
ApplicationContext applicationContext;
@ -64,7 +65,7 @@ public class GoodsController {
SpringWebContext ctx = new SpringWebContext(request,response,
request.getServletContext(),request.getLocale(), model.asMap(), applicationContext );
//手动渲染
html = thymeleafViewResolver.getTemplateEngine().process("goods_list", ctx);
html = viewResolver.getTemplateEngine().process("goods_list", ctx);
if(!StringUtils.isEmpty(html)) {
redisService.set(GoodsKey.getGoodsList, "", html);
}
@ -108,7 +109,7 @@ public class GoodsController {
SpringWebContext ctx = new SpringWebContext(request,response,
request.getServletContext(),request.getLocale(), model.asMap(), applicationContext );
html = thymeleafViewResolver.getTemplateEngine().process("goods_detail", ctx);
html = viewResolver.getTemplateEngine().process("goods_detail", ctx);
if(!StringUtils.isEmpty(html)) {
redisService.set(GoodsKey.getGoodsDetail, ""+goodsId, html);
}
@ -124,8 +125,9 @@ public class GoodsController {
*/
@RequestMapping(value="/detail/{goodsId}")
@ResponseBody
public Result<GoodsDetailVo> detail(HttpServletRequest request, HttpServletResponse response, Model model,MiaoshaUser user,
public ResultGeekQ<GoodsDetailVo> detail(HttpServletRequest request, HttpServletResponse response, Model model,MiaoshaUser user,
@PathVariable("goodsId")long goodsId) {
ResultGeekQ<GoodsDetailVo> result = ResultGeekQ.build();
GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
long startAt = goods.getStartDate().getTime();
long endAt = goods.getEndDate().getTime();
@ -147,6 +149,7 @@ public class GoodsController {
vo.setUser(user);
vo.setRemainSeconds(remainSeconds);
vo.setMiaoshaStatus(miaoshaStatus);
return Result.success(vo);
result.setData(vo);
return result;
}
}

View File

@ -1,88 +1,39 @@
package com.geekq.miaosha.controller;
import com.geekq.miaosha.dao.UserMapper;
import com.geekq.miaosha.domain.MiaoshaUser;
import com.geekq.miaosha.result.Result;
import com.geekq.miaosha.common.resultbean.ResultGeekQ;
import com.geekq.miaosha.service.MiaoShaUserService;
import com.geekq.miaosha.vo.LoginVo;
import org.apache.ibatis.annotations.Mapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
@Controller
@RequestMapping("/login")
public class LoginController {
private static Logger log = LoggerFactory.getLogger(LoginController.class);
private static Logger logger = LoggerFactory.getLogger(LoginController.class);
@Autowired
private MiaoShaUserService userService;
@Autowired
private UserMapper userMapper;
@RequestMapping("/to_login")
public String tologin(LoginVo loginVo) {
log.info(loginVo.toString());
logger.info(loginVo.toString());
return "login";
}
@RequestMapping("/do_login")
@ResponseBody
public Result<Boolean> dologin(HttpServletResponse response, @Valid LoginVo loginVo) {
log.info(loginVo.toString());
public ResultGeekQ<Boolean> dologin(HttpServletResponse response, @Valid LoginVo loginVo) {
ResultGeekQ<Boolean> result = ResultGeekQ.build();
logger.info(loginVo.toString());
userService.login(response, loginVo);
return Result.success(true);
return result;
}
@RequestMapping(value = "/register", method = RequestMethod.POST)
public Result<String> register(MiaoshaUser user) {
return userService.insertMiaoShaUser(user);
}
@RequestMapping("/mybatis")
public void mybatisXml() {
//
int count = userMapper.getMiaoShaUserNum();
System.out.println(count);
MiaoshaUser user = userMapper.getMiaoShaUserById(Long.valueOf("18612766134"));
System.out.println(user);
//
// MiaoshaUser miaoshaUser =new MiaoshaUser();
// miaoshaUser.setId(Long.valueOf("1234569879"));
// miaoshaUser.setNickname("test");
// Long num = userMapper.insertMiaoShaUser(miaoshaUser);
// MiaoshaUser upmiaoshaUser =new MiaoshaUser();
// upmiaoshaUser.setId(Long.valueOf("1234569879"));
// upmiaoshaUser.setNickname("test1");
// userMapper.updateMiaoShaUser(upmiaoshaUser);
//
// userMapper.deleteMiaoShaUser(Long.valueOf("1234569879"));
List<MiaoshaUser> lists = new ArrayList<MiaoshaUser>();
MiaoshaUser upmiaoshaUser =new MiaoshaUser();
upmiaoshaUser.setId(Long.valueOf("1234569879"));
upmiaoshaUser.setNickname("test1");
MiaoshaUser upmiaoshaUser1 =new MiaoshaUser();
upmiaoshaUser1.setId(Long.valueOf("1234569872"));
upmiaoshaUser1.setNickname("test1");
lists.add(upmiaoshaUser);
lists.add(upmiaoshaUser1);
userMapper.insertMiaoShaUserValues(lists);
}
}

View File

@ -1,6 +1,8 @@
package com.geekq.miaosha.controller;
import com.geekq.miaosha.access.AccessLimit;
import com.geekq.miaosha.common.enums.ResultStatus;
import com.geekq.miaosha.common.resultbean.ResultGeekQ;
import com.geekq.miaosha.domain.MiaoshaOrder;
import com.geekq.miaosha.domain.MiaoshaUser;
import com.geekq.miaosha.rabbitmq.MQSender;
@ -28,153 +30,168 @@ import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import static com.geekq.miaosha.common.enums.ResultStatus.*;
@Controller
@RequestMapping("/miaosha")
public class MiaoshaController implements InitializingBean {
@Autowired
MiaoShaUserService userService;
@Autowired
RedisService redisService;
@Autowired
GoodsService goodsService;
@Autowired
OrderService orderService;
@Autowired
MiaoshaService miaoshaService;
@Autowired
MiaoShaUserService userService;
@Autowired
MQSender mqSender ;
@Autowired
RedisService redisService;
private HashMap<Long, Boolean> localOverMap = new HashMap<Long, Boolean>();
@Autowired
GoodsService goodsService;
/**
* QPS:1306
* 5000 * 10
* get post get 幂等 从服务端获取数据 不会产生影响  post 对服务端产生变化 
* */
@AccessLimit(seconds = 5,maxCount = 5,needLogin = true)
@RequestMapping(value="/{path}/do_miaosha", method= RequestMethod.POST)
@ResponseBody
public Result<Integer> miaosha(Model model, MiaoshaUser user,
@RequestParam("goodsId")long goodsId,@PathVariable("path") String path) {
if (user == null) {
return Result.error(CodeMsg.SESSION_ERROR);
}
@Autowired
OrderService orderService;
@Autowired
MiaoshaService miaoshaService;
//验证path
boolean check = miaoshaService.checkPath(user, goodsId, path);
if(!check){
return Result.error(CodeMsg.REQUEST_ILLEGAL);
}
@Autowired
MQSender mqSender;
private HashMap<Long, Boolean> localOverMap = new HashMap<Long, Boolean>();
/**
* QPS:1306
* 5000 * 10
* get post get 幂等 从服务端获取数据 不会产生影响  post 对服务端产生变化
*/
@AccessLimit(seconds = 5, maxCount = 5, needLogin = true)
@RequestMapping(value = "/{path}/do_miaosha", method = RequestMethod.POST)
@ResponseBody
public ResultGeekQ<Integer> miaosha(Model model, MiaoshaUser user,
@RequestParam("goodsId") long goodsId, @PathVariable("path") String path) {
ResultGeekQ<Integer> result = ResultGeekQ.build();
if (user == null) {
result.withError(SESSION_ERROR.getCode(), SESSION_ERROR.getMessage());
return result;
}
//验证path
boolean check = miaoshaService.checkPath(user, goodsId, path);
if (!check) {
result.withError(REQUEST_ILLEGAL.getCode(), REQUEST_ILLEGAL.getMessage());
return result;
}
// //使用RateLimiter 限流
// RateLimiter rateLimiter = RateLimiter.create(10);
// //判断能否在1秒内得到令牌如果不能则立即返回false不会阻塞程序
// if (!rateLimiter.tryAcquire(1000, TimeUnit.MILLISECONDS)) {
// System.out.println("短期无法获取令牌,真不幸,排队也瞎排");
// return Result.error(CodeMsg.MIAOSHA_FAIL);
// return ResultGeekQ.error(CodeMsg.MIAOSHA_FAIL);
//
// }
//是否已经秒杀到
MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId);
if(order!=null){
return Result.error(CodeMsg.REPEATE_MIAOSHA) ;
}
//内存标记减少redis访问
boolean over = localOverMap.get(goodsId);
if(over) {
return Result.error(CodeMsg.MIAO_SHA_OVER);
}
//预见库存
Long stock = redisService.decr(GoodsKey.getMiaoshaGoodsStock,""+goodsId) ;
if(stock <0){
localOverMap.put(goodsId, true);
return Result.error(CodeMsg.MIAO_SHA_OVER);
}
MiaoshaMessage mm = new MiaoshaMessage();
mm.setGoodsId(goodsId);
mm.setUser(user);
mqSender.sendMiaoshaMessage(mm);
return Result.success(0);
}
//是否已经秒杀到
MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId);
if (order != null) {
result.withError(REPEATE_MIAOSHA.getCode(), REPEATE_MIAOSHA.getMessage());
return result;
}
//内存标记减少redis访问
boolean over = localOverMap.get(goodsId);
if (over) {
result.withError(MIAO_SHA_OVER.getCode(), MIAO_SHA_OVER.getMessage());
return result;
}
//预见库存
Long stock = redisService.decr(GoodsKey.getMiaoshaGoodsStock, "" + goodsId);
if (stock < 0) {
localOverMap.put(goodsId, true);
result.withError(MIAO_SHA_OVER.getCode(), MIAO_SHA_OVER.getMessage());
return result;
}
MiaoshaMessage mm = new MiaoshaMessage();
mm.setGoodsId(goodsId);
mm.setUser(user);
mqSender.sendMiaoshaMessage(mm);
return result;
}
/**
* orderId成功
* -1秒杀失败
* 0 排队中
* */
@AccessLimit(seconds = 5,maxCount = 5,needLogin = true)
@RequestMapping(value="/result", method=RequestMethod.GET)
@ResponseBody
public Result<Long> miaoshaResult(Model model,MiaoshaUser user,
@RequestParam("goodsId")long goodsId) {
model.addAttribute("user", user);
if(user == null) {
return Result.error(CodeMsg.SESSION_ERROR);
}
long result =miaoshaService.getMiaoshaResult(user.getId(), goodsId);
return Result.success(result);
}
@AccessLimit(seconds = 5,maxCount = 5,needLogin = true)
@RequestMapping(value="/path", method=RequestMethod.GET)
@ResponseBody
public Result<String> getMiaoshaPath(HttpServletRequest request, MiaoshaUser user,
@RequestParam("goodsId")long goodsId,
@RequestParam(value="verifyCode", defaultValue="0")int verifyCode
) {
if(user == null) {
return Result.error(CodeMsg.SESSION_ERROR);
}
boolean check = miaoshaService.checkVerifyCode(user, goodsId, verifyCode);
if(!check) {
return Result.error(CodeMsg.REQUEST_ILLEGAL);
}
String path =miaoshaService.createMiaoshaPath(user, goodsId);
return Result.success(path);
}
/**
* orderId成功
* -1秒杀失败
* 0 排队中
*/
@AccessLimit(seconds = 5, maxCount = 5, needLogin = true)
@RequestMapping(value = "/result", method = RequestMethod.GET)
@ResponseBody
public ResultGeekQ<Long> miaoshaResult(Model model, MiaoshaUser user,
@RequestParam("goodsId") long goodsId) {
ResultGeekQ<Long> result = ResultGeekQ.build();
if (user == null) {
result.withError(SESSION_ERROR.getCode(), SESSION_ERROR.getMessage());
return result;
}
model.addAttribute("user", user);
Long miaoshaResult = miaoshaService.getMiaoshaResult(user.getId(), goodsId);
result.setData(miaoshaResult);
return result;
}
@AccessLimit(seconds = 5, maxCount = 5, needLogin = true)
@RequestMapping(value = "/path", method = RequestMethod.GET)
@ResponseBody
public ResultGeekQ<String> getMiaoshaPath(HttpServletRequest request, MiaoshaUser user,
@RequestParam("goodsId") long goodsId,
@RequestParam(value = "verifyCode", defaultValue = "0") int verifyCode
) {
ResultGeekQ<String> result = ResultGeekQ.build();
if (user == null) {
result.withError(SESSION_ERROR.getCode(), SESSION_ERROR.getMessage());
return result;
}
boolean check = miaoshaService.checkVerifyCode(user, goodsId, verifyCode);
if (!check) {
result.withError(REQUEST_ILLEGAL.getCode(), REQUEST_ILLEGAL.getMessage());
return result;
}
String path = miaoshaService.createMiaoshaPath(user, goodsId);
result.setData(path);
return result;
}
@RequestMapping(value="/verifyCode", method=RequestMethod.GET)
@ResponseBody
public Result<String> getMiaoshaVerifyCod(HttpServletResponse response, MiaoshaUser user,
@RequestParam("goodsId")long goodsId) {
if(user == null) {
return Result.error(CodeMsg.SESSION_ERROR);
}
try {
BufferedImage image = miaoshaService.createVerifyCode(user, goodsId);
OutputStream out = response.getOutputStream();
ImageIO.write(image, "JPEG", out);
out.flush();
out.close();
return null;
}catch(Exception e) {
e.printStackTrace();
return Result.error(CodeMsg.MIAOSHA_FAIL);
}
}
@RequestMapping(value = "/verifyCode", method = RequestMethod.GET)
@ResponseBody
public Result<String> getMiaoshaVerifyCod(HttpServletResponse response, MiaoshaUser user,
@RequestParam("goodsId") long goodsId) {
if (user == null) {
return Result.error(CodeMsg.SESSION_ERROR);
}
try {
BufferedImage image = miaoshaService.createVerifyCode(user, goodsId);
OutputStream out = response.getOutputStream();
ImageIO.write(image, "JPEG", out);
out.flush();
out.close();
return null;
} catch (Exception e) {
e.printStackTrace();
return Result.error(CodeMsg.MIAOSHA_FAIL);
}
}
/**
* 系统初始化
* @throws Exception
*/
@Override
public void afterPropertiesSet() throws Exception {
List<GoodsVo> goodsList= goodsService.listGoodsVo();
if(goodsList ==null){
return;
}
for (GoodsVo goods :goodsList ){
redisService.set(GoodsKey.getMiaoshaGoodsStock,""+goods.getId(),goods.getStockCount()) ;
localOverMap.put(goods.getId(), false);
}
}
/**
* 系统初始化
*
* @throws Exception
*/
@Override
public void afterPropertiesSet() throws Exception {
List<GoodsVo> goodsList = goodsService.listGoodsVo();
if (goodsList == null) {
return;
}
for (GoodsVo goods : goodsList) {
redisService.set(GoodsKey.getMiaoshaGoodsStock, "" + goods.getId(), goods.getStockCount());
localOverMap.put(goods.getId(), false);
}
}
}

View File

@ -1,5 +1,6 @@
package com.geekq.miaosha.controller;
import com.geekq.miaosha.common.resultbean.ResultGeekQ;
import com.geekq.miaosha.domain.MiaoshaUser;
import com.geekq.miaosha.domain.OrderInfo;
import com.geekq.miaosha.redis.RedisService;
@ -17,6 +18,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import static com.geekq.miaosha.common.enums.ResultStatus.ORDER_NOT_EXIST;
import static com.geekq.miaosha.common.enums.ResultStatus.SESSION_ERROR;
@Controller
@RequestMapping("/order")
public class OrderController {
@ -35,21 +39,25 @@ public class OrderController {
@RequestMapping("/detail")
@ResponseBody
public Result<OrderDetailVo> info(Model model, MiaoshaUser user,
public ResultGeekQ<OrderDetailVo> info(Model model, MiaoshaUser user,
@RequestParam("orderId") long orderId) {
if(user == null) {
return Result.error(CodeMsg.SESSION_ERROR);
}
ResultGeekQ<OrderDetailVo> result = ResultGeekQ.build();
if (user == null) {
result.withError(SESSION_ERROR.getCode(), SESSION_ERROR.getMessage());
return result;
}
OrderInfo order = orderService.getOrderById(orderId);
if(order == null) {
return Result.error(CodeMsg.ORDER_NOT_EXIST);
result.withError(ORDER_NOT_EXIST.getCode(), ORDER_NOT_EXIST.getMessage());
return result;
}
long goodsId = order.getGoodsId();
GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
OrderDetailVo vo = new OrderDetailVo();
vo.setOrder(order);
vo.setGoods(goods);
return Result.success(vo);
result.setData(vo);
return result;
}
}

View File

@ -1,10 +0,0 @@
package com.geekq.miaosha.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/ratelimiter")
public class RateLimiterController {
}

View File

@ -1,24 +0,0 @@
package com.geekq.miaosha.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.http.HttpSession;
@Controller
@RequestMapping("/user/")
public class UserController {
/**
* 用户登录
* @param username
* @param password
* @param session
* @return
*/
@RequestMapping(value = "/login",method = RequestMethod.POST)
public Object login(String username , String password , HttpSession session){
return null;
}
}

View File

@ -1,32 +0,0 @@
package com.geekq.miaosha.dao;
import com.geekq.miaosha.domain.MiaoshaUser;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* mybatis xml 写法
*/
@Mapper
public interface UserMapper {
int countbyMenuId();
MiaoshaUser getMiaoShaUserById(Long phoneId);
//秒杀对象获取 mybatis的#与$的区别
List<MiaoshaUser> queryMiaoShaUserOrderByColumn(String column);
//查询总条数
public int getMiaoShaUserNum();
public Long insertMiaoShaUser(MiaoshaUser user);
void insertMiaoShaUserValues(List<MiaoshaUser> miaoshaUsers);
//更改表数据
void updateMiaoShaUser(MiaoshaUser user) ;
//删除表数据
void deleteMiaoShaUser(long id );
}

View File

@ -1,17 +1,22 @@
package com.geekq.miaosha.exception;
import com.geekq.miaosha.result.CodeMsg;
import com.geekq.miaosha.common.enums.ResultStatus;
public class GlobleException extends RuntimeException {
private CodeMsg cm ;
public GlobleException(CodeMsg cm){
private ResultStatus status;
public GlobleException(ResultStatus status){
super();
this.cm = cm;
this.status = status;
}
public CodeMsg getCm() {
return cm;
public ResultStatus getStatus() {
return status;
}
public void setStatus(ResultStatus status) {
this.status = status;
}
}

View File

@ -1,7 +1,11 @@
package com.geekq.miaosha.exception;
import com.geekq.miaosha.common.enums.ResultStatus;
import com.geekq.miaosha.common.resultbean.ResultGeekQ;
import com.geekq.miaosha.result.CodeMsg;
import com.geekq.miaosha.result.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.ControllerAdvice;
@ -11,25 +15,38 @@ import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import static com.geekq.miaosha.common.enums.ResultStatus.SESSION_ERROR;
import static com.geekq.miaosha.common.enums.ResultStatus.SYSTEM_ERROR;
import static com.geekq.miaosha.result.CodeMsg.BIND_ERROR;
/**
* 拦截异常
* @author qiurunze
*/
@ControllerAdvice
@ResponseBody
public class GlobleExceptionandler {
public class GlobleExceptionHandler {
private static Logger logger = LoggerFactory.getLogger(GlobleExceptionHandler.class);
@ExceptionHandler(value=Exception.class)
public Result<String> exceptionHandler(HttpServletRequest request , Exception e){
public ResultGeekQ<String> exceptionHandler(HttpServletRequest request , Exception e){
e.printStackTrace();
if(e instanceof GlobleException){
GlobleException ex= (GlobleException)e;
return Result.error(ex.getCm());
return ResultGeekQ.error(ex.getStatus());
}else if( e instanceof BindException){
BindException ex = (BindException) e ;
List<ObjectError> errors = ex.getAllErrors();
ObjectError error = errors.get(0);
String msg = error.getDefaultMessage();
return Result.error(CodeMsg.BIND_ERROR.fillArgs(msg));
/**
* 打印堆栈信息
*/
logger.error(String.format(msg, msg));
return ResultGeekQ.error(SESSION_ERROR);
}else {
return Result.error(CodeMsg.SERVER_ERROR);
return ResultGeekQ.error(SYSTEM_ERROR);
}
}
}

View File

@ -42,7 +42,7 @@ public class Result<T> {
return new Result<T>(cm);
}
// public Result(CodeMsg msg, T data) {
// public ResultGeekQ(CodeMsg msg, T data) {
// this.code = msg.getCode();
// this.msg = msg.getMsg();
// this.data = data;

View File

@ -1,7 +0,0 @@
package com.geekq.miaosha.service;
public interface IUserService {
Object login(String username , String password) ;
}

View File

@ -1,16 +1,13 @@
package com.geekq.miaosha.service;
import com.geekq.miaosha.Md5Utils.MD5Utils;
import com.geekq.miaosha.dao.MiaoShaUserDao;
import com.geekq.miaosha.domain.MiaoshaUser;
import com.geekq.miaosha.exception.GlobleException;
import com.geekq.miaosha.redis.MiaoShaUserKey;
import com.geekq.miaosha.redis.RedisService;
import com.geekq.miaosha.result.CodeMsg;
import com.geekq.miaosha.result.Result;
import com.geekq.miaosha.utils.MD5Utils;
import com.geekq.miaosha.utils.UUIDUtil;
import com.geekq.miaosha.vo.LoginVo;
import com.sun.org.apache.bcel.internal.classfile.Code;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -18,6 +15,8 @@ import org.springframework.stereotype.Service;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import static com.geekq.miaosha.common.enums.ResultStatus.*;
@Service
public class MiaoShaUserService {
@ -62,7 +61,7 @@ public class MiaoShaUserService {
//取user
MiaoshaUser user = getById(id);
if(user == null) {
throw new GlobleException(CodeMsg.MOBILE_NOT_EXIST);
throw new GlobleException(MOBILE_NOT_EXIST);
}
//更新数据库
MiaoshaUser toBeUpdate = new MiaoshaUser();
@ -76,34 +75,23 @@ public class MiaoShaUserService {
return true;
}
public Result<String> insertMiaoShaUser(MiaoshaUser miaoshaUser){
long resultRegister = miaoShaUserDao.insertMiaoShaUser(miaoshaUser);
if(resultRegister == 0){
throw new GlobleException(CodeMsg.RESIGETER_FAIL);
}
return Result.success(CodeMsg.SUCCESS_RESIGETER);
}
public boolean login(HttpServletResponse response , LoginVo loginVo) {
if(loginVo ==null){
throw new GlobleException(CodeMsg.SERVER_ERROR);
throw new GlobleException(SYSTEM_ERROR);
}
String mobile =loginVo.getMobile();
String password =loginVo.getPassword();
MiaoshaUser user = getById(Long.valueOf(mobile));
if(user == null) {
throw new GlobleException(CodeMsg.MOBILE_NOT_EXIST);
throw new GlobleException(MOBILE_NOT_EXIST);
}
String dbPass = user.getPassword();
String saltDb = user.getSalt();
String calcPass = MD5Utils.formPassToDBPass(password,saltDb);
if(!calcPass.equals(dbPass)){
throw new GlobleException(CodeMsg.PASSWORD_ERROR);
throw new GlobleException(PASSWORD_ERROR);
}
//生成cookie
String token= UUIDUtil.uuid();
@ -118,12 +106,4 @@ public class MiaoShaUserService {
cookie.setPath("/");
response.addCookie(cookie);
}
// private void addCookie(HttpServletResponse response ,MiaoshaUser user){
// String token = UUIDUtil.uuid();
// redisService.set(MiaoShaUserKey.token,token,user) ;
// Cookie cookie = new Cookie(COOKIE_NAME_TOKEN , token) ;
// cookie.setMaxAge(MiaoShaUserKey.token.expireSeconds());
// cookie.setPath("/");
// response.addCookie(cookie);
// }
}

View File

@ -1,11 +1,11 @@
package com.geekq.miaosha.service;
import com.geekq.miaosha.Md5Utils.MD5Utils;
import com.geekq.miaosha.domain.MiaoshaOrder;
import com.geekq.miaosha.domain.MiaoshaUser;
import com.geekq.miaosha.domain.OrderInfo;
import com.geekq.miaosha.redis.MiaoshaKey;
import com.geekq.miaosha.redis.RedisService;
import com.geekq.miaosha.utils.MD5Utils;
import com.geekq.miaosha.utils.UUIDUtil;
import com.geekq.miaosha.vo.GoodsVo;
import org.springframework.beans.factory.annotation.Autowired;

View File

@ -1,4 +1,4 @@
package com.geekq.miaosha.Md5Utils;
package com.geekq.miaosha.utils;
import org.apache.commons.codec.digest.DigestUtils;

View File

@ -7,8 +7,8 @@ import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = {IsMobileValidator.class})
public @interface IsMobile {
@Constraint(validatedBy = {MobileValidator.class})
public @interface MobileCheck {
boolean required() default true ;
String message() default "手机号码格式有误!";

View File

@ -6,12 +6,12 @@ import org.apache.commons.lang3.StringUtils;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class IsMobileValidator implements ConstraintValidator<IsMobile , String> {
public class MobileValidator implements ConstraintValidator<MobileCheck, String> {
private boolean require = false ;
@Override
public void initialize(IsMobile isMobile) {
public void initialize(MobileCheck isMobile) {
require = isMobile.required() ;
}

View File

@ -1,6 +1,6 @@
package com.geekq.miaosha.vo;
import com.geekq.miaosha.validator.IsMobile;
import com.geekq.miaosha.validator.MobileCheck;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
@ -15,7 +15,7 @@ import javax.validation.constraints.NotNull;
@NoArgsConstructor
public class LoginVo {
@NotNull
@IsMobile
@MobileCheck
private String mobile ;
@NotNull

View File

@ -86,7 +86,7 @@ function doLogin(){
layer.msg("成功");
window.location.href="/goods/to_list";
}else{
layer.msg(data.msg);
layer.msg(data.message);
}
},
error:function(){