Spring-MVC使用JSR303及拦截器,增强网络隐私安全

news2025/1/15 22:57:14

目录

一、JSR303

( 1 )  是什么

( 2 )  作用

( 3 )  常用注解

( 4 )  入门使用

二、拦截器

2.1  是什么

2.2  拦截器与过滤器的区别

2.3  应用场景

2.4 基础使用

2.5 用户登录权限控制

给我们带来的收获


一、JSR303

( 1 )  是什么

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开发中重要的一部分,帮助开发人员构建更健壮和可靠的应用程序。

( 2 )  作用

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可以提高应用程序的质量和开发效率。

( 3 )  常用注解

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

用于Boolean对象是否为false

@DecimalMin用于验证数字的最小值,可以指定包含最小值的边界。
@DecimalMax用于验证数字的最大值,可以指定包含最大值的边界。

 这些注解可以与属性的getter方法或字段上使用,用于定义验证规则。开发人员可以根据具体的业务需求选择合适的注解来进行数据验证。此外,JSR 303还支持自定义注解和验证器,开发人员可以根据需要定义自己的验证规则。

@Validated与@Valid区别

@Validated:

  • Spring提供的

  • 支持分组校验

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

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

@Valid:

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

  • 不支持分组校验

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

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

( 4 )  入门使用

以下的实例代码是基于本人博客中的代码进行扩展 : Spring-MVC的文件上传下载

导入依赖

<!-- 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>

以上代码在我博客中已经导入完成配置 :  Spring-MVC的文件上传下载

配置校验规则

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

例如 : 

    @NotNull(message = "房间编号不能为空")
    //@Size(max = 100,min = 23,message = "编号大小必须在23至100之间")
    private Long hid;

    @NotBlank(message = "房间名不能为空")
    private String hname;

    @NotBlank(message = "房间的类型名称不能为空")
    private String htype;

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

(增加以下方法代码) 例如 : 

   //需要校验,使用@Validated或@Valid注解要验证的对象
    @RequestMapping("/valiadd")
    public String valiadd(@Validated Hotel hotel, BindingResult result, HttpServletRequest request){
        //        如果服务端验证不通过,有错误
        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());
            }
            request.setAttribute("bugMap",map);
        }else {
            hotelbiz.insertSelective(hotel);
            return "redirect:list";
        }
        return "hot/edit";
    }

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

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
    <title>酒店管理编辑界面</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/hot/${empty h ? 'valiadd' : 'edit'}" method="post">
    房间编号:<input type="text" name="hid" value="${h.hid }"><span style="color: cornflowerblue;margin-left: 20px;">${bugMap.hid}</span><br>
    房间名称:<input type="text" name="hname" value="${h.hname }"><span style="color: cornflowerblue;margin-left: 20px;">${bugMap.hname}</span><br>
    房间类型:<input type="text" name="htype" value="${h.htype }"><span style="color: cornflowerblue;margin-left: 20px;">${bugMap.htype}</span><br>
    <input type="submit">
</form>
</body>
</html>

最后开启服务器,到浏览器中请求访问该地址进行测试 : 酒店后台管理系统http://localhost:8081/ssm/hot/list酒店后台管理系统

工作台输出结果 :

演示效果 : 

二、拦截器

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中的配置决定,按照配置的顺序依次对请求进行处理。

过滤器的主要作用包括:

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

拦截器的主要作用包括:

  1. 日志记录:拦截器可以记录请求的相关信息,如请求的URL、请求参数、请求的处理时间等,用于系统的日志记录和分析。

  2. 权限验证:拦截器可以对请求进行权限验证,判断用户是否具有访问特定资源的权限,如用户登录验证、角色权限验证等。

  3. 参数校验:拦截器可以对请求的参数进行校验,确保参数的合法性和有效性,如参数的格式、范围、长度等。

  4. 请求预处理:拦截器可以对请求进行预处理,如字符编码转换、请求参数解析、请求数据的封装等。

  5. 请求后处理:拦截器可以对请求的响应进行后处理,如设置响应头、字符编码转换、响应数据的封装等。

  6. 异常处理:拦截器可以捕获请求处理过程中可能出现的异常,并进行相应的处理,如异常的日志记录、错误页面的跳转等。

  7. 性能监控:拦截器可以对请求的处理时间进行监控,用于系统的性能分析和优化。

2.3  应用场景

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

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

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

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

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

2.4 基础使用

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

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

package com.CloudJun.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.zking.interceptor.OneInterceptor"></bean>
</mvc:interceptors>

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

如以下请求地址 :  酒店后台管理系统http://localhost:8081/ssm/hot/list酒店后台管理系统 (根据自己配置的请求地址进行访问)

演示测试结果为: 

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

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

package com.CloudJun.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:interceptors>
    <!--    拦截所以有用请求地址   -->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.CloudJun.Interceptor.OneInterceptor"/>
        </mvc:interceptor>
        <!--    只拦截中间有用名为clz的请求地址   -->
        <mvc:interceptor>
            <mvc:mapping path="/hot/**"/>
            <bean class="com.CloudJun.Interceptor.TwoInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

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

<!--配置自定义拦截器-->

<mvc:interceptors>

<bean class="com.CloudJun.Interceptor.OneInterceptor"></bean>

</mvc:interceptors>

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

如以下请求地址 :  酒店后台管理系统 (根据自己配置的请求地址进行访问)

2.5 用户登录权限控制

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

package com.CloudJun.Interceptor;

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

}

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

package com.CloudJun.web;

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

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

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

}

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

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>用户登入</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/login" method="post" enctype="multipart/form-data">
    <label>用户名称:</label><br/>
    <input type="text" name="hname"/><br/>
    <input type="submit" value="登入"/>
</form>
</body>
</html>

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

<!--&lt;!&ndash;    用户权限的请求拦截&ndash;&gt;-->
    <mvc:interceptors>
        <bean class="com.CloudJun.Interceptor.LoginInterceptor"></bean>
    </mvc:interceptors>

注意:

这里需要将我们上次配置的拦截器及拦截器链配置,进行注释保证效果,(当然也可不注释)

<!--配置自定义拦截器-->
<mvc:interceptors>
    <bean class="com.CloudJun.Interceptor.OneInterceptor"></bean>
</mvc:interceptors>

<!--2) 配置自定义多拦截器(拦截器链)-->
<mvc:interceptors>
<!--    拦截所以有用请求地址   -->
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="com.CloudJun.Interceptor.OneInterceptor"/>
    </mvc:interceptor>
    <!--    只拦截中间有用名为clz的请求地址   -->
    <mvc:interceptor>
        <mvc:mapping path="/hot/**"/>
        <bean class="com.CloudJun.Interceptor.TwoInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

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

如以下请求地址 :  http://localhost:8081/ssm/login  (根据自己配置的请求地址进行访问)

效果图 : 

给我们带来的收获

学习完Spring MVC的JSR 303和拦截器可以给我们带来以下几方面的收获:

  • 1. 参数校验的便利性:JSR 303是Java Bean验证的标准规范,它提供了一种简单而强大的方式来对请求参数进行校验。通过学习JSR 303,我们可以使用注解方式在实体类中定义参数的校验规则,从而实现对请求参数的自动校验。这样可以减少手动编写校验逻辑的工作量,提高开发效率,同时也提高了代码的可读性和可维护性。
  • 2. 统一的请求处理流程:拦截器可以用于对请求进行统一的处理,如权限验证、日志记录、异常处理等。通过学习拦截器,我们可以实现对请求的统一拦截和处理,从而减少重复代码的编写,提高代码的复用性和可维护性。同时,拦截器还可以对请求进行预处理和后处理,从而实现一些通用的操作,如字符编码转换、请求数据的封装等。
  • 3. 系统的安全性和稳定性:通过JSR 303和拦截器的应用,我们可以实现对请求参数的校验和权限验证,从而提高系统的安全性。同时,拦截器还可以对请求进行异常处理,捕获可能出现的异常并进行相应的处理,从而提高系统的容错性和稳定性。
  • 4. 性能监控和优化:拦截器可以对请求的处理时间进行监控,用于系统的性能分析和优化。通过学习拦截器,我们可以实现对请求处理时间的记录和分析,从而找出系统中的性能瓶颈,并进行相应的优化,提高系统的性能和响应速度。

总之,学习完Spring MVC的JSR 303和拦截器可以帮助我们提高开发效率,减少重复代码的编写,提高代码的复用性和可维护性。同时,它们还可以提高系统的安全性、稳定性和性能优化,为我们的开发工作带来更多的便利和收益。

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

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

相关文章

旅游复苏弹高OTA业绩,未来走势却有“U型曲线”与“抛物线”之变

文 | 螳螂观察 作者 | 易不二 经历了3年蛰伏&#xff0c;旅游业确实熬出头了&#xff0c;OTA也迎来了强势反弹。 自年初起就逐步恢复的旅游行业&#xff0c;经历了暑期小高潮后&#xff0c;正在逐步以强劲的复苏能力&#xff0c;为OTA们的期中财报增彩。 今年二季度&#x…

83 # 静态服务中间件 koa-static 的使用以及实现

静态服务中间件&#xff1a;koa-static 中间件可以决定是否向下执行&#xff0c;如果自己可以处理&#xff0c;那么直接处理完毕结束&#xff0c;如果自己处理不了&#xff0c;next 方法会继续向下执行 新建 public 文件夹&#xff0c;里面添加 index.html、style.css 文件 …

机器学习_个人笔记_周志华(更新中......)

第1章 绪论 1.1 引言 形成优秀的心理表征&#xff0c;自然能成为领域内的专家。 系统1 & 系统2。 机器学习&#xff1a;致力于研究如何通过计算的手段&#xff0c;利用经验来改善系统自身的性能。主要研究计算机从数据中产生model的算法&#xff0c;即“learning algori…

myCobot Pro600六轴机械臂与3D深度视觉:物体精确识别抓取堆叠

Introduction 随着时代的进步&#xff0c;各种精密的机械臂&#xff0c;人形机器人不断的问世。我们即将迎来到处都是机器人的高科技时代。为了跟上时代的脚步&#xff0c;我最近入手了一台myCobot pro 600机械臂&#xff0c;我主要是想要用它来学习机械臂相关得控制以及机器视…

【跟小嘉学 Apache Flink】二、Flink 快速上手

系列文章目录 【跟小嘉学 Apache Flink】一、Apache Flink 介绍 【跟小嘉学 Apache Flink】二、Flink 快速上手 文章目录 系列文章目录[TOC](文章目录) 一、创建工程1.1、创建 Maven 工程1.2、log4j 配置 二、批处理单词统计&#xff08;DataSet API&#xff09;2.1、创建 Bat…

今日话题:解决Linux中可以识别但无法连接Airpods问题(亲测且实用)

今日话题&#xff1a;解决Linux中可以识别但无法连接Airpods问题 起因经过结果方式一方式二 起因经过 在根据“Linux启动黑屏卡住Logo登录界面无法进入系统的终极解决方式”博客解决掉gdm3以及lightdm图形界面之间冲突的问题后&#xff0c;准备设置打开蓝牙连接Airpods&#x…

Java | 多线程

不爱生姜不吃醋⭐️ 如果本文有什么错误的话欢迎在评论区中指正 与其明天开始&#xff0c;不如现在行动&#xff01; 文章目录 &#x1f334;前言&#x1f334;一、什么是多线程&#xff1f;1.进程2.线程3.多线程作用 &#x1f334;二、多线程中的两个概念1. 并发2. 并行3.举例…

python-面向运行时性能优化-threading

python-面向运行时性能优化-threading 一:线程基础1> 线程状态2> 线程同步1. 锁的状态3> 线程通信-条件变量4> 线程阻塞-之间转换1. 阻塞分类二:threading类1> threading介绍2> Thread类1. Thread的生命周期2. 实例化Thread类3. 继承Thread类4. Thread构造…

9.11作业

实现一个对数组求和的函数&#xff0c;数组通过实参传递给函数 sum0 arr(11 22 33 44 55) Sum() {for i in ${arr[*]}do$((sumi))donereturn $sum } Sum ${arr[*]} var$? echo $var写一个函数&#xff0c;输出当前用户的uid和gid&#xff0c;并使用变量接收结果 Sum() {aid -…

C高级作业 【使用shell脚本】 实现一个对数组求和的函数,数组通过实参传递给函数+写一个函数输出当前用户的uid和gid,并使用变量接收结果

作业 1、实现一个对数组求和的函数&#xff0c;数组通过实参传递给函数 #!/bin/bash # 定义求和函数 function sum() {local arr("$") # 将传入的参数保存到一个数组中local sum0 # 初始化求和为0# 遍历数组元素进行求和for num in "${arr[]}";dosum$…

零代码编程:用ChatGPT批量合并ts文件

文件夹中有很多个ts后缀的视频文件&#xff0c;要合并成一个视频文件&#xff0c;在ChatGPT中可以这样输入提示词&#xff1a; 你是一个Python编程专家&#xff0c;要完成一个批量合并ts文件的任务&#xff0c;具体步骤如下&#xff1a; 打开文件夹&#xff1a;C:\Users\dell\…

亚马逊测评下单怎么操作?有没有自动下单软件?

想要进行亚马逊的测评下单&#xff0c;可以按照以下步骤进行操作&#xff1a; 首先&#xff0c;在亚马逊官方网站上搜索你感兴趣的产品&#xff0c;选择你喜欢的产品并查看其详细信息、价格以及其他用户的评价&#xff0c;确认你的购买意向后&#xff0c;点击“加入购物车”将…

C高级 shell指令分支和循环

实现一个对数组求和的函数&#xff0c;数组通过实参传递给函数 #!/bin/bash s0 function sum() {local brr($*)for i in ${brr[*]}do((si))doneecho $s } arr(1 2 3 4 5 6 7 8 9 ) sum ${arr[*]}写一个函数&#xff0c;输出当前用户的uid和gid&#xff0c;并使用变量接收结果 #…

Grafana配置邮件告警

1、创建一个监控图 2、grafana邮件配置 vim /etc/grafana/grafana.ini [smtp] enabled true host smtp.163.com:465 user qinziteng05163.com password xxxxx # 授权码 from_address qinziteng05163.com from_name Grafanasystemctl restart grafana-serv…

DAY03_瑞吉外卖——公共字段自动填充新增分类分类信息分页查询删除分类修改分类

目录 1. 公共字段自动填充1.1 问题分析1.2 基本功能实现1.2.1 思路分析1.2.2 代码实现1.2.3 功能测试 1.3 功能完善1.3.1 思路分析1.3.2 ThreadLocal1.3.3 操作步骤1.3.4 代码实现1.3.5 功能测试 2. 新增分类2.1 需求分析2.2 数据模型2.3 前端页面分析2.4 代码实现2.5 功能测试…

【算法】二分查找算法——leetcode二分查找、搜索插入位置

文章目录 二分查找704. 二分查找35. 搜索插入位置 二分查找 二分查找算法是一种在有序数组中查找特定元素的搜索算法。算法的工作原理是&#xff0c;通过比较数组中间元素和目标值&#xff0c;如果目标值等于中间元素&#xff0c;那么查找结束。如果目标值小于或大于中间元素&a…

单元测试界的高富帅,Pytest框架 (三) 用例标记和测试执行篇

pytest用例标记和测试执行篇 上一篇文章入门篇咱们介绍了pytest的前后置方法和fixture机制&#xff0c;这个章节主要给大家介绍pytest中的标记机制和用例执行的方法。pytest可以通过标记将数据传入于测试函数中&#xff0c;也可以通过标记中对执行的用例做筛选&#xff0c;接下…

NTC 温度采样 二分查表及公式法

NTC 温度采样&#xff1a; 本文记录对NTC 温度采样&#xff0c;分别采用二分查表法及公式法进行描述 资源下载链接&#xff1a;Excel 生成数组表 https://download.csdn.net/download/qq_41359157/88326839?spm1001.2014.3001.5503 NTC参数&#xff1a; NTC采样电路&#xf…

2023 年 Vue 最流行的动画库

数字世界以短暂的注意力和激烈的竞争为主导&#xff0c;因此必须立即将受众的注意力吸引到您的网站上。使用 Vue 动画库&#xff0c;您可以毫不费力地实现这一目标。据报道&#xff0c;VueJs 是 JavaScript 类别中第 7 大最受欢迎的&#xff0c;来自世界各地的开发人员使用它来…

arthas基本应用

下载 arthas curl https://arthas.aliyun.com/arthas-boot.jar启动 arthas&#xff08;启动之前确保有一个 java进程服务&#xff09; java -jar arthas-boot.jar输入3&#xff0c;再输入回车/enter。Arthas 会 attach 到目标进程上&#xff0c;并输出志&#xff1a; 输入das…