Java最新秒杀项目之登录(1),Java面试宝典最新版

总结

以上是字节二面的一些问题,面完之后其实挺后悔的,没有提前把各个知识点都复习到位。现在重新好好复习手上的面试大全资料(含JAVA、MySQL、算法、Redis、JVM、架构、中间件、RabbitMQ、设计模式、Spring等),现在起闭关修炼半个月,争取早日上岸!!!

下面给大家分享下我的面试大全资料

  • 第一份是我的后端JAVA面试大全

image.png

后端JAVA面试大全

  • 第二份是MySQL+Redis学习笔记+算法+JVM+JAVA核心知识整理

字节二面拜倒在“数据库”脚下,闭关修炼半个月,我还有机会吗?

MySQL+Redis学习笔记算法+JVM+JAVA核心知识整理

  • 第三份是Spring全家桶资料

字节二面拜倒在“数据库”脚下,闭关修炼半个月,我还有机会吗?

MySQL+Redis学习笔记算法+JVM+JAVA核心知识整理

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

2、将界面放到template


head.ftl文件:

秒杀项目

<#assign ctx>

${springMacroRequestContext.getContextPath()}

</#assign>

goodsList.ftl文件:

<#include “…/common/head.ftl”>

这是商品展示界面

login.ftl文件:

<#include “common/head.ftl”/>

用户登录

登录

注册

3、在js目录下新建目录project


新建JavaScript文件login:

layui.define(()=>{

// 得到layui中封装的jquery

let $=layui.jquery

// 给登录按钮设置事件

$(login).click(()=>{

// 取到表单的值

let mobile = $(“#mobile”).val();

let password=$(“#password”).val();

// 将数据给后台(前后端分离axios,普通开发ajax)

$.ajax({

url:“”,//后台登录接口

data:{

// 需要携带的数据

mobile,

password

},

datatype: “json”,//后端给你的数据类型

success(e){

// 成功的回调函数

},

error(e){

// 报错的回调函数

}

})

})

})

4、新建controller类


**专门用于跳转路径:**PathController类

package com.example.seckill.controller;

import org.springframework.stereotype.Controller;

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

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

@Controller

public class PathController {

// 登录跳首页

@RequestMapping(“/”)

public String toPath(){

return “login”;

}

// 跳所有二级页面

@RequestMapping(“/{dir}/{path}”)

public String toPath(@PathVariable(“dir”) String dir,@PathVariable(“path”) String path){

return dir+“/”+path;

}

}

得到界面:

三、MD5加密

=======

1、导入帮助包与exception包


①、exception

package com.example.seckill.exception;

import com.example.seckill.util.response.ResponseResultCode;

import lombok.Data;

@SuppressWarnings(“all”)

@Data

public class BusinessException extends RuntimeException {

private ResponseResultCode responseResultCode;

public BusinessException(ResponseResultCode responseResultCode) {

this.responseResultCode = responseResultCode;

}

}

②、response包,用于后面的全局异常

JsonResponseParse :

package com.example.seckill.util.response;

import lombok.extern.slf4j.Slf4j;

import org.springframework.core.MethodParameter;

import org.springframework.http.MediaType;

import org.springframework.http.server.ServerHttpRequest;

import org.springframework.http.server.ServerHttpResponse;

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

import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

@SuppressWarnings(“all”)

@RestControllerAdvice

@Slf4j

public class JsonResponseParse implements ResponseBodyAdvice {

@Override

public boolean supports(MethodParameter methodParameter, Class aClass) {

//返回值决定他是否需要进入beforeBodyWrite

return methodParameter.getMethod().isAnnotationPresent(JsonResponseResult.class);

}

@Override

public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {

//更改返回值

if (o == null) {

return ResponseResult.success();

}

if (o instanceof Integer) {

return ResponseResult.failure(ResponseResultCode.queryCode((Integer) o));

}

if (o instanceof ResponseResultCode) {

return ResponseResult.failure((ResponseResultCode) o);

}

if (o instanceof ResponseResult) {

return o;

}

return ResponseResult.success(o);

}

}

JsonResponseResult :

package com.example.seckill.util.response;

import java.lang.annotation.*;

@SuppressWarnings(“all”)

@Retention(value = RetentionPolicy.RUNTIME)

@Documented

@Target({ElementType.METHOD})

public @interface JsonResponseResult {

}

ResponseResult:

package com.example.seckill.util.response;

import lombok.AllArgsConstructor;

import lombok.Data;

import lombok.NoArgsConstructor;

import java.io.Serializable;

@SuppressWarnings(“all”)

@Data

@NoArgsConstructor

@AllArgsConstructor

public class ResponseResult implements Serializable {

private int code;

private String message;

private T data;

private Long total;

/**

  • 私有构造, 只允许通过static调用构造

  • @param resultCode 结果枚举

  • @param data 响应数据

*/

private ResponseResult(ResponseResultCode resultCode, T data) {

this.code = resultCode.getCode();

this.message = resultCode.getMessage();

this.data = data;

}

/**

  • 私有构造, 只允许通过static调用构造

  • @param resultCode 结果枚举

  • @param data 响应数据

*/

private ResponseResult(ResponseResultCode resultCode, Long total, T data) {

this.code = resultCode.getCode();

this.message = resultCode.getMessage();

this.data = data;

this.total = total;

}

/**

  • 成功调用返回的结果(无数据携带)

*/

public static ResponseResult success() {

return success(null);

}

/**

  • 成功调用返回的结果(数据携带)

  • @param data 携带的数据

*/

public static ResponseResult success(T data) {

return new ResponseResult(ResponseResultCode.SUCCESS, data);

}

/**

  • 成功调用返回的结果(分页使用)

  • @param data 携带的数据

  • @param total 数据总条数

*/

public static ResponseResult success(T data, Long total) {

return new ResponseResult(ResponseResultCode.SUCCESS, total, data);

}

/**

  • 失败调用返回的结果(数据携带)

  • @param resultCode 状态枚举

  • @param data 携带的数据

*/

public static ResponseResult failure(ResponseResultCode resultCode, T data) {

return new ResponseResult(resultCode, data);

}

/**

  • 失败调用返回的结果(无数据携带)

  • @param resultCode 状态枚举

*/

public static ResponseResult failure(ResponseResultCode resultCode) {

return failure(resultCode, null);

}

}

ResponseResultCode :

package com.example.seckill.util.response;

import java.io.Serializable;

@SuppressWarnings(“all”)

public enum ResponseResultCode implements Serializable {

/* 正常状态 */

SUCCESS(200, “成功”),

FAILURE(300, “失败”),

UNKNOWN(400, “未知错误”),

/**

  • 用户code范围: 1000;

*/

USER_ACCOUNT_NOT_FIND(1001, “用户名不存在”),

USER_ACCOUNT_DISABLED(1002, “该用户已被禁用”),

USER_PASSWORD_NOT_MATCH(1003, “该用户密码不一致”),

USER_PERMISSION_ERROR(1004, “该用户不具备访问权限”),

USER_STATE_OFF_LINE(1005, “该用户未登录”),

USER_CREDENTIAL_NOT_BE_EMPTY(1006, “用户的登录信息不能为空值”),

USER_ACCOUNT_NOT_MOBLIE(1007, “该用户登录信息格式不符合”),

USER_LOGIN_ERROR(1008, “登录失败”),

/**

  • 其它异常: 4000;

*/

TICKET_ERROR(4001, “TICKET失效,请重新登录”),

/**

  • 商品异常: 6000;

*/

GOODS_ADD_ERROR(6001, “商品添加失败”),

GOODS_EDIT_ERROR(6002, “商品修改失败”),

GOODS_REMOVE_ERROR(6003, “商品删除失败”),

/**

  • 秒杀商品异常: 8000

*/

SECKILL_GOODS_ADD_ERROR(8001, “秒杀商品增加失败”),

/**

  • 秒杀订单异常: 10000

*/

SECKILL_ORDER_ERROR(10001, “秒杀订单增加失败”),

SECKILL_ORDER_QUANTITY_ERROR(10002, “秒杀商品数量不足”),

SECKILL_ORDER_EXISTS_ERROR(10002, “秒杀订单已经存在”),

;

private final Integer code;

private final String message;

ResponseResultCode(Integer code, String message) {

this.code = code;

this.message = message;

}

public static ResponseResultCode queryCode(Integer code) {

for (ResponseResultCode value : values()) {

if (code.equals(value.code)) {

return value;

}

}

return UNKNOWN;

}

public Integer getCode() {

return code;

}

public String getMessage() {

return message;

}

}

RestThrowableAdvice :

package com.example.seckill.util.response;

import com.example.seckill.exception.BusinessException;

import lombok.extern.slf4j.Slf4j;

import org.springframework.ui.Model;

import org.springframework.validation.BindException;

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

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

import java.util.Arrays;

@SuppressWarnings(“all”)

@RestControllerAdvice

@Slf4j

public class RestThrowableAdvice {

@JsonResponseResult

@ExceptionHandler(value = {BusinessException.class})

public Object globalBusinessException(Model m, Exception e) {

log.error(e.toString());

return ((BusinessException) e).getResponseResultCode();

}

@JsonResponseResult

@ExceptionHandler(value = {BindException.class})

public Object globalBindException(Model m, Exception e) {

log.error(e.toString());

BindException error = (BindException) e;

return Arrays

.stream(error.getFieldError().getArguments())

.filter(arg -> arg instanceof ResponseResultCode)

.findAny()

.orElse(ResponseResultCode.UNKNOWN);

}

@JsonResponseResult

@ExceptionHandler(value = {Throwable.class})

public Object globalException(Model m, Exception e) {

log.error(e.toString());

return ResponseResultCode.UNKNOWN;

}

}

③、MD5Utils

package com.example.seckill.util;

import org.apache.commons.codec.digest.DigestUtils;

import org.springframework.stereotype.Component;

import java.util.UUID;

/**

  • MD5加密

  • 用户端:password=MD5(明文+固定Salt)

  • 服务端:password=MD5(用户输入+随机Salt)

  • 用户端MD5加密是为了防止用户密码在网络中明文传输,服务端MD5加密是为了提高密码安全性,双重保险。

*/

@Component

@SuppressWarnings(“all”)

public class MD5Utils {

//加密盐,与前端一致

private static String salt = “f1g2h3j4”;

/**

  • md5加密

  • @param src

  • @return

*/

public static String md5(String src) {

return DigestUtils.md5Hex(src);

}

/**

  • 获取加密的盐

  • @return

*/

public static String createSalt() {

return UUID.randomUUID().toString().replace(“-”, “”);

}

/**

  • 将前端的明文密码通过MD5加密方式加密成后端服务所需密码

  • 注意:该步骤实际是在前端完成!!!

  • @param inputPass 明文密码

  • @return

*/

public static String inputPassToFormpass(String inputPass) {

//混淆固定盐salt,安全性更可靠

String str = salt.charAt(1) + “” + salt.charAt(5) + inputPass + salt.charAt(0) + “” + salt.charAt(3);

return md5(str);

}

/**

  • 将后端密文密码+随机salt生成数据库的密码

  • @param formPass

  • @param salt

  • @return

*/

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

//混淆固定盐salt,安全性更可靠

String str = salt.charAt(7) + “” + salt.charAt(9) + formPass + salt.charAt(1) + “” + salt.charAt(5);

return md5(str);

}

/**

  • 将用户输入的密码转换成数据库的密码

  • @param inputPass 明文密码

  • @param salt 盐

  • @return

*/

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

String formPass = inputPassToFormpass(inputPass);

String dbPass = formPassToDbPass(formPass, salt);

return dbPass;

}

public static void main(String[] args) {

String formPass = inputPassToFormpass(“123456”);

System.out.println(“前端加密密码:” + formPass);

String salt = createSalt();

System.out.println(“后端加密随机盐:” + salt);

String dbPass = formPassToDbPass(formPass, salt);

System.out.println(“后端加密密码:” + dbPass);

String dbPass1 = inputPassToDbPass(“123456”, salt);

System.out.println(“最终加密密码:” + dbPass1);

}

}

ValidatorUtils :

package com.example.seckill.util;

import org.apache.commons.lang3.StringUtils;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

@SuppressWarnings(“all”)

public class ValidatorUtils {

private static final Pattern mobile_pattern = Pattern.compile(“1[0-9]{9}$”);

public static boolean isMobile(String mobile) {

if (StringUtils.isEmpty(mobile)) {

return false;

}

Matcher matcher = mobile_pattern.matcher(mobile);

return matcher.matches();

}

}

2、新建vo类


用于前后端传值:

package com.example.seckill.vo;

import lombok.Data;

@Data

public class UserVo {

// 手机号

private String mobile;

// 密码

private String password;

}

3、登录方法:


IUserService层:

package com.example.seckill.service;

import com.example.seckill.pojo.User;

import com.baomidou.mybatisplus.extension.service.IService;

import com.example.seckill.util.response.ResponseResult;

import com.example.seckill.vo.UserVo;

/**

  • 用户信息表 服务类

  • @author lv

  • @since 2022-03-15

*/

public interface IUserService extends IService {

ResponseResult<?> findByAccount(UserVo userVo);

}

UserServiceImpl类:

package com.example.seckill.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import com.example.seckill.pojo.User;

import com.example.seckill.mapper.UserMapper;

import com.example.seckill.service.IUserService;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.example.seckill.util.ValidatorUtils;

import com.example.seckill.util.response.ResponseResult;

import com.example.seckill.util.response.ResponseResultCode;

import com.example.seckill.vo.UserVo;

import org.apache.commons.lang3.StringUtils;

import org.springframework.stereotype.Service;

/**

  • 用户信息表 服务实现类

  • @author lv

  • @since 2022-03-15

*/

@Service

public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

@Override

public ResponseResult<?> findByAccount(UserVo userVo) {

// 先判断信息是否符合(账号是否是手机号码,密码是不是空)

if(!ValidatorUtils.isMobile(userVo.getMobile())){

return ResponseResult.failure(ResponseResultCode.USER_ACCOUNT_NOT_MOBLIE);

}

if(!StringUtils.isBlank(userVo.getPassword())){

return ResponseResult.failure(ResponseResultCode.USER_PASSWORD_NOT_MATCH);

}

// 再去数据库查出对应的用户(mobile)

User user=this.getOne(new QueryWrapper().eq(“id”,userVo.getMobile()));

if(user==null){

return ResponseResult.failure(ResponseResultCode.USER_ACCOUNT_NOT_FIND);

}

// 比较密码

if(userVo.getPassword().equals(user.getPassword())){

return ResponseResult.failure(ResponseResultCode.USER_PASSWORD_NOT_MATCH);

}

return ResponseResult.success();

}

}

UserController类:

package com.example.seckill.controller;

import com.example.seckill.service.IUserService;

import com.example.seckill.util.response.ResponseResult;

import com.example.seckill.vo.UserVo;

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

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

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

/**

  • 用户信息表 前端控制器

  • @author lv

  • @since 2022-03-15

*/

@RestController

@RequestMapping(“/user”)

public class UserController {

@Autowired

private IUserService userService;

// 用户登录

@RequestMapping(“/login”)

public ResponseResult<?> login(UserVo userVo){

// 调用service的登录验证

return userService.findByAccount(userVo);

}

}

4、密码加密


①、将md5.js放到js文件中

②、前端密码进行加密

login.js文件:

layui.use([“jquery”,“layer”],()=>{

// 得到layui中封装的jquery
let $=layui.jquery

** let layer=layui.layer**

// 给登录按钮设置事件
$(login).click(()=>{
 // 取到表单的值
let mobile = $("#mobile").val();
let password=$("#password").val();

** // 前端加密的盐

let salt= "f1g2h3j4";
if(password){
    // 将密码和盐混在一起
    password=salt.charAt(1) + "" + salt.charAt(5) + password + salt.charAt(0) + "" + salt.charAt(3);
    // 进行MD5加密
    password=md5(password)**
}
console.log(password)
// 将数据给后台(前后端分离axios,普通开发ajax)
   $.ajax({
       url:"/user/login",//后台登录接口
       data:{
         // 需要携带的数据
           mobile,
           password
       },
       datatype: "json",//后端给你的数据类型
       success(e){
           // 成功的回调函数
        layer.msg(e.message,{icon: 6});
       },
       error(e){
           // 报错的回调函数
       }
   })
})

})

UserServiceImpl文件:

package com.example.seckill.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import com.example.seckill.pojo.User;

import com.example.seckill.mapper.UserMapper;

import com.example.seckill.service.IUserService;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.example.seckill.util.MD5Utils;

import com.example.seckill.util.ValidatorUtils;

import com.example.seckill.util.response.ResponseResult;

import com.example.seckill.util.response.ResponseResultCode;

import com.example.seckill.vo.UserVo;

import org.apache.commons.lang3.StringUtils;

import org.springframework.stereotype.Service;

/**

*

* 用户信息表 服务实现类

*

*

* @author lv

* @since 2022-03-15

*/

@Service

public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

@Override
public ResponseResult<?> findByAccount(UserVo userVo) {

// 先判断信息是否符合(账号是否是手机号码,密码是不是空)

     if(!ValidatorUtils.isMobile(userVo.getMobile())){
         return ResponseResult.failure(ResponseResultCode.USER\_ACCOUNT\_NOT\_MOBLIE);
     }
     if(StringUtils.isBlank(userVo.getPassword())){
         return ResponseResult.failure(ResponseResultCode.USER\_PASSWORD\_NOT\_MATCH);
     }

// 再去数据库查出对应的用户(mobile)

    User user=this.getOne(new QueryWrapper<User>().eq("id",userVo.getMobile()));
    if(user==null){
        return ResponseResult.failure(ResponseResultCode.USER\_ACCOUNT\_NOT\_FIND);
    }

**// 比较密码

// 二重加密(前端->后端,后端->数据库)

    String salt=user.getSalt();

// 将前台的加密密码和后端的盐再次进行加密

    String newPassword=MD5Utils.formPassToDbPass(userVo.getPassword(),salt);
    if(!newPassword.equals(user.getPassword())){
        return ResponseResult.failure(ResponseResultCode.USER\_PASSWORD\_NOT\_MATCH);
    }**
    return ResponseResult.success();
}

}

得到密钥,登录成功:

最后

面试是跳槽涨薪最直接有效的方式,马上金九银十来了,各位做好面试造飞机,工作拧螺丝的准备了吗?

掌握了这些知识点,面试时在候选人中又可以夺目不少,暴击9999点。机会都是留给有准备的人,只有充足的准备,才可能让自己可以在候选人中脱颖而出。

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

是手机号码,密码是不是空)

     if(!ValidatorUtils.isMobile(userVo.getMobile())){
         return ResponseResult.failure(ResponseResultCode.USER\_ACCOUNT\_NOT\_MOBLIE);
     }
     if(StringUtils.isBlank(userVo.getPassword())){
         return ResponseResult.failure(ResponseResultCode.USER\_PASSWORD\_NOT\_MATCH);
     }

// 再去数据库查出对应的用户(mobile)

    User user=this.getOne(new QueryWrapper<User>().eq("id",userVo.getMobile()));
    if(user==null){
        return ResponseResult.failure(ResponseResultCode.USER\_ACCOUNT\_NOT\_FIND);
    }

**// 比较密码

// 二重加密(前端->后端,后端->数据库)

    String salt=user.getSalt();

// 将前台的加密密码和后端的盐再次进行加密

    String newPassword=MD5Utils.formPassToDbPass(userVo.getPassword(),salt);
    if(!newPassword.equals(user.getPassword())){
        return ResponseResult.failure(ResponseResultCode.USER\_PASSWORD\_NOT\_MATCH);
    }**
    return ResponseResult.success();
}

}

得到密钥,登录成功:

最后

面试是跳槽涨薪最直接有效的方式,马上金九银十来了,各位做好面试造飞机,工作拧螺丝的准备了吗?

掌握了这些知识点,面试时在候选人中又可以夺目不少,暴击9999点。机会都是留给有准备的人,只有充足的准备,才可能让自己可以在候选人中脱颖而出。

[外链图片转存中…(img-iyJrz9BS-1715440293444)]

[外链图片转存中…(img-ut3vcNyg-1715440293445)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值