Mybatis(2)

sql注入攻擊

SQL注入攻擊是一種常見的網絡安全威脅,攻擊者通過在輸入字段中插入惡意SQL代碼,繞過應用程序的安全機制,直接操縱數據庫。

SQL注入的原理

SQL注入利用應用程序未對用戶輸入進行充分過濾或轉義的漏洞。當用戶輸入被直接拼接到SQL查詢中時,攻擊者可以構造特殊輸入,改變查詢邏輯,獲取未授權的數據或執行惡意操作。

-- 示例:通過輸入' OR '1'='1繞過登錄驗證
SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1'='1';

SQL注入攻擊是一種常見的網絡安全威脅,攻擊者通過在輸入字段中插入惡意SQL代碼,繞過應用程序的安全機制,直接操縱數據庫。以下是關于SQL注入攻擊的詳細說明:

常見的SQL注入類型

基于錯誤的注入
攻擊者通過故意引發數據庫錯誤,從錯誤信息中獲取數據庫結構或敏感數據。

聯合查詢注入
利用UNION操作符將惡意查詢結果合并到正常查詢結果中,獲取其他表的數據。

-- 示例:獲取其他表數據
SELECT id, name FROM products WHERE id = 1 UNION SELECT username, password FROM users;

盲注
當應用程序不返回錯誤信息時,攻擊者通過布爾條件或時間延遲判斷查詢結果。

-- 布爾盲注示例
SELECT * FROM users WHERE username = 'admin' AND SUBSTRING(password, 1, 1) = 'a';

防御SQL注入的方法

參數化查詢(預編譯語句)
使用參數化查詢確保用戶輸入始終被視為數據而非代碼。

# Python示例(使用SQLite)
import sqlite3
conn = sqlite3.connect('database.db')
cursor = conn.cursor()
cursor.execute("SELECT * FROM users WHERE username = ? AND password = ?", (username, password))

輸入驗證與過濾
對用戶輸入進行嚴格驗證,僅允許符合預期的字符或格式。

最小權限原則
數據庫賬戶應僅具有必要的最小權限,避免使用高權限賬戶連接數據庫。

使用ORM框架
ORM(如Django ORM、SQLAlchemy)自動處理參數化查詢,減少手動拼接SQL的需求。

# Django ORM示例
from django.db import models
User.objects.filter(username=username, password=password)

靜態SQL與動態SQL的區別

靜態SQL和動態SQL是數據庫編程中兩種不同的SQL語句處理方式,它們在編寫方式、執行效率和適用場景上有顯著差異。

靜態SQL

靜態SQL是指在程序編譯時就已確定的SQL語句,通常直接嵌入在源代碼中。這些語句的結構和參數在編譯時已知,數據庫管理系統(DBMS)可以預先優化。

特點

  • 語句在編譯時固定,無法在運行時改變。
  • 性能較高,因為DBMS可以預編譯和優化。
  • 通常用于參數化查詢,參數通過占位符(如?@param)傳遞。

示例代碼(Java中使用JDBC)

String sql = "SELECT * FROM employees WHERE department_id = ?";
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setInt(1, 10); // 設置參數
ResultSet rs = stmt.executeQuery();

動態SQL

動態SQL是指在程序運行時動態構建的SQL語句,通常根據用戶輸入或其他運行時條件生成。語句的結構或內容可能在運行時變化。

特點

  • 語句在運行時動態生成,靈活性高。
  • 性能較低,因為DBMS無法預編譯。
  • 容易引發SQL注入風險,需謹慎處理輸入。

示例代碼(Java中使用JDBC)

String departmentId = getUserInput(); // 用戶輸入
String sql = "SELECT * FROM employees WHERE department_id = " + departmentId;
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql);

安全性與性能對比

靜態SQL

  • 安全性高:參數化查詢避免SQL注入。
  • 性能優:預編譯減少運行時開銷。

動態SQL

  • 安全性低:直接拼接輸入可能導致注入。
  • 性能差:每次執行需重新解析和優化。

例子

數據庫設計:

實體類代碼:

package com.qcby.entity;public class student {private Integer id;private  String name;private  String sex;private  String phone;private  String password;private  Integer age;private Integer pageSize;private  Integer pageStart;public student() {}public student(String name, String sex, String phone, Integer age) {this.name = name;this.sex = sex;this.phone = phone;this.age = age;}public Integer getPageSize() {return pageSize;}public void setPageSize(Integer pageSize) {this.pageSize = pageSize;}public Integer getPageStart() {return pageStart;}public void setPageStart(Integer pageStart) {this.pageStart = pageStart;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public String getPhone() {return phone;}public void setPhone(String phone) {this.phone = phone;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "student{" +"id=" + id +", name='" + name + '\'' +", sex='" + sex + '\'' +", phone='" + phone + '\'' +", password='" + password + '\'' +", age=" + age +'}';}
}

dao層代碼

package com.qcby.dao;import com.qcby.entity.student;
import org.apache.ibatis.annotations.Param;import java.util.List;public interface  StudentDao {public  abstract List<student> findAll();student findById(Integer id);Integer delete(Integer id);List<student> findByName(String name);List<student> findBystudent(student student);Integer insert(student student);Integer insertGetId(student student);List<student> findAllStudent(Integer pageSize,Integer pageStart);List<student> findAllStudentByAge (student student);List<student> findUserByStudentName(String name);List<student> findUser(student student);int update(student student);List<student> selectUserByChoose(student student);List<student> selectUserByUsernameAndSex(student student);int trimUpdate(student student);int deleteMoreByArray(@Param("ids") Integer[] ids);int insertMoreByList(@Param("students") List<student> students);
}

mapper.xml代碼

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qcby.dao.StudentDao"><select id="findAll" resultType="com.qcby.entity.student">SELECT * FROM student</select><select id="findById" resultType="com.qcby.entity.student" parameterType="java.lang.Integer">SELECT * from student WHERE id=#{id}</select><delete id="delete" parameterType="java.lang.Integer">DELETE from student WHERE id=#{id}</delete><select id="findByName" resultType="com.qcby.entity.student" parameterType="java.lang.String">SELECT  * from student where name=#{name}</select><select id="findBystudent" resultType="com.qcby.entity.student" parameterType="com.qcby.entity.student">SELECT  * from student where name=#{name} and password=#{password}</select><insert id="insert" parameterType="com.qcby.entity.student">INSERT  INTO student(name,sex,phone,password,age) VALUES (#{name},#{sex},#{phone},#{password},#{age})</insert><insert id="insertGetId" parameterType="com.qcby.entity.student"><selectKey keyProperty="id" resultType="int" order="AFTER">select LAST_INSERT_ID();</selectKey>INSERT INTO student(name,sex,phone,password,age) VALUES (#{name},#{sex},#{phone},#{password},#{age})</insert><select id="findAllStudent" parameterType="java.lang.Integer" resultType="com.qcby.entity.student">SELECT * from student limit #{param1} offset #{param2}</select><select id="findAllStudentByAge" resultType="com.qcby.entity.student" parameterType="com.qcby.entity.student">select * from student WHERE name=#{name} limit #{pageSize} offset #{pageStart}</select><select id="findUserByStudentName" parameterType="java.lang.String" resultType="com.qcby.entity.student">select * from student where name like #{value}</select><!-- where if --><select id="findUser" resultType="com.qcby.entity.student" parameterType="com.qcby.entity.student">select * from student<where><if test="name!=null and name!=''">AND name=#{name}</if><if test="sex!=null and sex!=''">AND sex=#{sex}</if><if test="phone!=null and phone!=''">AND phone=#{phone}</if><if test="password!=null and password!=''">AND password=#{password}</if><if test="age!=null and age!=''">AND age=#{age}</if></where></select><update id="update" parameterType="com.qcby.entity.student">UPDATE student<set><if test="name!=null and name!=''">name=#{name},</if><if test="sex!=null and sex!=''">sex=#{sex},</if><if test="phone!=null and phone!=''">phone=#{phone},</if><if test="password!=null and password!=''">password=#{password},</if><if test="age!=null and age!=''">age=#{age}</if></set>WHERE id = #{id}</update>
<!--if elseif else--><select id="selectUserByChoose" resultType="com.qcby.entity.student"            parameterType="com.qcby.entity.student">select * from student<where><choose><when test="name!=null and name!=''">AND name=#{name}</when><when test="sex!=null and sex!=''">AND sex=#{sex}</when><otherwise>and id=#{id}</otherwise></choose></where></select><select id="selectUserByUsernameAndSex" resultType="com.qcby.entity.student" parameterType="com.qcby.entity.student">SELECT * from student<trim prefix="where" prefixOverrides="and | or"><if test="name!=null and name!=''">AND name=#{name}</if><if test="sex!=null and sex!=''">AND sex=#{sex}</if><if test="phone!=null and phone!=''">AND phone=#{phone}</if><if test="password!=null and password!=''">AND password=#{password}</if><if test="age!=null and age!=''">AND age=#{age}</if></trim></select>
<update id="trimUpdate" parameterType="com.qcby.entity.student">update student<trim prefix="set" suffixOverrides=","><if test="name!=null and name!=''">name=#{name},</if><if test="sex!=null and sex!=''">sex=#{sex},</if><if test="phone!=null and phone!=''">phone=#{phone},</if><if test="password!=null and password!=''">password=#{password},</if><if test="age!=null and age!=''">age=#{age},</if></trim>where id = #{id}
</update><!--delete from user where id in (1,2,3,4,5); --><delete id="deleteMoreByArray">DELETE FROM student WHERE id IN<foreach collection="ids" item="id" separator="," open="(" close=")">#{id}</foreach></delete><!-- collection:當前要循環的數組或者集合   --><!--  item: 我們指定要循環的數組的每一個元素  --><!-- separator:每一個元素應該用什么來做分割   --><!-- open:當前循環是以什么開始   --><!-- close:當前循環是以什么結束   --><!--insert into 表名 (字段) values (值),(值)--><insert id="insertMoreByList" >insert into student(name,age,sex,phone) values<foreach collection="students" item="student" separator=",">(#{student.name},#{student.age},#{student.sex},#{student.phone})</foreach></insert>
</mapper>

1. 基本結構與命名空間

<mapper namespace="com.qcby.dao.StudentDao">

這個標簽確定了命名空間為com.qcby.dao.StudentDao,這意味著在 Java 代碼里可以通過該命名空間來調用這些 SQL 映射語句。

2. 基礎 CRUD 操作

  • 查詢全部學生
    <select id="findAll" resultType="com.qcby.entity.student">SELECT * FROM student
    </select>
    
    此語句會返回student表中的所有記錄。
  • 按 ID 查詢學生
    <select id="findById" resultType="com.qcby.entity.student" parameterType="java.lang.Integer">SELECT * from student WHERE id=#{id}
    </select>
    
    它依據傳入的 ID 參數來查找對應的學生。
  • 插入學生
    <insert id="insert" parameterType="com.qcby.entity.student">INSERT  INTO student(name,sex,phone,password,age) VALUES (#{name},#{sex},#{phone},#{password},#{age})
    </insert>
    
    該語句用于向表中插入新的學生記錄。
  • 更新學生信息
    <update id="update" parameterType="com.qcby.entity.student">UPDATE student<set><if test="name!=null and name!=''">name=#{name},</if><!-- 其他字段的更新條件類似 --></set>WHERE id = #{id}
    </update>
    
    借助<set>標簽和<if>條件判斷,能夠動態地更新學生信息。
  • 刪除學生
    <delete id="delete" parameterType="java.lang.Integer">DELETE from student WHERE id=#{id}
    </delete>
    
    此語句會刪除指定 ID 的學生記錄。

3. 動態 SQL 元素

  • <where>標簽
    <select id="findUser" resultType="com.qcby.entity.student" parameterType="com.qcby.entity.student">select * from student<where><if test="name!=null and name!=''">AND name=#{name}</if><!-- 其他條件判斷 --></where>
    </select>
    
    當有條件滿足時,<where>標簽會自動添加WHERE關鍵字,并且能智能地去除多余的ANDOR
  • <choose><when><otherwise>標簽
    <select id="selectUserByChoose" resultType="com.qcby.entity.student" parameterType="com.qcby.entity.student">select * from student<where><choose><when test="name!=null and name!=''">AND name=#{name}</when><otherwise>and id=#{id}</otherwise></choose></where>
    </select>
    
    這組標簽類似于 Java 中的switch-case語句,會按順序進行條件判斷,一旦有條件滿足就會停止后續判斷。
  • <trim>標簽
    <update id="trimUpdate" parameterType="com.qcby.entity.student">update student<trim prefix="set" suffixOverrides=","><!-- 更新字段 --></trim>where id = #{id}
    </update>
    
    <trim>標簽可以自定義前綴和后綴,suffixOverrides屬性能夠移除多余的逗號。

4. 批量操作

  • 批量刪除
    <delete id="deleteMoreByArray">DELETE FROM student WHERE id IN<foreach collection="ids" item="id" separator="," open="(" close=")">#{id}</foreach>
    </delete>
    
    <foreach>標簽會對集合進行遍歷,可用于生成IN條件。
  • 批量插入
    <insert id="insertMoreByList" >insert into student(name,age,sex,phone) values<foreach collection="students" item="student" separator=",">(#{student.name},#{student.age},#{student.sex},#{student.phone})</foreach>
    </insert>
    
    利用<foreach>標簽能夠批量插入多條學生記錄。

5. 分頁查詢

<select id="findAllStudent" parameterType="java.lang.Integer" resultType="com.qcby.entity.student">SELECT * from student limit #{param1} offset #{param2}
</select>

此查詢通過limitoffset實現分頁功能,param1代表每頁的記錄數,param2代表偏移量。

6. 自動獲取主鍵

<insert id="insertGetId" parameterType="com.qcby.entity.student"><selectKey keyProperty="id" resultType="int" order="AFTER">select LAST_INSERT_ID();</selectKey>INSERT INTO student(name,sex,phone,password,age) VALUES (#{name},#{sex},#{phone},#{password},#{age})
</insert>

<selectKey>標簽的作用是在插入數據后獲取自動生成的主鍵,并將其賦值給實體類的id屬性。

Test代碼

import com.qcby.dao.StudentDao;
import com.qcby.dao.UserDao;
import com.qcby.entity.User;
import com.qcby.entity.student;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
public class StudentTest {private InputStream in = null;private SqlSession session = null;private StudentDao mapper = null;@Before  //前置通知, 在方法執行之前執行public void init() throws IOException {//加載主配置文件,目的是為了構建SqlSessionFactory對象in = Resources.getResourceAsStream("SqlMapConfig.xml");//創建SqlSessionFactory對象SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);//通過SqlSessionFactory工廠對象創建SqlSesssion對象session = factory.openSession();//通過Session創建UserDao接口代理對象mapper = session.getMapper(StudentDao.class);}@After  //@After: 后置通知, 在方法執行之后執行 。public void destory() throws IOException {//釋放資源session.close();in.close();}@Testpublic void SELETALL(){List<student>  students = mapper.findAll();for (student student: students) {System.out.println(student.toString());}}@Testpublic  void findById(){student student=mapper.findById(1);System.out.println(student.toString());}@Testpublic void  delete(){mapper.delete(1);List<student>  students = mapper.findAll();for (student student: students) {System.out.println(student.toString());}session.commit();}@Testpublic  void findByName(){List<student> students=mapper.findByName("楊");for(student students1:students){System.out.println(students1.toString());}}@Testpublic void findBystudent(){student student=new student();student.setName("yu");student.setPassword("123456");List<student> students=mapper.findBystudent(student);for (student student1: students) {System.out.println(student1.toString());}}
@Testpublic  void insert(){student student=new student();student.setName("11");student.setPassword("123");student.setAge(11);student.setPhone("12345");student.setSex("男");mapper.insert(student);List<student>  students = mapper.findAll();for (student student1: students) {System.out.println(student1.toString());}session.commit();}@Testpublic  void insertGetId(){student student=new student();student.setName("11");student.setPassword("123");student.setAge(11);student.setPhone("12345");student.setSex("男");mapper.insertGetId(student);List<student>  students = mapper.findAll();for (student student1: students) {System.out.println(student1.toString());}session.commit();}@Testpublic void findAllStudent(){Integer pageSize=5;Integer pageIndex =1;Integer pageStart =pageSize *(pageIndex-1);List<student> students =mapper.findAllStudent(pageSize,pageStart);for(student student:students){System.out.println(student.toString());}}@Testpublic void findAllStudentByAge(){Integer pageSize=5;Integer pageIndex =1;student student=new student();Integer pageStart =pageSize *(pageIndex-1);student.setPageSize(pageSize);student.setName("博");student.setPageStart(pageStart);List<student> students =mapper.findAllStudentByAge(student);for(student student1:students){System.out.println(student1.toString());}}@Testpublic  void findUserByStudentName(){List<student> students=mapper.findUserByStudentName("%楊%");for(student student1:students){System.out.println(student1.toString());}}@Testpublic void findUser(){student student=new student();student.setSex("男");student.setPhone("1234321");student.setAge(11);student.setName("zzz");student.setPassword("123321");List<student> students=mapper.findUser(student);for(student student1:students){System.out.println(student1.toString());}}@Test
public void update(){student student=new student();student.setName("zzz");student.setId(2);student.setPassword("11441276423");student.setAge(143);student.setPhone("14231312");student.setSex("男");Integer num=mapper.update(student);List<student> students=mapper.findUser(student);for(student student1:students){System.out.println(student1.toString());}System.out.println(num);}@Test
public void selectUserByChoose(){student student=new student();student.setId(2);student.setName("bo");List<student>students=mapper.selectUserByChoose(student);for(student student1:students){System.out.println(student1.toString());}
}@Test
public  void  selectUserByUsernameAndSex(){student student=new student();student.setSex("男");student.setName("bo");List<student>students=mapper.selectUserByUsernameAndSex(student);for(student student1:students){System.out.println(student1.toString());}}@Test
public  void trimUpdate(){student student=new student();student.setName("sssssss");student.setId(2);mapper.trimUpdate(student);}@Testpublic void deleteMoreByArray(){Integer[] integer = new Integer[]{11,12,10,11};mapper.deleteMoreByArray(integer);session.commit();}@Testpublic void insertMoreByList(){student user1 = new student("小趙","男","1234",11);student user2 = new student("小張","男","122234",4);student user3 = new student("小李","男","123334",31);List<student> users = Arrays.asList(user1,user2,user3);mapper.insertMoreByList(users);session.commit();}}

單元測試基礎

單元測試是驗證代碼最小單元(如函數、方法)行為的自動化測試。以下以Java的JUnit框架為例說明基本用法:

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;public class CalculatorTest {@Testpublic void testAddition() {Calculator calc = new Calculator();assertEquals(5, calc.add(2, 3));  // 驗證2+3=5}
}

測試注解類型

  • @Test:標記方法為測試用例
  • @BeforeEach:每個測試前執行初始化
  • @AfterEach:每個測試后執行清理
  • @BeforeAll / @AfterAll:全局初始化和清理(靜態方法)

斷言方法示例

import static org.junit.jupiter.api.Assertions.*;assertTrue(result > 0);          // 驗證條件為真
assertNull(someObject);          // 驗證對象為空
assertArrayEquals(expected, actual); // 驗證數組相等

參數化測試

通過@ParameterizedTest實現多組輸入測試:

@ParameterizedTest
@ValueSource(ints = {1, 2, 3})
void testIsPositive(int number) {assertTrue(number > 0);
}

測試覆蓋率

使用工具(如JaCoCo)統計代碼被測試覆蓋的比例,通常建議達到80%以上關鍵路徑覆蓋率。在Maven項目中配置示例:

<plugin><groupId>org.jacoco</groupId><artifactId>jacoco-maven-plugin</artifactId><version>0.8.7</version><executions><execution><goals><goal>prepare-agent</goal></goals></execution></executions>
</plugin>

?Arrays.asList

Arrays.asList 方法

Arrays.asList 是 Java 中 java.util.Arrays 類提供的一個靜態方法,用于將數組或可變參數轉換為一個固定大小的列表(List)。該方法返回的列表是基于原始數組的視圖,因此對列表的修改會影響原始數組,反之亦然。

語法
public static <T> List<T> asList(T... a)

使用示例

以下是一些常見的 Arrays.asList 用法示例:

示例 1:將數組轉換為列表
String[] stringArray = {"apple", "banana", "cherry"};
List<String> stringList = Arrays.asList(stringArray);
System.out.println(stringList); // 輸出: [apple, banana, cherry]
示例 2:直接傳遞可變參數
List<String> list = Arrays.asList("one", "two", "three");
System.out.println(list); // 輸出: [one, two, three]

注意事項

  1. 固定大小列表
    返回的列表是固定大小的,不能添加或刪除元素,否則會拋出 UnsupportedOperationException

    List<String> list = Arrays.asList("a", "b", "c");
    list.add("d"); // 拋出 UnsupportedOperationException
    
  2. 修改會影響原始數組
    由于返回的列表是原始數組的視圖,修改列表中的元素會影響原始數組。

    String[] arr = {"a", "b", "c"};
    List<String> list = Arrays.asList(arr);
    list.set(0, "x"); // 修改列表
    System.out.println(arr[0]); // 輸出: x
    

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/82268.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/82268.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/82268.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Node.js】高級主題

個人主頁&#xff1a;Guiat 歸屬專欄&#xff1a;node.js 文章目錄 1. Node.js 高級主題概覽1.1 高級主題架構圖 2. 事件循環與異步編程深度解析2.1 事件循環機制詳解事件循環階段詳解 2.2 異步編程模式演進高級異步模式實現 3. 內存管理與性能優化3.1 V8 內存管理機制內存監控…

冰箱熱交換的原理以及如何加氟

冰箱如何加氟&#xff1a; 氟利昂被節流裝置降壓后&#xff0c;進入冰箱的蒸發器&#xff0c;此時它處于低溫低壓液態狀態。在冰箱內部&#xff08;例如 0C 或 -10C&#xff09;&#xff1a;它很容易氣化&#xff08;因為其沸點很低&#xff09;在氣化過程中吸收周圍熱量。 1…

WordPress多語言插件安裝與使用教程

WordPress多語言插件GTranslate的使用方法 在wordpress網站后臺搜索多語言插件GTranslate并安裝&#xff0c;安裝完成、用戶插件后開始設置&#xff0c;以下為設置方法&#xff1a; 1、先在后臺左側找到Gtranslate&#xff0c;進入到設置界面 2、選擇要顯示的形式&#xff0c…

DELL EMC PowerStore BBU更換手冊

寫在前面 上周給客戶賣了一個BBU電池&#xff0c;客戶要寫一個更換方案。順利完成了更換&#xff0c;下面就把這個更換方案給大家share出來&#xff0c;以后客戶要寫&#xff0c;您就Ctrlc 和Ctrlv就可以了。 下面的步驟是最理想的方式&#xff0c;中間沒有任何的問題&#xff…

FastMCP:為大語言模型構建強大的上下文和工具服務

FastMCP&#xff1a;為大語言模型構建強大的上下文和工具服務 在人工智能快速發展的今天&#xff0c;大語言模型&#xff08;LLM&#xff09;已經成為許多應用的核心。然而&#xff0c;如何讓這些模型更好地與外部世界交互&#xff0c;獲取實時信息&#xff0c;執行特定任務&a…

CMake基礎:CMakeLists.txt 文件結構和語法

目錄 1.CMakeLists.txt基本結構 2.核心語法規則 3.關鍵命令詳解 4.常用預定義變量 5.變量和緩存 6.變量作用域與傳遞 7.注意事項 1.CMakeLists.txt基本結構 CMakeLists.txt 是 CMake 構建系統的核心配置文件&#xff0c;采用命令式語法組織項目結構和編譯流程。主要用于…

戰略-2.1 -戰略分析(PEST/五力模型/成功關鍵因素)

戰略分析路徑&#xff0c;先宏觀&#xff08;PEST&#xff09;、再產業&#xff08;產品生命周期、五力模型、成功關鍵因素&#xff09;、再競爭對手分析、最后企業內部分析。 本文介紹&#xff1a;PEST、產品生命周期、五力模型、成功關鍵因素、產業內的戰略群組 一、宏觀環境…

深入理解設計模式:工廠模式、單例模式

深入理解設計模式&#xff1a;工廠模式、單例模式 設計模式是軟件開發中解決常見問題的可復用方案。本文將詳細介紹兩種種重要的創建型設計模式&#xff1a;工廠模式、單例模式&#xff0c;并提供Java實現示例。 一、工廠模式 工廠模式是一種創建對象的設計模式&#xff0c;…

Jenkins 2.426.2配置“構建歷史的顯示名稱,加上包名等信息“

Jenkins 2.426.2配置“構建歷史的顯示名稱,加上包名等信息" 需求:想要在構建歷史中展示,本次運行的是哪個版本或哪個包 操作步驟: 1、先安裝插件Build Name and Description Setter 2、Set Build Name 3、構建歷史處查看展示 插件特性說明 安裝依賴:需手動安裝 Build …

為何在VMware中清理CentOS虛擬機后,本地磁盤空間未減少的問題解決

文章目錄 前言原因:虛擬機磁盤&#xff0c;到底是咋回事&#xff1f;為啥空間沒變小&#xff1f; 解決方案 前言 在使用VMware運行CentOS虛擬機時&#xff0c;你是否曾遇到過這樣的情況&#xff1a;明明在虛擬機內刪除了大量文件&#xff0c;rm -rf 后發現并沒什么用&#xff…

Development靶機通關筆記

一、主機發現 arp-scan -l靶機ip為192.168.55.152 二、端口掃描、目錄枚舉、漏洞掃描、指紋識別 2.1端口掃描 nmap --min-rate 10000 -p- 192.168.55.152發現靶機沒有開放80端口&#xff0c;開放的是8080端口 UDP端口掃描 nmap -sU --min-rate 10000 -p- 192.168.55.152靶…

自然語言處理核心技術:詞向量(Word Embedding)解析

自然語言處理核心技術&#xff1a;詞向量&#xff08;Word Embedding&#xff09;全面解析 在自然語言處理&#xff08;NLP&#xff09;領域&#xff0c;如何讓計算機理解人類語言的語義一直是核心挑戰。詞向量&#xff08;Word Vector&#xff09;&#xff0c;又稱詞嵌入&…

【Matlab】雷達圖/蛛網圖

文章目錄 一、簡介二、安裝三、示例四、所有參數說明 一、簡介 雷達圖&#xff08;Radar Chart&#xff09;又稱蛛網圖&#xff08;Spider Chart&#xff09;是一種常見的多維數據可視化手段&#xff0c;能夠直觀地對比多個指標并揭示其整體分布特征。 雷達圖以中心點為原點&…

Vue3實現輪播表(表格滾動)

在這之前,寫過一篇Vue2實現該效果的博文:vue-seamless-scroll(一個簡單的基于vue.js的無縫滾動) 有興趣也可以去看下,這篇是用vue3實現,其實很簡單,目的是方便后面用到直接復制既可以了。 安裝: <

安卓開發用到的設計模式(1)創建型模式

安卓開發用到的設計模式&#xff08;1&#xff09;創建型模式 文章目錄 安卓開發用到的設計模式&#xff08;1&#xff09;創建型模式1. 單例模式&#xff08;Singleton Pattern&#xff09;2. 工廠模式&#xff08;Factory Pattern&#xff09;3. 抽象工廠模式&#xff08;Abs…

后端開發概念

1. 后端開發概念解析 1.1. 什么是服務器&#xff0c;后端服務 1.1.1. 服務器 服務器是一種提供服務的計算機系統&#xff0c;它可以接收、處理和響應來自其他計算機系統&#xff08;客戶端&#xff09;的請求。服務器主要用于存儲、處理和傳輸數據&#xff0c;以便客戶端可以…

Spring AI 源碼解析:Tool Calling鏈路調用流程及示例

Tool工具允許模型與一組API或工具進行交互&#xff0c;增強模型功能&#xff0c;主要用于&#xff1a; 信息檢索&#xff1a;從外部數據源檢索信息&#xff0c;如數據庫、Web服務、文件系統或Web搜索引擎等 采取行動&#xff1a;可用于在軟件系統中執行特定操作&#xff0c;如…

Spyglass:跨時鐘域同步(長延遲信號)

相關閱讀 Spyglasshttps://blog.csdn.net/weixin_45791458/category_12828934.html?spm1001.2014.3001.5482 簡介 長延遲信號方案用于控制或數據信號跨時鐘域同步&#xff0c;該方案將使用quasi_static約束的跨時鐘域信號視為已同步&#xff0c;如圖1所示。 // test.sgdc q…

Linux云計算訓練營筆記day13【CentOS 7 find、vim、vimdiff、ping、wget、curl、RPM、YUM】

Linux云計算訓練營筆記day13[CentOS 7 find、vim、vimdiff、ping、wget、curl、RPM、YUM]] 目錄 Linux云計算訓練營筆記day13[CentOS 7 find、vim、vimdiff、ping、wget、curl、RPM、YUM]]1.find練習2.vim高級使用2.1 命令模式:2.2 插入模式:2.3 末行模式: 3. vimdiff4. ping5.…

網絡流量分析工具ntopng的安裝與基本使用

網絡流量分析工具ntopng的安裝與基本使用 一、ntopng基本介紹1.1 ntopng簡介1.2 主要特點1.3 使用場景 二、本地環境介紹2.1 本地環境規劃2.2 本次實踐介紹 三、安裝ntopng工具3.1 官網地址3.2 配置軟件源3.3 添加軟件源3.4 安裝ntopng 四、ntopng的基本配置4.1 修改配置文件4.…