用户注册登陆&参数校验器&全局捕获异常&分布式session

工具类准备

分布式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";
    }
    
}

测试

 

码源

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值