学习 [Spring MVC] 的JSR 303和拦截器,提高开发效率

news2024/11/16 13:50:27

                                               🎬 艳艳耶✌️:个人主页

                                                🔥 个人专栏 :《推荐】Spring与Mybatis集成整合》

                                                ⛺️    生活的理想,不断更新自己 !

1.JSR303

1.1JSR303是什么

JSR 303是Java规范请求(Java Specification Request)的一部分,它定义了一套标准的Java Bean验证规范,也被称为Bean验证。它提供了一种简单而强大的方式来验证Java对象的属性的值。

在开发应用程序时,数据的验证是非常重要的,以确保数据的完整性一致性。传统的验证方式通常需要大量的手动编码,而且容易出错。JSR 303的目标是提供一种通用的验证框架,以便开发人员可以在应用程序中轻松地执行输入验证。

JSR 303定义了一套验证规范,通过在Java类的属性级别上定义验证规则,并通过注解的方式将这些规则与属性关联起来。开发人员可以使用内置的验证注解,也可以自定义验证注解,以满足特定的验证需求。

内置的验证注解包括@NotNull、@Size、@Min、@Max、@Pattern、@Email等。这些注解可以用于验证属性的值是否满足特定的条件,如非空、长度范围、最小值、最大值、正则表达式匹配等。

开发人员还可以通过编写自定义的验证注解和验证器来定义和执行自定义的验证规则。自定义验证注解可以根据具体的业务需求定义,而验证器则负责实现具体的验证逻辑。

JSR 303的验证框架可以在Java EE和Java SE环境中使用,并且已经被许多Java框架广泛采用。例如,Hibernate Validator是一个基于JSR 303规范的验证框架,它与Hibernate ORM框架集成,提供了强大的数据验证功能。Spring Framework也支持JSR 303规范,可以在Spring应用程序中使用注解进行数据验证。

通过使用JSR 303的验证框架,开发人员可以简化数据验证的过程,减少手动编码的工作量,并提高代码的可读性可维护性。它是Java开发中重要的一部分,帮助开发人员构建更健壮和可靠的应用程序。

1.2JSR303作用

JSR 303的具体作用是提供一种通用的验证框架,用于验证Java对象的属性的值。它在应用程序开发中的作用有以下几个方面:

1. 数据验证:JSR 303允许开发人员在Java类的属性级别上定义验证规则,并通过注解的方式将这些规则与属性关联起来。通过使用内置的验证注解或自定义的验证注解,开发人员可以验证属性的值是否符合特定的条件,如非空、长度范围、最小值、最大值、正则表达式等。这样可以确保输入数据的完整性和一致性,防止无效或不合法的数据进入应用程序。
2. 错误处理:JSR 303提供了一种标准的错误处理机制,当验证失败时,可以生成详细的错误信息。开发人员可以通过捕获验证异常或检查验证结果来处理验证错误。这样可以帮助开发人员快速定位和解决数据验证问题,并向用户提供友好的错误提示。
3. 可读性和可维护性:通过使用JSR 303的验证框架,开发人员可以将验证规则与属性直接关联起来,使代码更加清晰和易于理解。验证规则以注解的形式存在于代码中,使得验证逻辑更加直观和可读。此外,通过使用注解,验证规则与属性的关联性得到了明确的表达,使得代码更易于维护和修改。
4. 框架集成:JSR 303的验证框架已经被许多Java框架广泛采用。例如,Hibernate Validator是一个基于JSR 303规范的验证框架,与Hibernate ORM框架集成,提供了强大的数据验证功能。Spring Framework也支持JSR 303规范,可以在Spring应用程序中使用注解进行数据验证。通过与这些框架的集成,开发人员可以更方便地使用JSR 303的验证功能,提高开发效率。

  • 总之,JSR 303的具体作用是提供一种简单而强大的验证框架,用于验证Java对象的属性的值。它可以帮助开发人员确保输入数据的完整性和一致性,并提供标准的错误处理机制。通过提高代码的可读性和可维护性,以及与其他框架的集成,JSR 303可以提高应用程序的质量和开发效率。

1.3JSR303常用注解

注解说明
@Null用于验证对象为null
@NotNull用于对象不能为null,无法查检长度为0的字符串
@NotBlank只用于String类型上,不能为null且trim()之后的size>0
@NotEmpty用于集合类、String类不能为null,且size>0。但是带有空格的字符串校验不出来
@Size用于对象(Array,Collection,Map,String)长度是否在给定的范围之内
@Length用于String对象的大小必须在指定的范围内
@Pattern用于String对象是否符合正则表达式的规则
@Email用于String对象是否符合邮箱格式
@Min用于Number和String对象是否大等于指定的值
@Max用于Number和String对象是否小等于指定的值
@AssertTrue用于Boolean对象是否为true
@AssertFalse用于Boolean对象是否为false

@Validated与@Valid区别

@Validated:

Spring提供的

支持分组校验

可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上

由于无法加在成员属性(字段)上,所以无法单独完成级联校验,需要配合@Valid

@Valid:

JDK提供的(标准JSR-303规范)

不支持分组校验

可以用在方法、构造函数、方法参数和成员属性(字段)上

可以加在成员属性(字段)上,能够独自完成级联校验

1.4JSR303入门使用

小编上一篇写了SpringMvc文件上传下载一条龙服务教会你 ,就不重复写了。

首先导入依赖

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

配置校验规则

在实体类相对应的属性中增加注解用来指定校验 

 @NotNull(message = "书籍编号不能为空")
    private Integer bid;

    @NotBlank(message = "书籍名不能为空")
    private String bname;

    private String bimage;

    @NotBlank(message = "书籍价格不能为空")
    private Float price;

在需要校验的对象类的控制器中,增加要请求处理方法中,使用@Validated或@Valid注解要验证的对象,并根据BindingResult判断校验是否通过;

   //    给数据添加服务端校验
    @RequestMapping("/valiAdd")
    public String valiAdd(@Validated Book book, BindingResult result, HttpServletRequest req){
//        如果服务端验证不通过,有错误
            if(result.hasErrors()){
//            服务端验证了实体类的多个属性,多个属性都没有验证通过
                List<FieldError> fieldErrors = result.getFieldErrors();
                Map<String,Object> map = new HashMap<>();
                for (FieldError fieldError : fieldErrors) {
//                将多个属性的验证失败信息输送到控制台
                    System.out.println(fieldError.getField() + ":" + fieldError.getDefaultMessage());
                    map.put(fieldError.getField(),fieldError.getDefaultMessage());
                }
                req.setAttribute("errorMap",map);
            }else {
                this.bookBiz.insertSelective(book);
                return "redirect:list";
            }
            return "book/edit";
        }

在编辑页面的使用代码修改为以下代码 : 

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
                                                   <%--/book/add--%><%--/book/edit--%>
<form action="${pageContext.request.contextPath }/book/${empty b ? 'valiAdd' : 'edit'}" method="post">
    bid:<input type="text" name="bid" value="${b.bid }"><span style="color: blue;">${errorMap.bid}</span><br>
    bname:<input type="text" name="bname" value="${b.bname }"><span style="color: blue;">${errorMap.bname}</span><br>
    price:<input type="text" name="price" value="${b.price }"><span style="color: blue;">${errorMap.price}</span><br>
    <input type="submit">
</form>
</body>
</html>

最后 开启服务器,到浏览器中请求访问该地址进行测试.

 

2.拦截器

2.1  是什么

拦截器(Interceptor)是一种在请求处理过程中,对请求进行拦截和处理的机制。它可以在请求到达目标处理器之前、之后或者完全替代目标处理器来执行一些特定的操作。拦截器通常用于实现一些横切关注点(Cross-cutting Concerns),如日志记录、权限验证、性能监控等。

拦截器可以在整个请求处理过程中对请求进行多次拦截,每个拦截器都可以根据自己的需求对请求进行处理,并决定是否继续传递给下一个拦截器或目标处理器。拦截器可以形成一个拦截器链,按照一定的顺序依次对请求进行处理,每个拦截器都可以对请求进行修改或者中断请求处理流程。

在Web开发中,拦截器常用于对请求进行预处理和后处理。当一个请求到达服务器时,拦截器可以在请求到达目标处理器之前对请求进行一些预处理操作,如记录日志、验证权限等;在请求处理完成后,拦截器可以对响应进行后处理操作,如修改响应数据、设置响应头等。

在Java的Web开发中,拦截器通常是通过实现javax.servlet.Filter接口来实现的。Filter是Servlet规范中定义的一种用于在请求和响应之间进行拦截和处理的组件。通过在web.xml配置拦截器的URL模式和顺序,可以将拦截器应用到特定的URL或URL模式上。


拦截器的优点是可以将一些通用的操作抽离出来,避免在每个处理器中重复编写相同的代码。它提供了一种可扩展和可配置的方式来处理请求,使得系统的功能更加模块化和可维护。拦截器还可以实现一些与业务逻辑无关的功能,如性能监控、日志记录等,提高系统的可用性和可靠性。

                                                    拦截器工作原理 

2.2  拦截器与过滤器的区别

什么是过滤器(Filter)

过滤器(Filter)是Java Web开发中的一种组件,它主要用于对Servlet请求进行预处理和后处理。过滤器可以在请求到达目标Servlet之前或者之后执行一些特定的操作,如对请求参数进行解析、字符编码转换、请求日志记录等。通过过滤器,开发人员可以对请求进行统一的处理,提高代码的复用性和可维护性。

过滤器是基于Java的Servlet规范实现的,它是通过实现Filter接口来定义过滤器,并通过在web.xml配置过滤器的URL模式和顺序来应用到特定的请求。在过滤器链中,每个过滤器都可以对请求进行修改或者中断请求处理流程。过滤器的执行顺序由web.xml中的配置决定,按照配置的顺序依次对请求进行处理。

过滤器的主要作用包括:

请求预处理:对请求进行预处理,如解析请求参数、字符编码转换、请求日志记录等。
请求后处理:对请求的响应进行后处理,如设置响应头、字符编码转换、响应日志记录等。
权限验证:对请求进行权限验证,如用户登录验证、访问权限验证等。
缓存控制:对请求进行缓存控制,如设置缓存过期时间、缓存验证等。
异常处理:对请求中可能出现的异常进行处理,如捕获异常、记录异常日志等。

拦截器的主要作用包括:

  • 日志记录:拦截器可以记录请求的相关信息,如请求的URL、请求参数、请求的处理时间等,用于系统的日志记录和分析。
  • 权限验证:拦截器可以对请求进行权限验证,判断用户是否具有访问特定资源的权限,如用户登录验证、角色权限验证等。
  • 参数校验:拦截器可以对请求的参数进行校验,确保参数的合法性和有效性,如参数的格式、范围、长度等。
  • 请求预处理:拦截器可以对请求进行预处理,如字符编码转换、请求参数解析、请求数据的封装等。
  • 请求后处理:拦截器可以对请求的响应进行后处理,如设置响应头、字符编码转换、响应数据的封装等。
  • 异常处理:拦截器可以捕获请求处理过程中可能出现的异常,并进行相应的处理,如异常的日志记录、错误页面的跳转等。
  • 性能监控:拦截器可以对请求的处理时间进行监控,用于系统的性能分析和优化。

2.3  应用场景 

日志记录:拦截器可以用于记录请求的相关信息,如请求的URL、请求参数、请求的处理时间等。通过拦截器记录日志,可以方便后续的系统日志记录和分析,以及对请求的追踪和排查问题。

权限验证:拦截器可以用于对用户进行权限验证,判断用户是否具有访问特定资源的权限。例如,在用户访问某个需要登录的页面之前,拦截器可以检查用户是否已登录,并根据用户的角色判断是否有权限访问该页面。

请求预处理:拦截器可以用于对请求进行预处理,如字符编码转换、请求参数解析、请求数据的封装等。通过拦截器进行预处理,可以减轻目标处理器的负担,提高请求的处理效率和系统的稳定性。

性能监控:拦截器可以用于监控请求的处理时间,用于系统的性能分析和优化。例如,拦截器可以记录请求的处理时间,并根据时间阈值进行性能告警或者对慢请求进行分析和优化。

总之,拦截器可以应用于多个场景,包括权限验证、日志记录、参数校验、请求预处理、请求后处理、异常处理和性能监控等。通过拦截器,开发人员可以对请求进行统一的处理,提高代码的复用性和可维护性,同时实现系统的安全性、稳定性和性能优化。

2.4 基础使用

创建一个名为 Interceptor 的包,存放创建自定义拦截器

创建一个创建自定义拦截器,名为 : OneInterceptor,代码如下

package com.sy.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class OneInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("【OneInterceptor】:preHandle...");

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("【OneInterceptor】:postHandle...");

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("【OneInterceptor】:afterCompletion...");
    }
}

在名为 spring-mvc.xml 的配置文件中,配置自定义拦截器

<!--配置拦截器-->
    <mvc:interceptors>
        <bean class="com.sy.interceptor.OneInterceptor"></bean>
    </mvc:interceptors>

启动项目服务器,打开浏览器访问请求地址,测试拦截器的拦截效果。

测试结果:

拦截器链(同时配置多个拦截器,可以进行区别拦截)

在 Interceptor 的包里,创建一个拦截器 TwoInterceptor。

package com.sy.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TwoInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("【TwoInterceptor】:preHandle...");

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("【TwoInterceptor】:postHandle...");

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("【TwoInterceptor】:afterCompletion...");
    }
}

在名为 spring-mvc.xml 的配置文件中,配置自定义拦截器链

 <!--2) 多拦截器(拦截器链)-->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.sy.interceptor.OneInterceptor"/>
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/book/**"/>
            <bean class="com.sy.interceptor.TwoInterceptor"/>
        </mvc:interceptor>

注意: 这里需要将我们上次配置的拦截器配置,进行注释,注释以下配置

2.5 用户登录权限控制

创建一个名为 : LoginInterceptor 的拦截器

package com.sy.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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) throws Exception {
        System.out.println("【implements】:preHandle...");
        StringBuffer url = request.getRequestURL();
        if (url.indexOf("/login") > 0 || url.indexOf("/logout") > 0){
            //        如果是 登录、退出 中的一种
            return true;
        }
//            代表不是登录,也不是退出
//            除了登录、退出,其他操作都需要判断是否 session 登录成功过
        String bname = (String) request.getSession().getAttribute("bname");
        if (bname == null || "".equals(bname)){
            response.sendRedirect("/page/login");
            return false;
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

创建一个名为 : LoginController 的控制器

package com.sy.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * @author 谌艳
 * @site www.shenyan.com
 * @create 2023-09-11 22:31
 */

@Controller
public class LoginController {
    @RequestMapping("/login")
    public String login(HttpServletRequest req){
        String bname = req.getParameter("bname");
        HttpSession session = req.getSession();
        if ("zs".equals(bname)){
            session.setAttribute("bname",bname);
        }
        return "redirect:/book/list";
    }
    @RequestMapping("/logout")
    public String logout(HttpServletRequest req){
        req.getSession().invalidate();
        return "redirect:/book/list";
    }

}

创建一个 login.jsp 的显示页面,进行测试效果

<%--
  Created by IntelliJ IDEA.
  User: 86177
  Date: 2023/9/11
  Time: 22:29
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>登录</h1>
<form action="${pageContext.request.contextPath }/login" method="post" enctype="multipart/form-data">
    <label>用户名称:</label><br/>
    <input type="text" name="bname"/><br/>
    <input type="submit" value="登入"/>
</form>

</body>
</html>

在名为 spring-mvc.xml 的配置文件中,配置自定义拦截器,配置登入的用户。

<!--配置拦截器-->
    <mvc:interceptors>
        <!--单个配置拦截器-->
        <bean class="com.sy.interceptor.LoginInterceptor"></bean>
    </mvc:interceptors>

启动项目服务器,打开浏览器访问请求地址,测试效果。

测试结果:

                                          今日分享到这就结束了!!!

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

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

相关文章

【AI理论学习】语言模型Performer:一种基于Transformer架构的通用注意力框架

语言模型Performer&#xff1a;一种基于Transformer架构的通用注意力框架 Performer论文解读Regular Attention MechanismFAVOR&#xff1a;通过矩阵相关性实现快速注意力 Attention的时间复杂性绕过softmax瓶颈通过Gaussian kernel求Softmax kernel寻找更稳定的Softmax内核使用…

单链表(Single Link Table)——单文件实现

一、单链表前言 上篇文章我们讲述了顺序表&#xff0c;认真学习我们会发现顺序表优缺点。 缺点1&#xff1a;头部和中部的插入删除效率都不行&#xff0c;时间和空间复杂度都为O(N); 缺点2&#xff1a;空间不够了扩容有一定的消耗(尤其是realloc的异地扩容)&#xff1b; 缺…

Linux网络编程:网络协议及网络传输的基本流程

目录 一. 计算机网络的发展 二. 网络协议的认识 2.1 对于协议分层的理解 2.2 TCP/IP五层协议模型 2.3 OSI七层模型 三. 网络传输的流程 3.1 同一网段中计算机通信的流程 3.2 不同网段中计算机设备的通信 3.3 对于IP地址和MAC地址的理解 3.4 数据的封装和解包 四. 总结…

2.linux的组管理和权限管理

一、组管理 1.Linux组的介绍 在linux中每个用户必须属于一个组&#xff0c;不能独立于组外。在linux中每个文件有所有者&#xff0c;所有组&#xff0c;其他组的概念 ①所有者 ②所在组 ③其他组 ④改变用户所在组 2.文件/目录 所有者 哪个用户创建了文件&#xff0c;就…

使用rpm重新安装包

#查询 rpm -qa | grep cloudstack #卸载 rpm -e cloudstack-agent-4.18.0.0-1.x86_64 #安装 rpm -ivh cloudstack-agent-4.18.0.0-1.x86_64.rpm

17.Xaml DockPanel控件 ---> 停靠面板

1.运行效果 2.运行源码 a.Xaml源码 <Window x:Class="testView.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.mic…

CFD模拟仿真理论求解-基于大数据的物理现象研究:热传导方程的数值求解

基于大数据的物理现象研究&#xff1a;热传导方程的数值求解 CFD模拟仿真理论求解 在科学研究和工程实践中&#xff0c;许多物理现象都可以用微分方程来描述。其中&#xff0c;热传导方程是一个非常重要且基础的例子。热传导方程是一个二阶线性偏微分方程&#xff0c;描述了热…

Docker-namespace

Docker-namespace namespace基础命令dd 命令mkfsdfmountunshare pid 隔离试验mount 隔离 namespace namespace 是 Linux 内核用来隔离内核资源的方式。通过 namespace 可以让一些进程只能看到与自己相关的一部分资源&#xff0c;而另外一些进程也只能看到与它们自己相关的资源…

D3JS简介

D3JS 什么是D3js D3.js是一个流行的JavaScript数据可视化库&#xff0c;它提供了一系列的API和工具&#xff0c;用于创建交互式的数据图表、地图等可视化效果。以下是一些D3.js的特点和用途&#xff1a; 数据驱动&#xff1a;D3.js基于数据驱动的思想&#xff0c;将数据和视觉…

科教兴国 | 拓世集团携手中国航天广电集团,打造《AI+教育平台》

在这个时代&#xff0c;人工智能的奇迹交织成一片璀璨的星河。在这片星河中&#xff0c;各大企业如同星辰&#xff0c;闪烁着探索的光芒&#xff0c;寻找着那些志同道合的伙伴。我们并肩飞翔&#xff0c;穿越信息的海洋&#xff0c;共同描绘出未来的蓝图。每一次合作&#xff0…

麒麟信安主办openEuler嵌入式Meetup:打造湖南大学openEuler技术小组,大咖齐聚共探技术前沿

9月8日&#xff0c;由开放原子基金会指导&#xff0c;openEuler社区、麒麟信安、湖南欧拉生态创新中心以及湖南大学联合主办的openEuler嵌入式Meetup在湖南大学成功举办。这一技术盛会汇聚了业内顶尖专家和开发者&#xff0c;旨在为嵌入式技术领域注入新的活力和创新。 活动现场…

巴州阳光志愿者服务协会党支部开展 第十一季“衣旧情深”爱心 活动

为了让捐赠真正回归公益慈善&#xff0c;奉行衣物回收“取之于民&#xff0c;用之于民”的理念&#xff0c;2023年9月10日&#xff0c;巴州阳光志愿者服务协会党支部书记李晓红组织志愿者们去普惠乡开展第十一季“衣旧情深”爱心活动。 本次活动是以“99公益日”活动为契机&…

Mysql5.7(Docker环境)实现主从复制

文章目录 前言一、MySQL主从数据库同步如何实现&#xff1f;(理论)1.1 为什么要使用数据库主从1.2 数据库主从实现原理是什么&#xff1f; 二、Docker环境配置MySQL5.7主从(实践)2.1 配置安装Master2.2 配置安装Slave 前言 本文章将以MySQL5.7版本来讲诉MySQL主从复制的原理以…

Android Jetpack Compose之状态持久化与恢复

目录 1.概述2.实例解析4. Compose提供的MapSaver和ListSaver4.1 mapServer4.2 ListSaver 1.概述 在之前的文章中&#xff0c;我们提到了remember&#xff0c;我们都知道remember可以缓存创建状态&#xff0c;避免因为重组而丢失。使用remember缓存的状态虽然可以跨越重组&…

软件测试之功能测试

一、测试项目启动与研读需求文档 &#xff08;一&#xff09; 组建测试团队 1.测试团队中的角色 2.测试团队的基本责任 尽早地发现软件程序、系统或产品中所有的问题。 督促和协助开发人员尽快地解决程序中的缺陷。 帮助项目管理人员制定合理的开发和测试计划。 对缺陷进行跟…

芯科蓝牙BG27开发笔记3-修改第一个程序

提问&#xff1a; 如何实现连续发送通知消息&#xff1f; 蓝牙无线射频信号在时间轴不是连续不断地存在&#xff0c;为了实现大数量的传输&#xff0c;需要额外的机制保证设备可以在下一次启动射频后可以接着发送之前没有发完的消息&#xff0c;nordic是可以使用队列&#xf…

springboot jpa手动事务

创建springboot项目 搭建最简单的SpringBoot项目_Steven-Russell的博客-CSDN博客 引入jpa和数据据依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>…

yolov8 模型部署--TensorRT部署-c++服务化部署

写目录 yolov8 模型部署--TensorRT部署1、模型导出为onnx格式2、模型onnx格式转engine 部署 yolov8 模型部署–TensorRT部署 1、模型导出为onnx格式 如果要用TensorRT部署YOLOv8&#xff0c;需要先使用下面的命令将模型导出为onnx格式&#xff1a; yolo export modelyolov8n.p…

二维前缀和

导言 当我们需要求到某个矩阵的子矩阵的和时,就可以使用二维前缀和 这是一个矩阵, 就是左上角区域的所有数之和 ...... 如果要 求中间的子矩阵的和,(x,y)为左上角 ...... ...... ,(i,j)为右下角,那么只需要算 - - ------这一…

QT第五天

void Widget::on_show_clicked() { QString sql "select * from myTable" ; QSqlQuery querry; if(!querry.exec(sql)) { QMessageBox::information(this,"失败","展示失败"); return; } //此时&…