前端项目nginx部署
nginx配置文件
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/json;
sendfile on;
keepalive_timeout 65;
server {
listen 8080;
server_name localhost;
# 指定前端项目所在的位置
location / {
root html/hmdp;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
location /api {
default_type application/json;
#internal;
keepalive_timeout 30s;
keepalive_requests 1000;
#支持keep-alive
proxy_http_version 1.1;
rewrite /api(/.*) $1 break;
proxy_pass_request_headers on;
#more_clear_input_headers Accept-Encoding;
proxy_next_upstream error timeout;
proxy_pass http://127.0.0.1:8081;
#proxy_pass http://backend;
}
}
upstream backend {
server 127.0.0.1:8081 max_fails=5 fail_timeout=10s weight=1;
#server 127.0.0.1:8082 max_fails=5 fail_timeout=10s weight=1;
}
}
启动nginx
在D:\centos7nginx\nginx-1.18.0\nginx-1.18.0目录下,执行start nginx.exe命令启动。
可以看出,地址http://localhost:8080/api请求 会转发到 http://localhost:8081上
例如:http://localhost:8080/api/shop-type/list 会转发到 http://localhost:8081/shop-type/list
正则表达式校验的工具类
package com.xkj.org.utils;
/**
* @author 虎哥
*/
public abstract class RegexPatterns {
/**
* 手机号正则
*/
public static final String PHONE_REGEX = "^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\\d{8}$";
/**
* 邮箱正则
*/
public static final String EMAIL_REGEX = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$";
/**
* 密码正则。4~32位的字母、数字、下划线
*/
public static final String PASSWORD_REGEX = "^\\w{4,32}$";
/**
* 验证码正则, 6位数字或字母
*/
public static final String VERIFY_CODE_REGEX = "^[a-zA-Z\\d]{6}$";
}
package com.xkj.org.utils;
import cn.hutool.core.util.StrUtil;
/**
* @author 虎哥
*/
public class RegexUtils {
/**
* 是否是无效手机格式
* @param phone 要校验的手机号
* @return true:符合,false:不符合
*/
public static boolean isPhoneInvalid(String phone){
return mismatch(phone, RegexPatterns.PHONE_REGEX);
}
/**
* 是否是无效邮箱格式
* @param email 要校验的邮箱
* @return true:符合,false:不符合
*/
public static boolean isEmailInvalid(String email){
return mismatch(email, RegexPatterns.EMAIL_REGEX);
}
/**
* 是否是无效验证码格式
* @param code 要校验的验证码
* @return true:符合,false:不符合
*/
public static boolean isCodeInvalid(String code){
return mismatch(code, RegexPatterns.VERIFY_CODE_REGEX);
}
// 校验是否不符合正则格式
private static boolean mismatch(String str, String regex){
if (StrUtil.isBlank(str)) {
return true;
}
return !str.matches(regex);
}
}
登录校验用户状态
因为很多功能都要校验用户,所以需要使用拦截器。
拦截器校验了用户信息,将用户信息放入每一个线程的ThreadLocal中,每个线程需要用户信息就从自己的ThreadLocal中获取,保证的线程安全。
拦截器
package com.xkj.org.interceptor;
import com.xkj.org.entity.User;
import com.xkj.org.utils.UserHolder;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
//1.获取session中的user
User user = (User)request.getSession().getAttribute("user");
//2.判断用户是否存在
if (user == null) {
//3.不存在,拦截, 401未授权
response.setStatus(401);
return false;
}
//4.存在,保存用户信息到ThreadLocal
UserHolder.saveUser(user);
//5.放行
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
//请求执行完毕,释放内存,threadlocal避免内存泄漏
UserHolder.removeUser();
}
}
ThreadLocal
package com.xkj.org.utils;
import com.xkj.org.entity.User;
public class UserHolder {
private static final ThreadLocal<User> t1 = new ThreadLocal<>();
public static void saveUser(User user) {
t1.set(user);
}
public static User getUser() {
return t1.get();
}
public static void removeUser() {
t1.remove();
}
}
配置拦截器
package com.xkj.org.config;
import com.xkj.org.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MvcConfig implements WebMvcConfigurer{
@Override
public void addInterceptors(InterceptorRegistry registry) {
//添加拦截器,排除一些不需要拦截的url
registry.addInterceptor(new LoginInterceptor())
.excludePathPatterns(
"/user/code",
"/user/login",
"/blog/hot",
"/shop/**",
"/shop-type/**",
"/upload/**",
"voucher/**"
);
}
}
用户相关功能
发送验证码
登录用户
获取用户信息
package com.xkj.org.controller;
import com.xkj.org.dto.LoginFormDTO;
import com.xkj.org.dto.Result;
import com.xkj.org.entity.User;
import com.xkj.org.service.IUserService;
import com.xkj.org.utils.UserHolder;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
@RequestMapping("/user")
@RestController
public class UserController {
@Resource
private IUserService userService;
@PostMapping("/code")
public Result sendCode(@RequestParam("phone") String phone, HttpSession session) {
return userService.sendCode(phone, session);
}
@PostMapping("/login")
public Result login(@RequestBody LoginFormDTO loginFormDTO, HttpSession session) {
return userService.login(loginFormDTO, session);
}
@GetMapping("/me")
public Result me() {
User user = UserHolder.getUser();
return Result.ok(user);
}
}
package com.xkj.org.service.impl;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xkj.org.dto.LoginFormDTO;
import com.xkj.org.dto.Result;
import com.xkj.org.entity.User;
import com.xkj.org.mapper.UserMapper;
import com.xkj.org.service.IUserService;
import com.xkj.org.utils.RegexUtils;
import com.xkj.org.utils.SystemConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpSession;
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService{
@Override
public Result sendCode(String phone, HttpSession session) {
//检验手机号
if (RegexUtils.isPhoneInvalid(phone)) {
return Result.fail("手机号无效");
}
//生成验证码
String code = RandomUtil.randomString(6);
//存入session
session.setAttribute("code", code);
//发送验证码给用户
log.info("给用户发送验证码============={}", code);
//返回
return Result.ok("发送成功");
}
@Override
public Result login(LoginFormDTO loginFormDTO, HttpSession session) {
//校验手机号
if (RegexUtils.isPhoneInvalid(loginFormDTO.getPhone())) {
return Result.fail("手机号无效");
}
//校验验证码
String cacheCode = session.getAttribute("code").toString();
String code = session.getAttribute("code").toString();
if (code == null || !code.equals(cacheCode)) {
return Result.fail("验证码错误");
}
//根据手机号查询用户
User user = query().eq("phone", loginFormDTO.getPhone()).one();
if (user == null) {
//用户不存在则创建用户
user = createUser(loginFormDTO.getPhone());
}
//将用户放入session
session.setAttribute("user", user);
//返回
return Result.ok();
}
private User createUser(String phone) {
User user = new User();
user.setPhone(phone);
user.setNickName(SystemConstants.USER_NICK_NAME_PREFIX + RandomUtil.randomString(6));
save(user);
return user;
}
}