当前位置: 首页 > news >正文

JavaWeb(05)

在这里插入图片描述

环境搭建

  • 准备数据库表(dept,emp)
  • 创建springboot工程,引入对应的起步依赖
  • 配置文件application.properties 中引入mybatis的配置信息,准备对应的实体类
  • 准备对应的Mapper,Service(接口,实现类),Controller基础结构

项目结构
在这里插入图片描述

配置文件
在这里插入图片描述

编写规范

  • 基本信息
    • 请求路径
    • 请求方式
    • 接口描述
  • 接收参数
  • 响应数据
    • 参数含义
    • 响应数据的案例(json的格式)

Restful - 开发规范

  • REST(REpresentational State Transfer),表述性状态转换,它是一种软甲架构风格
  • URL定位资源
  • HTTP动词描述操作
  • REST 是风格,是约定方式,约定不是规定,可以打破。
  • 描述模块的功能通常使用复数,也就是加 s 的格式来描述,表示此类资源,而非单个资源。如:users、emps、books…
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {private Integer code; // 响应码,1 代表成功;0 代表失败private String msg;  // 响应信息 描述字符串private Object data; // 返回的数据public static Result success() { // 增删改 成功响应return new Result(1, "success", null);}public static Result success(Object data) { // 查询 成功响应return new Result(1, "success", data);}public static Result error(String msg) { // 失败响应return new Result(0, msg, null);}
}
  • 查看页面原型,明确需求
  • 阅读接口文档
  • 思路分析
  • 接口开发
  • 接口测试
  • 前后端联调

日志记录


import org.slf4j.Logger;  
import org.slf4j.LoggerFactory;log .info("user");

labok 中为注解提供了一种注解 @Slf4j --> 然后就可以之直接使用 log

注: @RestController 注解中包含了一个 @ResponseBody --> 可以将返回对象直接返回为json对象

个人梳理:

  1. Controller中写入一个 service 层 的接口 ,底层会自动将该接口实例化
  2. 然后调用 service 层的方法
  3. 同样的方式进入 mapper 层

解决跨域问题

  • 后端实现
// 全局配置类
@Configuration
public class CorsConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**")  // 所有接口.allowedOrigins("http://localhost:3000", "http://your-domain.com") // 允许的源.allowedMethods("*")  // GET/POST等.allowedHeaders("*")  // 请求头.allowCredentials(true)  // 允许带cookie.maxAge(3600);  // 预检请求缓存时间}
}

这段 Java 代码定义了一个名为CorsConfig的全局配置类,用于解决跨域资源共享(CORS)问题,以下是对该类各部分作用的详细解析:

1. 类声明及实现接口

@Configuration
public class CorsConfig implements WebMvcConfigurer {

@Configuration 是 Spring 框架中的一个注解,用于标记该类是一个配置类,Spring 容器会扫描并加载该类中的配置信息。
CorsConfig 类实现了 WebMvcConfigurer 接口,通过实现这个接口,可以自定义 Spring MVC 的配置,这里主要用于配置 CORS 相关的信息。

2. addCorsMappings 方法

@Override
public void addCorsMappings(CorsRegistry registry) {

addCorsMappings 方法是 WebMvcConfigurer 接口中的一个方法,通过重写这个方法来配置 CORS 策略。CorsRegistry 是 Spring 提供的一个用于注册 CORS 映射的类,通过它可以定义哪些请求路径适用 CORS 配置,以及具体的 CORS 配置项。

3. 配置 CORS 具体策略

registry.addMapping("/**").allowedOrigins("http://localhost:3000", "http://your-domain.com").allowedMethods("*").allowedHeaders("*").allowCredentials(true).maxAge(3600);
  • addMapping("/**"):表示对所有的接口(路径)都应用 CORS 配置。"/**" 是一个通配符,匹配所有请求路径。
  • .allowedOrigins("http://localhost:3000", "http://your-domain.com"):设置允许访问该后端服务的源(origin)。这里指定了两个源,http://localhost:3000http://your-domain.com,只有来自这两个源的请求会被允许跨域访问。如果需要允许所有源,可以使用 "*",但这样存在安全风险,不建议在生产环境中使用。
  • .allowedMethods("*"):设置允许的 HTTP 方法,这里 "*" 表示允许所有的 HTTP 方法,如 GET、POST、PUT、DELETE 等。也可以具体指定,例如 ".allowedMethods("GET", "POST")"
  • .allowedHeaders("*"):设置允许在请求头中携带的字段,"*" 表示允许所有请求头字段。同样,也可以具体指定允许的请求头字段。
  • .allowCredentials(true):设置是否允许携带 Cookie 等认证信息。设置为 true 表示允许在跨域请求中携带 Cookie,前提是请求的源在 allowedOrigins 中明确列出,因为不能对 * 源启用该功能。
  • .maxAge(3600):设置预检请求(OPTIONS 请求)的缓存时间,单位是秒。在缓存时间内,浏览器不会再次发送预检请求,而是直接使用缓存中的 CORS 配置,从而提高性能。

总的来说,这个 CorsConfig 类通过上述配置,使得 Spring Boot 应用能够支持跨域请求,并且对跨域请求的源、方法、请求头、是否允许携带认证信息以及预检请求缓存等方面进行了详细的设置。


// 在 vue.config.js 中配置
module.exports = {devServer: {proxy: {'/api': {target: 'http://localhost:8080', // 后端地址changeOrigin: true,pathRewrite: { '^/api': '' } // 去掉路径中的/api}}}
}

前端获取数据

    fetchUsers() {fetch('/api/user').then(response => response.json()).then(data => {this.users = data.data;}).catch(error => {console.error(error);});},
  • 将得到的数据返回 json 格式
  • 然后就可以通过 json 方式访问到数据

简化Mapping层的代码

在这里插入图片描述

mapper层的SQL写法

@Update("UPDATE learn01 SET name=#{name},age=#{age} WHERE id=#{id}")  
void edit(User user);

事件总线

  1. 创建一个空的 Vue 实例作为 “总线”(全局唯一)
  2. 发送方组件通过 bus.$emit('事件名', 数据) 发送事件
  3. 接收方组件通过 bus.$on('事件名', 回调函数) 监听事件
  4. 回调函数中可以处理接收到的数据或执行相应方法
  5. 组件销毁前需通过 bus.$off('事件名') 移除监听,避免内存泄漏

登录

  • 登录功能
  • 登录校验
    • 会话技术
    • JWT令牌
    • 过滤器 Filter
    • 拦截器 Interceptor
  • 异常处理

会话技术

会话:用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束。在一次会话中可以包含多次请求和响应

会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同一次会话的多次请求间共享数据

  • 客户端会话跟踪技术:Cookie
    • 优点:HTTP协议中支持的技术
    • 缺点
      • 移动端APP无法使用Cookie
      • 不安全,用户可以自己警用Cookie
      • Cookie不能跨域
  • 服务端会话跟踪技术:Session
    • 优点:存储在服务端,安全
    • 缺点
      • 服务器集群环境下无法直接使用Session
      • Cookie的缺点
  • 令牌技术
    • 优点
      • 支持PC端,移动端
      • 解决集群环境下的认证问题
      • 减轻服务器端存储压力
    • 缺点:需要自己来实现

JWT(JSON Web Token)

简介

定义了一种简洁的,自包含的格式,用于在通信双方以json数据格式安全的传输信息,由于数字签名的存在,这些信息是可靠的

  • 组成
    • 第一部分:Header, 记录令牌类型,签名算法
    • 第二部分:Payload(有效荷载),携带一些自定义信息,默认信息
    • 第三部分:Signature(签名),防止Token被篡改,保证安全性,将header,payload,并加入指定密钥,通过指定签名算法计算而来

JWT生成

配置依赖项

<dependency>  <groupId>io.jsonwebtoken</groupId>  <artifactId>jjwt-api</artifactId>  <version>0.11.5</version>  
</dependency>  
<!-- JJWT 实现 -->  
<dependency>  <groupId>io.jsonwebtoken</groupId>  <artifactId>jjwt-impl</artifactId>  <version>0.11.5</version>  <scope>runtime</scope>  
</dependency>  
<!-- JJWT JSON 处理器 -->  
<dependency>  <groupId>io.jsonwebtoken</groupId>  <artifactId>jjwt-jackson</artifactId>  <version>0.11.5</version>  <scope>runtime</scope>  
</dependency>

@Test  
void getJwt(){  Map<String,Object> map = new HashMap<>();  map.put("id","1");  map.put("username","admin");  SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS256);  String jwt = Jwts.builder()  .setClaims(map)  .signWith(SignatureAlgorithm.HS256,key)  .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 12))  .compact();  System.out.println(jwt);  Claims claims = Jwts.parser()  .setSigningKey(key)  .parseClaimsJws(jwt)  .getBody();  System.out.println(claims);  
}

Filter过滤器

  • 概念:Filter 过滤器,是JavaWeb三大组件之一
  • 过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能
  • 过滤器一般完成一些通用的操作:登录校验,同一编码处理,敏感字符处理等
  1. 快速入门
  2. 详解
  3. 登录校验

快速入门

  1. 定义Filter:定义一个类,实现Filter接口,并重写其所有方法
  2. 配置Filter:Filter类上加@WebFilter 注解,配置拦截资源的路径。引导类上加 @ServletComponentScan 开启Servlet组件支持
public class DemoFilter implements Filter {public void init(FilterConfig filterConfig) throws ServletException { //初始化方法, Web服务器启动, 创建Filter时调用, 只调用一次Filter.super.init(filterConfig);}public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) //拦截到请求时, 调用该方法, 可调用多次System.out.println("拦截方法执行,拦截到了请求 ...");chain.doFilter(request, response); //放行sout("放行之后的逻辑");}
}
拦截路径urlPatterns 值含义
拦截具体路径/login只有访问 /login 路径时,才会被拦截
目录拦截/emps/*访问 /emps 下的所有资源,都会被拦截
拦截所有/*访问所有资源,都会被拦截

过滤器链

在这里插入图片描述

顺序:注解配置恶的Filter,优先级是按照过滤器类名(字符串)的自然顺序

登录校验

  • 获取请求 url。
  • 判断请求 url 中是否包含 login,如果包含,说明是登录操作,放行。
  • 获取请求头中的令牌(token)。
  • 判断令牌是否存在,如果不存在,返回错误结果(未登录)。
  • 解析 token,如果解析失败,返回错误结果(未登录)。
  • 放行。

将对象转换成json格式 引入的依赖

<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.76</version>
</dependency>
@Slf4j
@WebFilter(urlPatterns = "/*")
public class LoginCheckFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, HttpServletRequest req = (HttpServletRequest) request;HttpServletResponse resp = (HttpServletResponse) response;//1.获取请求url。String url = req.getRequestURL().toString();log.info("请求的url: {}",url);//2.判断请求url中是否包含login,如果包含,说明是登录操作,放行。if(url.contains("login")){log.info("");}//3.获取请求头中的令牌(token)。String jwt = req.getHeader("token");//4.判断令牌是否存在,如果不存在,返回错误结果(未登录)。if(!StringUtils.hasLength(jwt)){log.info("请求头token为空,返回未登录的信息");Result error = Result.error("NOT_LOGIN");//手动转换 对象--json -------> 阿里巴巴fastJSONString notLogin = JSONObject.toJSONString(error);resp.getWriter().write(notLogin);return;}try {JwtUtils.parseJWT(jwt);} catch (Exception e) { //jwt解析失败e.printStackTrace();log.info("解析令牌失败,返回未登录错误信息");Result error = Result.error("NOT_LOGIN");//手动转换 对象--json -------> 阿里巴巴fastJSONString notLogin = JSONObject.toJSONString(error);resp.getWriter().write(notLogin);return;}//6.放行。log.info("令牌合法,放行");chain.doFilter(request, response);
}

拦截器(Interceptor)

概念:是一种动态拦截方法调用的机制,类似于过滤器。spring框架中提供的,用来动态拦截控制器方法的执行

作用:拦截请求,在指定的方法调用前后,更具业务需求执行预定设定的代码

  1. 定义拦截器,实现HandlerInterceptor接口,并重写其所有方法
  2. 注册拦截器
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {@Override //目标资源方法执行前执行,放回true: 放行,返回false: 不放行public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {System.out.println("preHandle ...");return true;}@Override //目标资源方法执行后执行public void postHandle(HttpServletRequest req, HttpServletResponse resp, Object handler, ModelAndView modelAndView) {System.out.println("postHandle ...");}@Override // 视图渲染完毕后运行public void afterCompletion(HttpServletRequest req, HttpServletResponse resp, Object handler, Exception ex) {System.out.println("afterCompletion ...");}
}
@Configuration
public class WebConfig implements WebMvcConfigurer {@Autowiredprivate LoginCheckInterceptor loginCheckInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**");}
}

详解

拦截路径含义举例
/*一级路径能匹配/depts/emps/login,不能匹配 /depts/1
/**任意级路径能匹配/depts/depts/1/depts/1/2
/depts/*/depts下的一级路径能匹配/depts/1,不能匹配/depts/1/2/depts
/depts/**/depts下的任意级路径能匹配/depts/depts/1/depts/1/2,不能匹配/emps/1
@Override
public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**").excludePathPatterns("/login");
}
// 需要拦截哪些资源               不需要拦截哪些资源

在这里插入图片描述

Filter 与 Interceptor 之间的区别

  • 接口规范不同:过滤器需要实现 Filter 接口,而拦截器需要实现 HandlerInterceptor 接口
  • 拦截范围不同:过滤器 Filter 会拦截所有的资源,而 Interceptor 只会拦截 Spring 环境中的资源

异常处理

全局异常处理器

遇到异常时的处理逻辑:

Mapper --> Service --> Controller --> 全局异常处理器

@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(Exception.class)public Result ex(Exception ex){ex.printStackTrace();return Result.error(" 对不起,操作失败,请联系管理员 ");}
}
http://www.lryc.cn/news/620330.html

相关文章:

  • TCP客户端Linux网络编程设计详解
  • 人工智能——CNN基础:卷积和池化
  • HiSmartPerf使用WIFI方式连接Android机显示当前设备0.0.0.0无法ping通!设备和电脑连接同一网络,将设备保持亮屏重新尝试
  • SAP Valuation Category在制造业成本核算中的使用场景与配置方案
  • 基于C语言基础对C++的进一步学习_C和C++编程范式、C与C++对比的一些补充知识、C++中的命名空间、文件分层
  • window显示驱动开发—多平面覆盖 VidPN 呈现
  • 看懂 Linux 硬件信息查看与故障排查
  • 力扣42:接雨水
  • 人工智能入门①:AI基础知识(上)
  • Python图像处理基础(十三)
  • 《工程封装》(Python)
  • 网络安全合规6--服务器安全检测和防御技术
  • 3.Ansible编写和运行playbook
  • 3DM游戏运行库合集离线安装包下载, msvcp140.dll丢失等问题修复
  • ESP32_STM32_DHT20
  • 三极管的基极为什么需要下拉电阻
  • Vue3从入门到精通:4.1 Vue Router 4深度解析与实战应用
  • vue实现模拟 ai 对话功能
  • JS的学习5
  • vue修改element的css属性
  • 决策树回归:用“分而治之”的智慧,搞定非线性回归难题(附3D可视化)
  • 北京JAVA基础面试30天打卡09
  • uniapp授权登录
  • 硬件工程师八月实战项目分享
  • 8.13迎来联动:PUBG布加迪,新版本37.1内容资讯!低配置也能飙车吃鸡!
  • 谈一些iOS组件化相关的东西
  • 【Golang】 Context.WithCancel 全面解析与实战指南
  • CAN仲裁机制的原理
  • 【CV 目标检测】③——目标检测方法
  • 玳瑁的嵌入式日记D17-08013(linux文件编程)