工具类准备
分布式ID工具类
package com.example.miaosha_xdp.util;
import java.util.UUID;
public class UUIDUtil {
public static String uuid(){
/**
*用java.util.UUID生成随机字符串
*将字符串里面的"-"替换
*/
return UUID.randomUUID().toString().replace("-", "");
}
}
全局捕获异常
定义我们自己的全局异常类
package com.example.miaosha_xdp.exception;
import com.example.miaosha_xdp.result.CodeMsg;
import lombok.Getter;
@Getter
public class GlobalException extends RuntimeException {
private static final long serialVersionUID = 1L;
private CodeMsg codeMsg;
public GlobalException(CodeMsg codeMsg) {
super(codeMsg.toString());
this.codeMsg = codeMsg;
}
}
定义我们的全局异常处理器
package com.example.miaosha_xdp.exception;
import com.example.miaosha_xdp.result.CodeMsg;
import com.example.miaosha_xdp.result.Result;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {
@ExceptionHandler(value = Exception.class)
public Result<String> exceptionHandler(Exception e){
e.printStackTrace();
if (e instanceof GlobalException){
GlobalException globalException = (GlobalException) e;
return Result.error(globalException.getCodeMsg());
}
if (e instanceof BindException){
BindException bindException = (BindException) e;
List<ObjectError> errors = bindException.getAllErrors();
ObjectError error = errors.get(0);
String errorDefaultMessage = error.getDefaultMessage();
return Result.error(CodeMsg.BIND_ERROR.fillArgs(errorDefaultMessage));
}
return Result.error(CodeMsg.SERVER_ERROR);
}
}
使用参数校验器
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
定义我们自己的校验器
package com.example.miaosha_xdp.util;
import org.springframework.util.StringUtils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ValidatorUtil {
/**
* 定义正则表达式规则
*/
public static final Pattern MOBILE_PATTERN = Pattern.compile("1\\d{10}");
/**
* 校验手机号
* @param str
* @return
*/
public static boolean isMObile(String str){
if (StringUtils.isEmpty(str)){
return false;
}
Matcher matcher = MOBILE_PATTERN.matcher(str);
return matcher.matches();
}
}
package com.example.miaosha_xdp.validator;
import javax.validation.Constraint;
import javax.validation.Payload;
import javax.validation.groups.Default;
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 {
boolean required() default true;//注解里面必须有这个属性,默认为空
String message() default "手机号码格式错误";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default{};
}
package com.example.miaosha_xdp.validator;
import com.example.miaosha_xdp.util.ValidatorUtil;
import org.springframework.util.StringUtils;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.annotation.Annotation;
public class IsMobileValidator implements ConstraintValidator<IsMobile,String> {
private boolean requried =false;
@Override
public void initialize(IsMobile constraintAnnotation) {
requried=constraintAnnotation.required();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
if (requried){
return ValidatorUtil.isMObile(value);
}
if (StringUtils.isEmpty(value)){
return true;
}
return ValidatorUtil.isMObile(value);
}
}
创建一个VO类
package com.example.miaosha_xdp.VO;
import com.example.miaosha_xdp.validator.IsMobile;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotNull;
@Getter
@Setter
@ToString
public class LoginVo {
/**
* 这里使用的是参数校验器的注解
*/
@NotNull
@IsMobile
private String mobile;
@NotNull
@Length(min = 32)
private String password;
}
编写service层
package com.example.miaosha_xdp.service;
import com.example.miaosha_xdp.VO.LoginVo;
import com.example.miaosha_xdp.entity.User;
import com.example.miaosha_xdp.exception.GlobalException;
import com.example.miaosha_xdp.mapper.UserMapper;
import com.example.miaosha_xdp.redis.MiaoshaUserKey;
import com.example.miaosha_xdp.redis.RedisService;
import com.example.miaosha_xdp.result.CodeMsg;
import com.example.miaosha_xdp.result.Result;
import com.example.miaosha_xdp.util.MD5Util;
import com.example.miaosha_xdp.util.UUIDUtil;
import org.hibernate.validator.constraints.Length;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
@Service
@Transactional
public class UserService {
public static final String TOKEN = "token";
@Autowired
private UserMapper userMapper;
@Autowired
private RedisService redisService;
/**
* 登陆
* @param response
* @param loginVo
* @return
*/
public boolean login(HttpServletResponse response, LoginVo loginVo){
if (loginVo==null){
throw new GlobalException(CodeMsg.SERVER_ERROR);
}
@NotNull String mobile = loginVo.getMobile();
@NotNull @Length(min = 32) String password = loginVo.getPassword();
//查看用户是否存在
long longMobile = Long.parseLong(mobile);
User user = byId(longMobile);
if (user==null){
throw new GlobalException(CodeMsg.MOBILE_NOT_EXIST);
}
//验证密码
String userPassword = user.getPassword();
String salt = user.getSalt();
String saltPassword = MD5Util.formPassToDBPass(userPassword, salt);
if (!saltPassword.equals(password)){
throw new GlobalException(CodeMsg.PASSWORD_ERROR);
}
//生成token
String token = UUIDUtil.uuid();
addCookie(response,token,user);
return true;
}
/**
*根据token进行查询
* @param response
* @param token
* @return
*/
public User byToken(HttpServletResponse response,String token){
if (StringUtils.isEmpty(token)){
return null;
}
User user = redisService.get(MiaoshaUserKey.token, token, User.class);
//延长有效期
if(user!=null){
addCookie(response,token,user);
}
return user;
}
/**
* 添加cookie
* @param response
* @param token
* @param user
*/
private void addCookie(HttpServletResponse response,String token,User user){
redisService.set(MiaoshaUserKey.token,token,user);
Cookie cookie = new Cookie(TOKEN, token);
cookie.setMaxAge(MiaoshaUserKey.token.expireSeconds());
cookie.setPath("/");
response.addCookie(cookie);
}
/**
* 根据id查找用户
* @param id
* @return
*/
public User byId(Long id){
return userMapper.selectByPrimaryKey(id);
}
}
编写控制层
package com.example.miaosha_xdp.controller;
import com.example.miaosha_xdp.VO.LoginVo;
import com.example.miaosha_xdp.entity.User;
import com.example.miaosha_xdp.redis.RedisService;
import com.example.miaosha_xdp.result.CodeMsg;
import com.example.miaosha_xdp.result.Result;
import com.example.miaosha_xdp.service.UserService;
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.*;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
@Controller
@RequestMapping("/user")
public class UserController {
public static final String LOGIN = "login";
private static Logger logger= LoggerFactory.getLogger(UserController.class);
@Autowired
private UserService userService;
@Autowired
private RedisService redisService;
/**
* 跳转到登陆页面
* @return
*/
@GetMapping("/login")
public String login(){
return LOGIN;
}
/**
* 实现登陆
* @Valid 注解不能少,表示开启参数校验器
* @param response
* @param loginVo
* @return
*/
@RequestMapping("/to_login")
@ResponseBody
public Result<Boolean> to_login(HttpServletResponse response,@Valid LoginVo loginVo){
logger.info(loginVo.toString());
userService.login(response,loginVo);
return Result.success(true);
}
}
前端代码
导入静态资源
编写我们的common.js
//展示loading
function g_showLoading(){
var idx = layer.msg('处理中...', {icon: 16,shade: [0.5, '#f5f5f5'],scrollbar: false,offset: '0px', time:100000}) ;
return idx;
}
//salt
var g_passsword_salt="1a2b3c4d"
在登陆页面引入相关需要
<!-- jquery -->
<script type="text/javascript" th:src="@{/js/jquery.min.js}"></script>
<!-- bootstrap -->
<link rel="stylesheet" type="text/css" th:href="@{/bootstrap/css/bootstrap.min.css}" />
<script type="text/javascript" th:src="@{/bootstrap/js/bootstrap.min.js}"></script>
<!-- jquery-validator -->
<script type="text/javascript" th:src="@{/jquery-validation/jquery.validate.min.js}"></script>
<script type="text/javascript" th:src="@{/jquery-validation/localization/messages_zh.min.js}"></script>
<!-- layer -->
<script type="text/javascript" th:src="@{/layer/layer.js}"></script>
<!-- md5.js -->
<script type="text/javascript" th:src="@{/js/md5.min.js}"></script>
<!-- common.js -->
<script type="text/javascript" th:src="@{/js/common.js}"></script>
编写登陆页面的Js
<script>
function login(){
$("#loginForm").validate({
submitHandler:function(form){
doLogin();
}
});
}
function doLogin(){
g_showLoading();
var inputPass = $("#password").val();
var salt = g_passsword_salt;
var str = ""+salt.charAt(0)+salt.charAt(2) + inputPass +salt.charAt(5) + salt.charAt(4);
var password = md5(str);
$.ajax({
url: "/user/to_login",
type: "POST",
data:{
mobile:$("#mobile").val(),
password: password
},
success:function(data){
layer.closeAll();
if(data.code == 0){
layer.msg("成功");
window.location.href="/goods/to_list";
}else{
layer.msg(data.msg);
}
},
error:function(){
layer.closeAll();
}
});
}
</script>
这里我们需要再编写一个商品列表页面goods_list.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>商品列表</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'hello:'+${user.nickname}" ></p>
</body>
</html>
再编写一个商品列表控制器
package com.example.miaosha_xdp.controller;
import com.example.miaosha_xdp.entity.User;
import com.example.miaosha_xdp.redis.RedisService;
import com.example.miaosha_xdp.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;
@Controller
@RequestMapping("/goods")
public class GoodsController {
@Autowired
UserService userService;
@Autowired
RedisService redisService;
@RequestMapping("/to_list")
public String list(Model model, User user) {
model.addAttribute("user", user);
return "goods_list";
}
}
测试