【智能排班系统】Hibernate Validator 参数校验

🎯导读:本文档介绍了参数校验的重要性及其在软件开发中的作用,强调了数据完整性、安全性、用户体验、系统稳定性及开发效率等方面的关键价值。文档详细阐述了Hibernate Validator这一流行的Java验证框架的使用方法,展示了如何利用其内置注解(如@NotNull、@Size、@Email等)来对输入数据进行有效性检查。此外,还探讨了自定义校验规则的开发方式,以及如何通过分组校验来适应不同的业务场景需求。通过集成Hibernate Validator,开发者可以显著提升应用程序的质量与用户体验。

文章目录

  • 参数校验
  • Hibernate Validator 简介
  • 依赖
  • 基础使用
  • 常用校验注解
    • 字段校验注解
    • 其他注解
  • 分组校验
    • 定义分组
    • 使用
  • 自定义校验
    • 定义注解
    • 校验器实现
    • 使用
    • 排班系统实现(以添加节日为例)
      • 代码位置
      • 参数类
      • 接口
      • 统一异常处理
      • 测试
  • 嵌套校验

参数校验

参数校验是指在接收输入数据时,对传入的参数进行验证,以确保它们符合预期的格式、范围和有效性。这种校验对于保证软件的稳定性和安全性至关重要。以下是参数校验的一些关键作用和意义:

  1. 数据完整性:
    1. 参数校验可以帮助确保接收到的数据符合预期的格式和结构。例如,通过校验确保日期格式正确、数值在合理范围内、字符串长度合适等。
    2. 这样可以防止因输入数据错误而导致的程序异常或错误行为。
  2. 安全性:
    1. 校验可以防止恶意或意外的数据注入,如 SQL 注入、XSS 攻击等。通过严格的校验规则,可以降低这些安全风险。
    2. 正确的校验机制能够帮助过滤掉不安全的输入,保护系统免受攻击。
  3. 用户体验:
    1. 在用户界面上,及时反馈错误信息给用户,帮助他们更快地纠正输入错误,改善用户体验。
    2. 清晰的错误提示可以使用户更容易理解和操作系统,减少因输入错误造成的困惑和沮丧感。
  4. 系统稳定性:
    1. 通过在校验阶段捕获潜在的问题,可以提前处理错误情况,避免后续处理逻辑中出现未预见的异常。
    2. 这有助于确保系统在面对各种输入时都能保持一致的行为,提高系统的可靠性和稳定性。
  5. 开发效率:
    1. 自动化的参数校验减少了手工检查的需要,简化了开发过程,降低了出错的可能性。
    2. 开发者可以专注于核心业务逻辑,而不必担心基础的数据验证问题。
  6. 易于维护:
    1. 明确的校验规则使得代码更易于理解和维护。当需要调整业务逻辑或数据格式时,可以在一处修改校验逻辑即可。
    2. 这有助于保持代码的清晰和整洁,便于团队协作。

Hibernate Validator 简介

参数校验最直接的方式就是在方法中实现具体的逻辑来判断参数是否合理,但是如果每个方法都要这样判断,未免太过复杂,Hibernate Validator 定义了一些常用的校验注解可以帮助我们快速搞定一些常见的常数校验,如非空、长度限制、邮件是否合格……

Hibernate Validator 是一个强大的开源库,用于实现 Java Bean Validation(JSR 303 和 JSR 380)规范。它是 Java 应用程序中最广泛使用的验证框架之一。Hibernate Validator 提供了一套丰富的约束注解,允许开发者轻松地对实体对象中的属性进行约束定义,确保它们满足特定的业务规则。通过使用如 @NotNull@Size@Pattern 等内置注解,开发者可以方便地检查对象的状态,确保数据的完整性和一致性。

Hibernate Validator 不仅支持标准的 JSR 规范中定义的约束,还提供了一些额外的注解,如 @Length@ScriptAssert,使得验证逻辑更加灵活和强大。此外,它还支持自定义约束注解的开发,允许根据具体的应用需求来扩展验证功能。通过集成 Hibernate Validator,开发者可以在运行时自动执行验证逻辑,减少手工编写验证代码的工作量,并提高代码的可读性和可维护性。

Hibernate Validator 的应用场景非常广泛,从简单的 Web 表单数据验证到复杂的业务规则检查,都可以看到它的身影。无论是前端还是后端开发,Hibernate Validator 都能帮助开发者确保数据的准确性和有效性,从而提升软件的质量和用户体验。

依赖

在父工程添加如下依赖来管理版本

<hibernate-validator.version>6.2.5.Final</hibernate-validator.version><dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator</artifactId><version>${hibernate-validator.version}</version>
</dependency>

sss-commonsss-enterprisesss-aggregation模块添加都如下依赖,你可能会疑惑,sss-enterprise模块不是已经导入了sss-common了吗,为什么还要重复引用。亲测不引用,参数会生效,这个bug我找了一个下午o(╥﹏╥)o

<dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator</artifactId>
</dependency>

基础使用

首先给参数类的字段添加注解,例如给name定义非空检验

@Data
@TableName("festival")
@NoArgsConstructor
@AllArgsConstructor
public class FestivalEntity extends BaseEntity implements Serializable {private static final long serialVersionUID = 1L;/*** 节日名称*/@NotBlank(message = "节日名称不能为空")private String name;/*** 起始日期*/@NotNull(message = "起始日期不能为空")private Date startDate;/*** 截止日期*/@NotNull(message = "截止日期不能为空")private Date endDate;/*** 门店id*/@JsonSerialize(using = ToStringSerializer.class)private Long storeId;/*** 0:农历 1:新历*/private int type;
}

接在给Controller的方法添加校验注解,@Validated要添加在@RequestBody前面,这样接收到参数festival之后,就会按照所设定规则对里面的字段值进行校验

@PostMapping("/save")
public R save(@Validated @RequestBody FestivalEntity festival, HttpServletRequest httpServletRequest) {long storeId = Long.parseLong(JwtUtil.getStoreId(httpServletRequest.getHeader("token")));festival.setStoreId(storeId);festivalService.save(festival);return R.ok();
}

常用校验注解

字段校验注解

【布尔类】

  • **@AssertTrue**布尔表达式必须为true。
  • **@AssertFalse**布尔表达式必须为false。
@AssertTrue(message = "你必须同意服务条款")
private boolean agreeToTerms;@AssertFalse(message = "您必须不是机器人")
private boolean isRobot;

【数字类】

  • **@Min**数值必须大于等于指定的最小值。
  • **@Max**数值必须小于等于指定的最大值。
  • **@DecimalMin**十进制数必须大于等于指定的最小值。
  • **@DecimalMax**十进制数必须小于等于指定的最大值。
  • **@Digits**检查数字的整数部分和小数部分的位数是否不超过指定的值。
  • **@Range**数字或日期必须在指定范围内。
  • **@Negative**数字必须是负数。
  • **@NegativeOrZero**数字必须是负数或零。
  • **@Positive**数字必须是正数。
  • **@PositiveOrZero**数字必须是正数或零。
// 确保年龄至少为 18 岁
@Min(value = 18)
private int age;
// 确保考试分数不能超过 100 分
@Max(value = 100)
private int score;// 确保价格至少为 10.00。inclusive = true 表示包括 10.00 在内
@DecimalMin(value = "10.00", inclusive = true)
private BigDecimal price;
// 确保折扣率不能超过 0.99。inclusive = false 表示不包括 0.99
@DecimalMax(value = "0.99", inclusive = false)
private BigDecimal discountRate;@Digits(integer = 10, fraction = 2, message = "交易金额的整数部分不能超过10位数,小数部分不能超过2位数")
private BigDecimal amount;@Digits(integer = 5, fraction = 2, message = "手续费的整数部分不能超过5位数,小数部分不能超过2位数")
private BigDecimal fee;@Range(min = 18, max = 100, message = "年龄必须在18到100岁之间")
private int age;@Negative(message = "温度必须低于零度")
private double temperature;@NegativeOrZero(message = "海拔高度必须是负数或零")
private int altitude;@Positive(message = "体重必须是正数")
private double weight;@PositiveOrZero(message = "身高必须是正数或零")
private double height;

【日期类】

  • **@Past**日期必须在过去。
  • **@Future**日期必须在未来。
  • @PastOrPresent:用于验证日期是否在过去或当前日期。
  • @FutureOrPresent:用于验证日期是否在未来或当前日期。
@Past(message = "出生日期必须在过去")
private LocalDate birthDate;
@Future(message = "预约日期必须在未来")
private LocalDate appointmentDate;
@PastOrPresent
private LocalDate lastLogin;
@FutureOrPresent
private LocalDate nextAppointment;

【字符串类】

  • **@NotBlank**字符串不能为null且去除空白后长度必须大于零。
  • **@Length**字符串长度必须在指定范围内。
  • **@Email**字符串必须是有效的电子邮件地址。
  • **@Pattern**字符串必须匹配正则表达式。
  • **@CreditCardNumber**字符串必须是一个有效的信用卡号。
@NotBlank(message = "评论内容不能为空")
@Length(min = 5, max = 200, message = "评论内容长度必须在5到200个字符之间")
private String content;
@Email(message = "电子邮件地址无效")
private String email;
@NotBlank(message = "密码不能为空")
@Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{8,}$", message = "密码必须包含字母和数字,且长度至少为8个字符")
private String password;
@CreditCardNumber(message = "信用卡号无效")
private String creditCardNumber;

【通用】

  • **@NotEmpty**字符串、集合、数组等不能为null且长度必须大于零。
  • **@NotNull**字段或属性不能为null。
  • **@Null**字段或属性必须为null。
  • **@Size**用于字符串、集合、数组等,检查大小是否在指定范围内。
@NotNull(message = "用户名不能为空")
private String username;@NotNull(message = "密码不能为空")
private String password;@Size(min = 3, max = 20, message = "用户名长度必须在3到20个字符之间")
private String username;
@Size(min = 1, message = "至少需要选择一项兴趣")
private List<String> interests;@NotEmpty(message = "用户名不能为空")
private String username;

其他注解

  • **@Constraint**用于创建自定义约束。
  • **@ConstraintValidator**用于创建自定义约束的验证器。
  • **@ConstraintViolation**用于描述约束违反的情况。
  • **@ConstraintDescriptor**用于描述约束元数据。
  • **@ValidationGroups**允许你对验证逻辑进行分组,从而控制哪些约束在何时被应用。
  • **@Valid**应用于对象,验证对象的所有属性。
  • **@Validated**通常用于框架集成,比如Spring,以启用方法参数验证。

分组校验

同一个字段,不同方法中可能对其有不同的要求。例如名字这个字段,添加用户的时候要求该字段非空,但修改用户信息的时候,如果不修改名字,该字段可以为空。

为了满足上面的需求,我们需要定义不同的小组来进行校验隔离

定义分组

新增分组

/*** @Author dam* @create 2024/8/31 10:32*/
public interface AddGroup {
}

修改分组

/*** @Author dam* @create 2024/8/31 10:32*/
public interface UpdateGroup {
}

使用

在使用注解的时候,使用groups属性来定义即可

@NotNull(message = "起始日期不能为空", groups = {AddGroup.class})
private Date startDate;@NotNull(message = "起始日期不能为空", groups = {AddGroup.class, UpdateGroup.class})
private Date startDate;

自定义校验

自定义校验规则是为了让我们可以定义一些项目通用,但是Hibernate Validator不具备的校验方法。下面的例子会实现一个校验 传入参数 是否被 指定数组 所包含,例如参数是被在{1,2,3,4,5}当中

定义注解

import com.dam.valid.validator.TypeValidator;import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;/*** 注解:校验是否在所包含的数字中** @Author dam* @create 2024/8/31 10:48*/
@Documented
@Constraint(validatedBy = {TypeValidator.class})
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface TypeAnno {//--------------- 必须包含字段 ----------------String message() default "字段必须是0或1";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};//--------------- 自定义字段 ----------------/*** 用来接收所包含的值**/int[] values() default {};
}
  • @Documented:当你生成Javadoc文档时,该注解将被记录下来,方便其他开发者查阅
  • @Constraint(validatedBy = {TypeValidator.class}):表示这是一个验证约束注解,并指定了一个验证器类 TypeValidator,用于执行具体的验证逻辑。 validatedBy属性用来指定一个或多个验证器类,这些类负责实现具体的验证逻辑
  • @Target:定义此注解可以应用的目标元素类型。
    • ElementType.METHOD:方法。
    • ElementType.FIELD:字段。
    • ElementType.CONSTRUCTOR:构造函数。
    • ElementType.PARAMETER:方法或构造函数的参数。
  • @Retention(RetentionPolicy.RUNTIME):定义了注解的保留策略,这里设置为 RUNTIME,意味着该注解将在编译时保留,并且可以在运行时通过反射访问。

校验器实现

import com.dam.valid.annotations.TypeAnno;import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.HashSet;
import java.util.Set;/*** 校验器:校验是否在所包含的数字中** @Author dam* @create 2024/8/31 10:52*/
public class TypeValidator implements ConstraintValidator<TypeAnno, Integer> {/*** 存储类型*/private Set<Integer> typeSet = new HashSet<>();@Overridepublic void initialize(TypeAnno constraintAnnotation) {for (int value : constraintAnnotation.values()) {typeSet.add(value);}}/*** 校验字段是否有效** @param value 要校验的值* @param context* @return*/@Overridepublic boolean isValid(Integer value, ConstraintValidatorContext context) {System.out.println("触发校验");return typeSet.contains(value);}
}

使用

/*** 0:农历 1:新历*/
@TypeAnno(values = {0, 1}, groups = {AddGroup.class}, message = "节日日期类型只能是农历(0)、新历(1)")
private int type;

排班系统实现(以添加节日为例)

代码位置

在这里插入图片描述

参数类

import com.baomidou.mybatisplus.annotation.TableName;
import com.dam.model.entity.BaseEntity;
import com.dam.valid.annotations.TypeAnno;
import com.dam.valid.groups.AddGroup;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;/*** 门店节日表** @author dam* @email 1782067308@qq.com* @date 2023-03-13 16:42:08*/
@Data
@TableName("festival")
@NoArgsConstructor
@AllArgsConstructor
public class FestivalEntity extends BaseEntity implements Serializable {private static final long serialVersionUID = 1L;/*** 节日名称*/@NotBlank(message = "节日名称不能为空")private String name;/*** 起始日期*/@NotNull(message = "起始日期不能为空", groups = {AddGroup.class})private Date startDate;/*** 截止日期*/@NotNull(message = "截止日期不能为空", groups = {AddGroup.class})private Date endDate;/*** 门店id*/@JsonSerialize(using = ToStringSerializer.class)private Long storeId;/*** 0:农历 1:新历*/@TypeAnno(values = {0, 1}, groups = {AddGroup.class}, message = "节日日期类型只能是农历(0)、新历(1)")private int type;
}

接口

/*** 保存*/
@PostMapping("/save")
@OperationLog(title = FestivalController.title, businessType = BusinessTypeEnum.INSERT, detail = "新增节日")
@PreAuthorize("hasAuthority('bnt.festival.add')")
public R save(@Validated({AddGroup.class}) @RequestBody FestivalEntity festival, HttpServletRequest httpServletRequest) {long storeId = Long.parseLong(JwtUtil.getStoreId(httpServletRequest.getHeader("token")));festival.setStoreId(storeId);festivalService.save(festival);return R.ok();
}

统一异常处理

当请求参数未能通过 Spring MVC 的数据绑定和校验时,会抛出 MethodArgumentNotValidException。该方法捕捉此类异常,并将校验错误信息整理后返回给客户端。

import com.dam.model.enums.ResultCodeEnum;
import com.dam.model.result.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;import java.util.HashMap;
import java.util.Map;@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {/*** 参数校验异常* @param exception* @return*/@ExceptionHandler(value = MethodArgumentNotValidException.class)@ResponseBodypublic R handleValidException(MethodArgumentNotValidException exception) {// 创建一个 Map 用来存储每个字段的错误信息Map<String, String> map = new HashMap<>();// 获取数据校验的错误结果BindingResult bindingResult = exception.getBindingResult();// 遍历所有的 FieldError 对象,将每个字段的错误信息存入 map 中bindingResult.getFieldErrors().forEach(fieldError -> {// 获取错误信息String message = fieldError.getDefaultMessage();// 获取字段名String field = fieldError.getField();// 将字段名和错误信息放入 mapmap.put(field, message);});// 记录错误日志log.error("数据校验出现问题{}, 异常类型{}", exception.getMessage(), exception.getClass());// 获取错误信息并格式化成字符串StringBuilder sb = new StringBuilder();int id = 1;for (String key : map.keySet()) {// 格式化错误信息,每条错误信息前加上编号sb.append(id++).append(") ").append(key).append("->").append(map.get(key)).append("<br/>");}// 打印错误信息到控制台System.out.println(sb.toString());// 返回包含错误代码和错误信息的 R 对象return R.error(ResultCodeEnum.ARGUMENT_VALID_ERROR.getCode(), ResultCodeEnum.ARGUMENT_VALID_ERROR.getMessage() + ":<br/>" + sb.toString());}
}

测试

使用ApiFox软件来进行接口测试

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

定义请求头参数

在这里插入图片描述

发送请求

在这里插入图片描述

嵌套校验

嵌套校验指在进行数据验证时,不仅仅检查顶层对象的属性是否符合预期,同时也深入到对象的子对象或者集合中去验证它们的属性是否满足特定规则的过程。这种校验方式常见于复杂的数据结构中,比如对象的属性可能是一个列表,而列表中的每个元素本身又是一个对象;或者是对象的某个属性是一个具有多个字段的另一个对象。这时需要使用@Valid来修饰该属性

import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;// 订单实体类
public class Order {@NotNull(message = "用户信息不能为空")@Validprivate User user;@NotEmpty(message = "订单中至少需要包含一个产品")@Validprivate List<Product> products;// Getters and Setterspublic User getUser() {return user;}public void setUser(User user) {this.user = user;}public List<Product> getProducts() {return products;}public void setProducts(List<Product> products) {this.products = products;}
}// 用户实体类
public class User {@NotNull(message = "用户名不能为空")private String name;// Getters and Setterspublic String getName() {return name;}public void setName(String name) {this.name = name;}public Address getAddress() {return address;}public void setAddress(Address address) {this.address = address;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/52778.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

异业联盟的巅峰之作!某店生活 两年百亿销售额!

大家好 我是一家软件开发公司的产品经理 吴军 最近有个爆火的商业模式 带动了三方消费 平台能赚到钱 消费者能省钱 商家也能获取到客源甚至还能赚钱 他究竟是怎么样做到三方都赚到钱的&#xff1f; 在当前经济形势下&#xff0c;许多消费者变得谨慎&#xff0c;减少了不必…

Git之2.5版本重要特性及用法实例(五十七)

简介&#xff1a; CSDN博客专家、《Android系统多媒体进阶实战》一书作者. 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a; 多媒体系统工程师系列…

【架构设计】安全架构设计

安全架构概述 在当今以计算机、网络和软件为载体的数字化服务几乎成为人类社会赖以生存的手段&#xff0c;与之而来的计算机犯罪呈现指数上升趋势&#xff0c;因此&#xff0c;信息的可用性、完整性、机密性、可控性和不可抵赖性等安全保障有位重要&#xff0c;为满足这些诉求&…

【测试】——开发模型与测试模型

&#x1f4d6; 前言&#xff1a;在软件开发过程中&#xff0c;理解和应用合适的开发模型与测试模型至关重要。本文将详细介绍几种常见的开发模型&#xff0c;如瀑布模型、螺旋模型、增量模型和敏捷过程&#xff0c;以及测试模型如V模型和W模型。 目录 &#x1f552; 1. 开发模型…

Nginx: 使用KeepAlived配置实现虚IP在多服务器节点漂移及Nginx高可用原理

使用KeepAlived配置实现虚IP在多服务器节点漂移 1 &#xff09;环境准备 2台 linux , 一主一备 节点1&#xff1a;192.168.184.30 CentOS 7 Master节点2&#xff1a;192.168.184.40 CentOS 7 BackupVIP 192.168.184.50 安装 KeepAlived, $ yum install keepalived 注意&#x…

时空图卷积网络:用于交通流量预测的深度学习框架-1

摘要 准确的交通预测对于城市交通控制和引导至关重要。由于交通流的高度非线性和复杂性&#xff0c;传统方法无法满足中长期预测任务的需求&#xff0c;且往往忽略了空间和时间的依赖关系。本文提出一种新的深度学习框架——时空图卷积网络(STGCN)来解决交通领域的时间序列预测…

云同步的使用

云同步技术是一种在多个设备或系统之间保持数据一致性的技术&#xff0c;它通常依赖于云存储服务来实现。在Java中&#xff0c;实现云同步功能通常需要与云服务提供商的API进行交互&#xff0c;如Amazon S3、Google Cloud Storage、Microsoft Azure Blob Storage等。 以下是一个…

golang gin template模板渲染

1、根据值控制html元素显示隐藏 main.go package main import ("html/template""net/http""github.com/gin-gonic/gin" ) func main() {r : gin.Default()r.SetFuncMap(template.FuncMap{"greaterThan": func(a, b int) bool {retur…

PyCharm 自定义字体大小

常用编程软件自定义字体大全首页 文章目录 前言具体操作1. 打开设置对话框2. 设置编辑器字体3. 选择外观字体 前言 PyCharm 自定义字体大小&#xff0c;统一设置为 JetBrains Mono 具体操作 【File】>【Settings...】>【Editor】>【Font】 统一设置为字体样式 JetB…

人工智能训练师工作内容及职业发展路径

人工智能训练师&#xff08;AI Trainer&#xff09;是一种专业职位&#xff0c;主要负责训练和优化人工智能系统&#xff0c;尤其是机器学习模型。他们的工作涉及到以下几个方面&#xff1a; 1、数据准备&#xff1a;训练师需要收集、清洗和预处理数据&#xff0c;以确保数据的…

C++ | Leetcode C++题解之第355题设计推特

题目&#xff1a; 题解&#xff1a; class Twitter {struct Node {// 哈希表存储关注人的 Idunordered_set<int> followee;// 用链表存储 tweetIdlist<int> tweet;};// getNewsFeed 检索的推文的上限以及 tweetId 的时间戳int recentMax, time;// tweetId 对应发送…

简易STL实现 | Deque的实现

一种 在内存中存储元素的数据结构&#xff0c;它支持 在两端添加和删除元素&#xff08;使用循环数组实现&#xff09; 1、deque的特性&#xff08;分段deque实现&#xff09; 1、双端操作&#xff1a; deque支持在前端和后端执行快速的插入和删除操作 2、随机访问&#xff…

Servlet 简介+ Cookie和session+过滤器Filter和监听器Listener

目录 1.Servlet 介绍 1.1 什么是Servlet 1.2 Servlet的使用方法 1.3 Servlet接口的继承结构 2.Servlet的生命周期 2.1 servlet生命周期中重要的方法 3.获得前端提交数据 4.中文乱码的解决方案 5.重定向和转发 5.1 重定向 5.2 转发 6. Request对象 7. Response对象…

Linux上启动redis

1.默认启动方式:在系统的任意位置执行 redis-server即可启动 ps:这是前端界面启动&#xff0c;无法直接连接redis&#xff0c;想要连接的话只能另外启动一个窗口&#xff0c;因此下面我们介绍后台启动redis 2.指定配置启动&#xff1a; redis的配置文件位置&#xff1a…

华为手机数据丢失如何恢复?

在智能手机普及的今天&#xff0c;华为手机凭借其卓越的性能和用户体验赢得了众多用户的青睐。然而&#xff0c;在使用过程中&#xff0c;我们难免会遇到数据丢失或误删除的情况。面对这一困境&#xff0c;许多用户可能会感到束手无策。别担心&#xff0c;本文将为你提供一份全…

FastGPT:利用大模型重新定义传统知识库

引言 传统知识库的痛点 传统知识库广泛应用于企业文档管理、客户支持等场景&#xff0c;但随着信息量和复杂度的增加&#xff0c;存在以下显著问题&#xff1a; 数据难整合&#xff1a; 结构化与非结构化数据分散&#xff0c;更新维护成本高。检索不精准&#xff1a; 依赖关…

【前端开发必备小技巧】前端代码规范Vue篇

文章目录 &#x1f7e2; 前端代码规范&#x1f7e2; 一、前端代码规范Vue篇&#x1f449;1、Vue编码基础&#x1f449;1.1、组件规范&#x1f449;1.2、模板中使用简单的表达式&#x1f449;1.3、指令都使用缩写形式&#x1f449;1.4、 标签顺序保持一致&#x1f449;1.5、必须…

【Kotlin设计模式】Kotlin实现适配器模式

前言 适配器模式(Adapter Pattern)的核心将某个类的接口转换成客户端期望的另一个接口表示&#xff0c;使得客户端能够通过自己期望的接口与不兼容的类进行交互。适配器模式有三种实现方式&#xff0c;分别是类适配器模式、对象适配器模式、 接口适配器模式。 我们假设有个视频…

3D Tiles的4x4的仿射变换矩阵

前言 项目需要&#xff0c;使用Cesium技术&#xff0c;把STL格式模型加载进去。 一、格式转换 第一步&#xff0c;先将STL文件转换为glTF格式 第二步&#xff0c;将glTF文件转换为3D Tiles格式&#xff0c;使用Cesium ion 二、矩阵整体结构 这个矩阵是一个4x4的仿射变换矩阵&…

LeetCode题练习与总结:单词搜索Ⅱ--212

一、题目描述 给定一个 m x n 二维字符网格 board 和一个单词&#xff08;字符串&#xff09;列表 words&#xff0c; 返回所有二维网格上的单词 。 单词必须按照字母顺序&#xff0c;通过 相邻的单元格 内的字母构成&#xff0c;其中“相邻”单元格是那些水平相邻或垂直相邻…