总结
以上是字节二面的一些问题,面完之后其实挺后悔的,没有提前把各个知识点都复习到位。现在重新好好复习手上的面试大全资料(含JAVA、MySQL、算法、Redis、JVM、架构、中间件、RabbitMQ、设计模式、Spring等),现在起闭关修炼半个月,争取早日上岸!!!
下面给大家分享下我的面试大全资料
- 第一份是我的后端JAVA面试大全
后端JAVA面试大全
- 第二份是MySQL+Redis学习笔记+算法+JVM+JAVA核心知识整理
MySQL+Redis学习笔记算法+JVM+JAVA核心知识整理
- 第三份是Spring全家桶资料
MySQL+Redis学习笔记算法+JVM+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点。机会都是留给有准备的人,只有充足的准备,才可能让自己可以在候选人中脱颖而出。
是手机号码,密码是不是空)
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)]