苍穹外卖day01记录

张开发
2026/5/8 16:29:21 15 分钟阅读

分享文章

苍穹外卖day01记录
苍穹外卖黑马程序员 day01笔记我们这里省略掉配置文件的过程直接进行到完整的功能讲解注意一下我是用mac的在配置文件的时候和win不同强烈建议查看博客解决而不是只是盯着ai来处理错误。前后端联调测试nginx 反向代理流程说明在本项目中前端访问地址http://localhost:8088/api/employee/login后端服务端口8080虽然端口不同但依然可以访问成功其原因是使用了Nginx 反向代理。请求处理流程浏览器访问8088请求先到达NginxNginx 判断请求路径以/api/开头Nginx 将请求转发到8080端口的 SpringBoot 后端后端处理请求并返回结果Nginx 再将结果返回给浏览器实际访问链路浏览器 → Nginx(8088) → SpringBoot(8080)为什么可以这样访问因为 Nginx 起到了“中间代理”的作用浏览器并不直接访问后端所有请求先经过 Nginx再由 Nginx 转发给后端服务使用 Nginx 的作用前后端分离更清晰前端不需要直接暴露后端端口可以统一处理静态资源和接口请求可以解决跨域问题提高访问速度Nginx 可以对静态资源HTML、CSS、JS、图片等进行缓存和高效处理减少后端服务器压力从而提升整体响应速度。方便后期扩展负载均衡、集群部署负载均衡 当后端有多台服务器时Nginx 可以将请求分发到不同服务器上避免单点压力过大提高系统并发能力。提高系统安全性隐藏真实后端地址后端服务不会直接暴露给客户端所有请求必须经过 Nginx从而可以隐藏真实服务器地址并进行访问控制、防攻击等安全策略。Nginx 源码解析我们来看这个代码location /api/ { proxy_pass http://localhost:8080/admin/; }配置解析配置项含义location /api/匹配所有以/api/开头的请求路径proxy_pass http://localhost:8080/admin/;将请求转发到后端服务注意末尾有/关键点路径替换规则当proxy_pass后面带有路径/admin/时Nginx 会进行路径替换location匹配的路径部分/api/会被替换为proxy_pass中的路径/admin/实际转换示例以登录接口为例步骤路径前端请求http://localhost:8088/api/employee/loginlocation 匹配/api/替换为/admin/实际转发http://localhost:8080/admin/employee/login为什么这样设计隐藏后端真实路径前端用/api/后端用/admin/前后端路径不一致增强安全性统一路径前缀方便后端对/admin/开头的接口进行统一的权限拦截Shiro / Spring Security解耦前后端前端不需要知道后端实际的接口路径结构补充说明如果proxy_pass后面没有路径例如location /api/ { proxy_pass http://localhost:8080; }则转发时保留原始路径即/api/employee/login→http://localhost:8080/api/employee/loginMD5加密MD5加密算法将原始数据进行加密生成一个32位长度的字符串。MD5 不是用来“加密传输”而是用来“保护数据库里的密码”。防止数据库泄露后密码暴露。苍穹外卖原先的密码设置在数据库里面的是真实的密码不是通过md5加密的所以这里需要将密码进行md5加密。//密码比对// TODO 后期需要进行md5加密然后再进行比对/对前端传回来的代码进行md5加密 passwordDigestUtils.md5DigestAsHe(password.getBytes());}config配置类我们看以下这个放在config包下的类/** * 配置类注册web层相关组件 */ConfigurationSlf4jpublicclassWebMvcConfigurationextendsWebMvcConfigurationSupport{AutowiredprivateJwtTokenAdminInterceptorjwtTokenAdminInterceptor;/** * 注册自定义拦截器 * * param registry */protectedvoidaddInterceptors(InterceptorRegistryregistry){log.info(开始注册自定义拦截器...);registry.addInterceptor(jwtTokenAdminInterceptor).addPathPatterns(/admin/**).excludePathPatterns(/admin/employee/login);}/** * 通过knife4j生成接口文档 * return */BeanpublicDocketdocket(){log.info(准备生成接口文档...);ApiInfoapiInfonewApiInfoBuilder().title(苍穹外卖项目接口文档).version(2.0).description(苍穹外卖项目接口文档).build();DocketdocketnewDocket(DocumentationType.SWAGGER_2).apiInfo(apiInfo).select().apis(RequestHandlerSelectors.basePackage(com.sky.controller)).paths(PathSelectors.any()).build();returndocket;}/** * 设置静态资源映射 * param registry */protectedvoidaddResourceHandlers(ResourceHandlerRegistryregistry){log.info(开始进行静态资源映射...);registry.addResourceHandler(/doc.html).addResourceLocations(classpath:/META-INF/resources/);registry.addResourceHandler(/webjars/**).addResourceLocations(classpath:/META-INF/resources/webjars/);}}这个类的整体是在配置 SpringMVC 行为拦截器 文档 静态资源我们先看第一个部分registry.addInterceptor(jwtTokenAdminInterceptor).addPathPatterns(/admin/**).excludePathPatterns(/admin/employee/login);这是一个拦截器这个的意思就是admin/下面的所有后台接口都要拦截除了/admin/employee/login因为登陆接口不需要进行token验证不然别人咋去登陆。接下来是第二个部分BeanpublicDocketdocket(){log.info(准备生成接口文档...);ApiInfoapiInfonewApiInfoBuilder().title(苍穹外卖项目接口文档).version(2.0).description(苍穹外卖项目接口文档).build();DocketdocketnewDocket(DocumentationType.SWAGGER_2).apiInfo(apiInfo).select().apis(RequestHandlerSelectors.basePackage(com.sky.controller)).paths(PathSelectors.any()).build();returndocket;}这个部分是生成接口文档的这个接口文档生成工具是knife4j这个接口文档生成工具会自动生成接口文档。第三个部分protectedvoidaddResourceHandlers(ResourceHandlerRegistryregistry){log.info(开始进行静态资源映射...);registry.addResourceHandler(/doc.html).addResourceLocations(classpath:/META-INF/resources/);registry.addResourceHandler(/webjars/**).addResourceLocations(classpath:/META-INF/resources/webjars/);}这个部分是静态资源映射目的是让 Knife4j 接口文档页面能够正常访问。配置解析配置作用addResourceHandler(/doc.html)当访问/doc.html时addResourceLocations(classpath:/META-INF/resources/)去 classpath 下的这个目录找文件为什么需要这个配置Knife4j 的文档页面doc.html和相关的 JS/CSS 文件打包在项目的META-INF/resources/目录下。如果不配置静态资源映射这些资源无法通过 HTTP 访问文档页面就会加载失败。访问文档页面的路径Knife4j 文档首页http://localhost:8080/doc.html原始 Swagger 页面http://localhost:8080/swagger-ui.htmlWebJars 是什么WebJars 是将前端资源jQuery、Bootstrap、Vue 等打成 JAR 包方便 Maven/Gradle 管理。Knife4j 依赖的前端库如 swagger-ui就通过 WebJars 引入。实际效果配置后Nginx/浏览器就能找到/doc.html→classpath:/META-INF/resources/doc.html/webjars/**→classpath:/META-INF/resources/webjars/**登录功能详解我们先看一下完整的controller的登录类/** * 员工管理 */RestControllerRequestMapping(/admin/employee)Slf4jpublicclassEmployeeController{AutowiredprivateEmployeeServiceemployeeService;AutowiredprivateJwtPropertiesjwtProperties;/** * 登录 * * param employeeLoginDTO * return */PostMapping(/login)publicResultEmployeeLoginVOlogin(RequestBodyEmployeeLoginDTOemployeeLoginDTO){log.info(员工登录{},employeeLoginDTO);EmployeeemployeeemployeeService.login(employeeLoginDTO);//登录成功后生成jwt令牌MapString,ObjectclaimsnewHashMap();claims.put(JwtClaimsConstant.EMP_ID,employee.getId());StringtokenJwtUtil.createJWT(jwtProperties.getAdminSecretKey(),jwtProperties.getAdminTtl(),claims);EmployeeLoginVOemployeeLoginVOEmployeeLoginVO.builder().id(employee.getId()).userName(employee.getUsername()).name(employee.getName()).token(token).build();returnResult.success(employeeLoginVO);}/** * 退出 * * return */PostMapping(/logout)publicResultStringlogout(){returnResult.success();}}代码逐行解析第一步接收前端请求PostMapping(\/login\)publicResultEmployeeLoginVOlogin(RequestBodyEmployeeLoginDTOemployeeLoginDTO)PostMapping- 处理 POST 请求登录一般用 POSTRequestBody- 将 JSON 请求体自动反序列化为 DTO 对象EmployeeLoginDTO- 前端传入的登录数据用户名、密码第二步调用 Service 层验证EmployeeemployeeemployeeService.login(employeeLoginDTO);调用 Service 层进行业务处理下面的代码就是login的具体实现publicEmployeelogin(EmployeeLoginDTOemployeeLoginDTO){StringusernameemployeeLoginDTO.getUsername();StringpasswordemployeeLoginDTO.getPassword();//1、根据用户名查询数据库中的数据EmployeeemployeeemployeeMapper.getByUsername(username);//2、处理各种异常情况用户名不存在、密码不对、账号被锁定if(employeenull){//账号不存在thrownewAccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);}//密码比对// TODO 后期需要进行md5加密然后再进行比对passwordDigestUtils.md5DigestAsHex(password.getBytes());if(!password.equals(employee.getPassword())){//密码错误thrownewPasswordErrorException(MessageConstant.PASSWORD_ERROR);}if(employee.getStatus()StatusConstant.DISABLE){//账号被锁定thrownewAccountLockedException(MessageConstant.ACCOUNT_LOCKED);}//3、返回实体对象returnemployee;}根据用户名查询数据库验证密码MD5加密后比对返回完整的 Employee 实体对象第三步生成 JWT 令牌MapString,ObjectclaimsnewHashMap();claims.put(JwtClaimsConstant.EMP_ID,employee.getId());StringtokenJwtUtil.createJWT(jwtProperties.getAdminSecretKey(),// 密钥jwtProperties.getAdminTtl(),// 过期时间claims// 载荷数据);组件作用claims存放用户信息这里只存了员工 IDSecretKey签名密钥用于验证 token 合法性TTLToken 过期时间一般 12 小时或 24 小时第四步构建返回 VOEmployeeLoginVOemployeeLoginVOEmployeeLoginVO.builder().id(employee.getId()).userName(employee.getUsername()).name(employee.getName()).token(token).build();字段来源id数据库返回的员工主键userName数据库中的用户名name员工真实姓名token刚刚生成的 JWT 令牌第五步返回给前端returnResult.success(employeeLoginVO);前端收到后将 token 存储到 localStorage后续请求带上这个 token。总结day01主要完善了登录功能并且完善了接口文档以及相关的配置文件。

更多文章