java分布式会话,Java秒杀登录模块与分布式session

一、两次MD5

1. 用户端: PASS = MD5( 明文 + 固定 Salt)

2. 服务端: PASS = MD5( 用户输入 + 随机 Salt)

pom添加依赖

commons-codec

commons-codec

1.11

org.apache.commons

commons-lang3

3.6

添加MD5工具类

package com.imooc.miaosha.util;

import org.springframework.util.DigestUtils;

public class Md5Util {

private static final String SALT = "1a2b3c4d";

public static String md5(String src){

return DigestUtils.md5Hex(src);

}

public static String inputPass2FormPass(String inputPass){

String src = "" + SALT.charAt(0) + SALT.charAt(2)+ inputPass + SALT.charAt(5)+ SALT.charAt(4);

return md5(src);

}

public static String formPass2DbPass(String formPass, String salt){

String src = "" + salt.charAt(0) + salt.charAt(2)+ formPass + salt.charAt(5)+ salt.charAt(4);

return md5(src);

}

public static String inputPass2DbPass(String inputPass, String salt){

String formPass = inputPass2FormPass(inputPass);

String dbPass = formPass2DbPass(formPass, salt);

return dbPass;

}

public static void main(String[] args) {

String inputPass = "13632481101";

String salt = "mysalt";

String formPass = inputPass2FormPass(inputPass);

String dbPass1 = formPass2DbPass(formPass, salt);

String dbPass2 = inputPass2DbPass(inputPass, salt);

System.out.println(formPass);

System.out.println(dbPass1);

System.out.println(dbPass2);

}

}

添加电话号码校验类

package com.imooc.miaosha.util;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

import com.alibaba.druid.util.StringUtils;

public class ValidatorUtil {

private static Pattern MOBILE_PATTERN = Pattern.compile("1\\d{10}");

public static boolean isMobile(String mobile){

if(StringUtils.isEmpty(mobile)){

return false;

}

Matcher matcher = MOBILE_PATTERN.matcher(mobile);

return matcher.matches();

}

public static void main(String[] args) {

boolean result1 = isMobile("13632481101");

boolean result2 = isMobile("1363248110");

System.out.println(result1);

System.out.println(result2);

}

}

resources文件下添加js/common.js,js/jquery.min.js,js/md5.min.js,templates/login.html

新增登录页面login.html

登录

用户登录

请输入手机号码

请输入密码

重置

登录

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: "/login/do_login",

type: "POST",

data:{

mobile:$("#mobile").val(),

password: password

},

success:function(data){

layer.closeAll();

if(data.code == 0){

layer.msg("成功");

}else{

layer.msg(data.msg);

}

},

error:function(){

layer.closeAll();

}

});

}

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"

二.JSR303参数检验+全局异常处理器

pom添加依赖

org.springframework.boot

spring-boot-starter-validation

新建包package com/imooc/miaosha/validator

自定义参数注解

package com.imooc.miaosha.validator;

import javax.validation.Constraint;

import javax.validation.Payload;

import java.lang.annotation.Documented;

import java.lang.annotation.Retention;

import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;

import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })

@Retention(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.imooc.miaosha.validator;

import com.imooc.miaosha.util.ValidatorUtil;

import org.apache.commons.lang3.StringUtils;

import javax.validation.ConstraintValidator;

import javax.validation.ConstraintValidatorContext;

public class IsMobileValidator implements ConstraintValidator {

private boolean required;

@Override

public void initialize(IsMobile isMobile) {

required = isMobile.required();

}

@Override

public boolean isValid(String value, ConstraintValidatorContext context) {

if (!required && StringUtils.isEmpty(value)) {

return true;

}

return ValidatorUtil.isMobile(value);

}

}

在LoginVo中使用注解

package com.imooc.miaosha.vo;

import javax.validation.constraints.NotNull;

import com.imooc.miaosha.validator.IsMobile;

import org.hibernate.validator.constraints.Length;

public class LoginVo {

@NotNull

@IsMobile

private String mobile;

@NotNull

@Length(min = 32)

private String password;

public String getMobile() {

return mobile;

}

public void setMobile(String mobile) {

this.mobile = mobile;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

@Override

public String toString() {

return "LoginVo [mobile=" + mobile + ", password=" + password + "]";

}

}

方法中添加参数校验

@RequestMapping("/do_login")

@ResponseBody

public Result doLogin(@Valid LoginVo loginVo) {

log.info(loginVo.toString());

seckillUserService.login(loginVo);

return Result.success(CodeMsg.SUCCESS);

}

service的login方法

public boolean login(LoginVo loginVo){

if(loginVo == null){

//return CodeMsg.SERVER_ERROR;

throw new GlobalException(CodeMsg.SERVER_ERROR);

}

String mobile = loginVo.getMobile();

String password = loginVo.getPassword();

/*

if(StringUtils.isEmpty(mobile)){

return CodeMsg.MOBILE_EMPTY;

}

if(StringUtils.isEmpty(password)){

return CodeMsg.PASSWORD_EMPTY;

}

if(!ValidatorUtil.isMobile(mobile)){

return CodeMsg.MOBILE_ERROR;

}

*/

SeckillUser user = seckillUserDao.getById(Long.parseLong(mobile));

if(user == null){

//return CodeMsg.MOBILE_NOT_EXIST;

throw new GlobalException(CodeMsg.MOBILE_NOT_EXIST);

}

String salt = user.getSalt();

String dbPass = user.getPassword();

String md5Pass = Md5Util.formPass2DbPass(password, salt);

if(!dbPass.equals(md5Pass)){

//return CodeMsg.PASSWORD_ERROR;

throw new GlobalException(CodeMsg.PASSWORD_ERROR);

}

return true;

}

新建包package com/imooc/miaosha/exception

添加全局异常类GlobalException和全局异常处理器GlobalExceptionHandler

package com.imooc.miaosha.exception;

import com.imooc.miaosha.result.CodeMsg;

public class GlobalException extends RuntimeException{

private static final long serialVersionUID = 31665074385012932L;

private CodeMsg cm;

public GlobalException(CodeMsg cm){

this.cm = cm;

}

public CodeMsg getCm() {

return cm;

}

}

package com.imooc.miaosha.exception;

import com.imooc.miaosha.result.CodeMsg;

import com.imooc.miaosha.result.Result;

import org.springframework.web.bind.annotation.ControllerAdvice;

import org.springframework.web.bind.annotation.ExceptionHandler;

import org.springframework.web.bind.annotation.ResponseBody;

import org.springframework.validation.BindException;

import javax.servlet.http.HttpServletRequest;

@ControllerAdvice

@ResponseBody

public class GlobalExceptionHandler {

@ExceptionHandler(value = Exception.class)

public Result handleException(HttpServletRequest request, Exception ex){

ex.printStackTrace();

if(ex instanceof GlobalException){

GlobalException gex = (GlobalException)ex;

return Result.error(gex.getCm());

} else if(ex instanceof BindException){

BindException bex = (BindException)ex;

String message = bex.getAllErrors().get(0).getDefaultMessage();

return Result.error(CodeMsg.BIND_ERROR.fillMsg(message));

} else {

return Result.error(CodeMsg.SERVER_ERROR);

}

}

}

三.分布式session

添加工具类UUIDUtil

package com.imooc.miaosha.util;

import java.util.UUID;

public class UUIDUtil {

public static String uuid(){

return UUID.randomUUID().toString().replace("-", "");

}

}

userservice的login添加代码

String token = UUIDUtil.uuid();

redisService.set(SeckillUserKey.token, token, user);

Cookie cookie = new Cookie(COOKIE_TOKEN_NAME, token);

cookie.setMaxAge(SeckillUserKey.token.expireSeconds());

cookie.setPath("/");

response.addCookie(cookie);

userservice使用token获取user对象

public User getByToke(String token) {

if(StringUtils.isEmpty(token)){

return null;

}

return redisService.get(UserKey.token, token, User.class);

}

GoodsController

public SeckillUser getByToke(String token) {

if(StringUtils.isEmpty(token)){

return null;

}

return redisService.get(SeckillUserKey.token, token, SeckillUser.class);

}

四.优化

使用SpringMVC中WebMvcConfigurerAdapter的addArgumentResolvers,向需要user对象的方法进行入参注入。

新建包package com/imooc/miaosha/exception

新建类UserArgumentResolver和WebConfig

package com.imooc.miaosha.config;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.method.support.HandlerMethodArgumentResolver;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import java.util.List;

@Configuration

public class WebConfig extends WebMvcConfigurerAdapter {

@Autowired

private UserArgumentResolver userArgumentResolver;

@Override

public void addArgumentResolvers(List argumentResolvers) {

argumentResolvers.add(userArgumentResolver);

}

}

package com.imooc.miaosha.config;

import com.imooc.miaosha.domain.User;

import com.imooc.miaosha.service.UserService;

import org.apache.commons.lang3.StringUtils;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.core.MethodParameter;

import org.springframework.stereotype.Service;

import org.springframework.web.bind.support.WebDataBinderFactory;

import org.springframework.web.context.request.NativeWebRequest;

import org.springframework.web.method.support.HandlerMethodArgumentResolver;

import org.springframework.web.method.support.ModelAndViewContainer;

import javax.servlet.http.Cookie;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

@Service

public class UserArgumentResolver implements HandlerMethodArgumentResolver {

@Autowired

private UserService UserService;

@Override

public boolean supportsParameter(MethodParameter parameter) {

Class> clazz = parameter.getParameterType();

return clazz == User.class;

}

@Override

public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,

NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);

HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);

String paramToken = request.getParameter(UserService.COOKIE_TOKEN_NAME);

String cookieToken = getCookieValue(request, UserService.COOKIE_TOKEN_NAME);

if(StringUtils.isEmpty(cookieToken) && StringUtils.isEmpty(paramToken)){

return null;

}

String token = StringUtils.isEmpty(paramToken) ? cookieToken : paramToken;

return UserService.getByToke(token, response);

}

private String getCookieValue(HttpServletRequest request, String cookieName) {

Cookie[] cookies = request.getCookies();

if(cookies != null){

for(Cookie cookie : cookies){

if(cookie.getName().equals(cookieName)){

return cookie.getValue();

}

}

}

return null;

}

}

优化后userservice类

package com.imooc.miaosha.service;

import com.imooc.miaosha.dao.UserDao;

import com.imooc.miaosha.domain.User;

import com.imooc.miaosha.exception.GlobalException;

import com.imooc.miaosha.redis.RedisService;

import com.imooc.miaosha.redis.UserKey;

import com.imooc.miaosha.result.CodeMsg;

import com.imooc.miaosha.util.Md5Util;

import com.imooc.miaosha.util.UUIDUtil;

import com.imooc.miaosha.vo.LoginVo;

import org.apache.commons.lang3.StringUtils;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import javax.servlet.http.Cookie;

import javax.servlet.http.HttpServletResponse;

@Service

public class UserService {

public static final String COOKIE_TOKEN_NAME = "token";

@Autowired

UserDao UserDao;

@Autowired

RedisService redisService;

public User getById(long id){

return UserDao.getById(id);

}

public boolean login(HttpServletResponse response, LoginVo loginVo){

if(loginVo == null){

throw new GlobalException(CodeMsg.SERVER_ERROR);

}

String mobile = loginVo.getMobile();

String password = loginVo.getPassword();

User user = UserDao.getById(Long.parseLong(mobile));

if(user == null){

throw new GlobalException(CodeMsg.MOBILE_NOT_EXIST);

}

String salt = user.getSalt();

String dbPass = user.getPassword();

String md5Pass = Md5Util.formPass2DbPass(password, salt);

if(!dbPass.equals(md5Pass)){

throw new GlobalException(CodeMsg.PASSWORD_ERROR);

}

String token = UUIDUtil.uuid();

addCookie(token, response, user);

return true;

}

public User getByToke(String token, HttpServletResponse response) {

if(StringUtils.isEmpty(token)){

return null;

}

// 延长有效期

User user = redisService.get(UserKey.token, token, User.class);

if(user != null){

addCookie(token, response, user);

}

return user;

}

private void addCookie(String token, HttpServletResponse response, User user){

redisService.set(UserKey.token, token, user);

Cookie cookie = new Cookie(COOKIE_TOKEN_NAME, token);

cookie.setMaxAge(UserKey.token.expireSeconds());

cookie.setPath("/");

response.addCookie(cookie);

}

}

controller类

package com.imooc.miaosha.controller;

import com.imooc.miaosha.domain.User;

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

import org.springframework.web.bind.annotation.RequestMapping;

@Controller

@RequestMapping("/goods")

public class GoodsController {

@RequestMapping("/to_list")

public String toList(Model model, User User) {

model.addAttribute("user", User);

return "goods_list";

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源
大学生在线租房平台管理系统按照操作主体分为管理员和用户。管理员的功能包括报修管理、报修评价管理、字典管理、房东管理、房屋管理、房屋收藏管理、房屋留言管理、房屋租赁管理、租房论坛管理、公告信息管理、留言板管理、用户管理、管理员管理。用户的功能等。该系统采用了Mysql数据库,Java语言,Spring Boot框架等技术进行编程实现。 大学生在线租房平台管理系统可以提高大学生在线租房平台信息管理问题的解决效率,优化大学生在线租房平台信息处理流程,保证大学生在线租房平台信息数据的安全,它是一个非常可靠,非常安全的应用程序。 管理员权限操作的功能包括管理公告,管理大学生在线租房平台信息,包括房屋管理,培训管理,报修管理,薪资管理等,可以管理公告。 房屋管理界面,管理员在房屋管理界面中可以对界面中显示,可以对房屋信息的房屋状态进行查看,可以添加新的房屋信息等。报修管理界面,管理员在报修管理界面中查看报修种类信息,报修描述信息,新增报修信息等。公告管理界面,管理员在公告管理界面中新增公告,可以删除公告。公告类型管理界面,管理员在公告类型管理界面查看公告的工作状态,可以对公告的数据进行导出,可以添加新公告的信息,可以编辑公告信息,删除公告信息。
基于hal库的OLED显示屏驱动C语言实现源码.zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我! 基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值