智慧社區構建——2

1.實現Token校驗

## Token校驗URL```json
GET /checkToken
```參數```json
HttpServletRequest request
```返回```json
{"msg": "操作成功","code": 200,"status": "ok"
}{"msg": "操作成功","code": 200,"status": "error"
}

?在LoginController中實現下面得方法

/*** Token校驗* @param request HTTP請求* @return 校驗結果*/@RequestMapping("/checkToken")public Result checkToken(HttpServletRequest request) {//1.從請求頭中獲取tokenString token = request.getHeader("token");System.out.println("從請求頭獲取到的token:" + token);//2.判斷token是否為空或空字符串,如果是則返回錯誤信息if (token == null || token.isEmpty()) {System.out.println("token為空或空字符串,驗證失敗");return Result.ok().put("status", "error").put("msg", "token不能為空");}//3.聲明變量用于標記JWT格式是否有效boolean isJwtValid;//4.聲明變量用于存儲從token中解析出的userIdString userId = null;try {//5.使用JWT工具類解析token,獲取負載信息Claims claims = Jwts.parser().setSigningKey(jwtUtil.getSecret()).parseClaimsJws(token).getBody();//6.從負載中獲取userIduserId = claims.get("userId", String.class);System.out.println("從token中解析出的userId:" + userId);//7.如果解析成功,標記JWT格式有效isJwtValid = true;System.out.println("JWT格式驗證通過");} catch (Exception e) {//8.如果解析失敗,標記JWT格式無效isJwtValid = false;System.out.println("JWT格式驗證失敗,異常信息:" + e.getMessage());}//9.如果JWT格式無效,返回錯誤信息if (!isJwtValid) {System.out.println("JWT格式無效,返回錯誤響應");return Result.ok().put("status", "error").put("msg", "token格式無效");}//10.根據userId拼接Redis中存儲token的keyString redisKey = "communityuser-" + userId;System.out.println("Redis中存儲token的key:" + redisKey);//11.從Redis中獲取存儲的tokenString redisToken = (String) redisTemplate.opsForValue().get(redisKey);System.out.println("從Redis中獲取到的token:" + redisToken);//12.判斷Redis中是否存在token且與請求中的token一致boolean isTokenValid = redisToken != null && redisToken.equals(token);System.out.println("Redis中token與請求token是否一致:" + isTokenValid);//13.根據雙重驗證結果返回對應的響應信息if (isTokenValid) {System.out.println("token雙重驗證通過,返回成功響應");return Result.ok().put("status", "ok").put("msg", "token驗證通過");} else {System.out.println("token雙重驗證失敗,返回錯誤響應");return Result.ok().put("status", "error").put("msg", "token已失效或不匹配");}}

利用上面得Token校驗實現動態路由

加載動態路由

實現思路

1.通過session獲取用戶信息

2.根據userId獲取角色名稱,需要在user_role表和role表中聯表查詢

3.根據userId獲取用戶的權限菜單:

第一步:根據用戶的id查詢該用戶所對應的角色以及該角色所對應的菜單,需要user_role、user_menu、menu三個表聯表查詢;

第二步:按照查詢出來的菜單進行封裝,一個一級菜單的信息封裝進一個列表,此菜單下的二級菜單的信息封裝進此列表的子列表中,若有三級菜單以此類推進行封裝

④返回用戶信息、角色名稱和用戶的權限菜單信息,格式如

```json
{"msg": "操作成功","code": 200,"data": {"userId": 1,"username": "admin", "password": "8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92","realName": "管理員", "contact": "", "mobile": "15679711120", "status": 1},"roles": "超級管理員","routers": [{"name": "系統管理","path": "/sys","hidden": "false","redirect": "noRedirect","component": "Layout","alwaysShow": true,"meta": {"title": "系統管理","icon": "system"},"children": [{"name": "管理員管理","path": "/user","hidden": "false","component": "sys/user/index","meta": {"title": "管理員管理","icon": "user"}}]}]
}

封裝返回的routers信息MenuRouterVO、ChildMenuRouterVO、MenuRouterVO

package com.qcby.vo;import lombok.Data;import java.util.List;@Data
public class MenuRouterVO {private String name;private String path;private String component;private String hidden;private String redirect = "noRedirect";private Boolean alwaysShow = true;private MetaVO meta;private List<ChildMenuRouterVO> children;}
package com.qcby.vo;import lombok.Data;@Data
public class ChildMenuRouterVO {private String name;private String path;private String component;private String hidden;private MetaVO meta;}
package com.qcby.vo;import lombok.Data;@Data
public class MetaVO {private String title;private String icon;
}

加載動態路由controller請求

/*** 通過登錄的用于加載動態路由* 顯示該用戶能訪問的菜單* @param session* @return*/@RequestMapping("/getRouters")public Result getRouters(HttpSession session){//獲取用戶名稱User user = (User)session.getAttribute("user");//獲取用戶的角色名稱String roles = roleMapper.getRoleNameByUserId(user.getUserId());//獲取用戶的權限菜單List<MenuRouterVO> routers = this.menuService.getMenuRouterByUserId(user.getUserId());return Result.ok().put("data", user).put("roles", roles).put("routers",routers);}

獲取用戶的角色名稱的mapper

@Select("SELECT role_name FROM role, user_role where user_role.role_id=role.role_id and user_role.user_id=#{userId}")public String getRoleNameByUserId(Integer userId);

獲取用戶的菜單信息service

 /*** 重寫接口方法,根據用戶ID獲取菜單路由信息* @param userId 用戶ID* @return 菜單路由信息列表*/@Overridepublic List<MenuRouterVO> getMenuRouterByUserId(Integer userId) {// 1. 根據用戶ID查詢該用戶擁有的角色及對應的所有菜單列表List<Menu> menuList = this.menuMapper.getMenusByUserId(userId);// 2. 創建最終要返回的菜單路由VO集合(VO用于前端展示的數據模型)List<MenuRouterVO> list = new ArrayList<>();// 3. 遍歷所有菜單,篩選出一級菜單(父菜單ID為0)并封裝成MenuRouterVOfor (Menu menu : menuList) {// 篩選一級菜單(parentId為0表示是頂級菜單)if (menu.getParentId() == 0) {// 創建一級菜單路由VO對象MenuRouterVO menuRouterVO = new MenuRouterVO();// 復制Menu對象的屬性到MenuRouterVO(使用框架提供的屬性拷貝工具類)BeanUtils.copyProperties(menu, menuRouterVO);// 封裝Meta信息(前端顯示需要的標題和圖標)MetaVO metaVO = new MetaVO();metaVO.setTitle(menu.getName()); // 設置菜單標題metaVO.setIcon(menu.getIcon()); // 設置菜單圖標menuRouterVO.setMeta(metaVO); // 將meta信息設置到路由對象// 獲取當前一級菜單的ID,用于匹配其子菜單Integer menuId = menu.getMenuId();// 4. 創建子菜單集合,用于存儲當前一級菜單下的所有子菜單List<ChildMenuRouterVO> children = new ArrayList<>();// 遍歷所有菜單,篩選出屬于當前一級菜單的子菜單for (Menu child : menuList) {// 判斷當前菜單是否為當前一級菜單的子菜單(子菜單的parentId等于父菜單的menuId)if(child.getParentId() == menuId){// 5. 創建子菜單路由VO對象并封裝數據ChildMenuRouterVO childVO = new ChildMenuRouterVO();BeanUtils.copyProperties(child, childVO); // 復制基本屬性// 封裝子菜單的Meta信息MetaVO childMetaVO = new MetaVO();childMetaVO.setTitle(child.getName()); // 子菜單標題childMetaVO.setIcon(child.getIcon()); // 子菜單圖標childVO.setMeta(childMetaVO); // 設置子菜單的meta信息// 將子菜單添加到子菜單集合children.add(childVO);}}// 6. 將子菜單集合設置到當前一級菜單路由對象中menuRouterVO.setChildren(children);// 7. 將封裝好的一級菜單路由對象添加到最終返回的集合中list.add(menuRouterVO);}}// 返回整理好的菜單路由列表(包含一級菜單和對應的子菜單)return list;}

獲取用戶的菜單信息mapper

    @Select({"select m.menu_id,m.parent_id,m.name,m.path,m.component," +"m.menu_type,m.status,m.icon,m.sort,m.hidden from " +"user_role ur,role_menu rm,menu m where ur.role_id = rm.role_id" +" and rm.menu_id = m.menu_id " +"and ur.user_id = #{userId} order by m.sort"})public List<Menu> getMenusByUserId(Integer userId);

結果圖

登錄進去之后就能夠看到一級目錄

每個目錄下面有對應得子目錄

2.修改密碼

實現思路

①發送更新密碼請求,彈出更新密碼彈出層

②前端密碼格式驗證,新舊密碼是否一致驗證

③修改密碼:第一步獲取session中的用戶信息;第二步將根據用戶查詢的密碼和前端傳來的舊密碼進行比較,如果相等,將新密碼加密后在數據庫中更新密碼字段信息,密碼更新成功,返回。

修改密碼請求處理

/*** 修改用戶密碼的控制器方法* @return 返回操作結果*/@PutMapping("/updatePassword")  // 使用PUT映射處理/updatePassword請求public Result updatePassword(@RequestBody UpdatePasswordFrom updatePasswordFrom, HttpSession session){// 從session中獲取當前登錄的用戶信息User user = (User)session.getAttribute("user");// 獲取用戶當前存儲的密碼String pwd = user.getPassword();// 使用SHA-256算法對用戶輸入的原密碼進行加密String password = SecureUtil.sha256(updatePasswordFrom.getPassword());// 比較數據庫中的密碼和用戶輸入的原密碼是否一致if(pwd.equals(password)){String newpassword = SecureUtil.sha256(updatePasswordFrom.getNewPassword());user.setPassword(newpassword);if(userService.updateById(user)){return Result.ok().put("status","success");}return Result.error("修改失敗");}
// 原密碼驗證失敗return Result.ok().put("status","passwordError");}

密碼修改表單實體類UpdatePasswordFrom

package com.qcby.DTO;import lombok.Data;/*** 密碼修改表單實體類* 用于接收前端傳遞的舊密碼修改相關參數*/
@Data
public class UpdatePasswordFrom {/*** 當前密碼(舊密碼)*/private String password;/*** 新密碼*/private String newPassword;/*** 確認新密碼(可選,用于前端二次驗證)*/private String confirmPassword;
}

?結果

3.退出登錄模塊

實現思路

①登出請求:將當前session設置為無效

②將token設置為空

③將router設置為空

④將cookie里面的token信息清空

⑤返回登錄頁面

登出請求處理

 /*** 用戶退出* @param session* @return*/@RequestMapping("/logout")public Result logOut(HttpSession session){session.invalidate();return Result.ok();}

結果圖

4.小區的增刪改查

對應的實體類

package com.qcby.entity;import lombok.Data;import java.util.Date;@Data
public class Community {private Integer communityId;private String communityName;private Integer termCount;private Integer seq;private String creater;private Date createTime;private Float lng;private Float lat;
}

服務層

package com.qcby.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.qcby.DTO.CommunityListFrom;
import com.qcby.entity.Community;
import com.qcby.vo.PageVO;public interface ICommunityService extends IService<Community> {PageVO communityList(CommunityListFrom communityListForm);
}

增刪改查的實現思路?

對于傳入參數,如果有,但是參數不多,只有一個,直接接收;如果參數較多,應將其傳入字段封裝在一個實體類中。對于get請求,用@PathVariable接收,對于非get請求,用@RequestBody接收。

對于返回參數,如果與數據單表中的字段可以進行一一映射,不需要考慮封裝,直接返回;如果無法在單表中進行一一映射,則需要根據返回參數進行實體類封裝。

對于單表的增刪改查,mybatiaPlus提供了相應的操作,對于多表則需要手寫sql語句

4.1小區搜索和查詢

傳入參數

{"page": 1,"limit": 10,"communityId": "","communityName": ""
}

返回參數

{"msg": "操作成功","code": 200,"data": {"totalCount": 8,"pageSize": 10,"totalPage": 1,"currPage": 1,"list": [{"communityId": 19,"communityName": "北清云際","termCount": 33,"seq": 190,"creater": "admin","createTime": "2023-07-18 00:41:20","lng": 116.298904,"lat": 40.091644,"personCnt": 1},{"communityId": 17,"communityName": "天龍苑","termCount": 10,"seq": 170,"creater": "admin","createTime": "2023-07-18 00:38:06","lng": 116.36206,"lat": 40.088108,"personCnt": 0}]}
} 

?實現思路:由于返回list中在community表中沒有personCnt字段,因此需要封裝一個CommunityVO類用于數據的返回。同時由于mybtisPlus中并沒有現成的sql用于根據community_id查詢相應的居民人數,因此需要編寫sql用來查詢每個community對于的人數personCnt

CommunityVO類

package com.qcby.vo;import lombok.Data;import java.util.Date;@Data
public class CommunityVO {private Integer communityId;private String communityName;private Integer termCount;private Integer seq;private String creater;private Date createTime;private Float lng;private Float lat;private Integer personCnt;
}

?controller

/*** 獲取小區的所有信息,分頁條件查詢* @return*/@GetMapping("/list")public Result getList(CommunityListFrom communityListFrom){PageVO pageVO = this.communityService.communityList(communityListFrom);return Result.ok().put("data",pageVO);}

service?

// CommunityServiceImpl.java
package com.qcby.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qcby.DTO.CommunityListFrom;
import com.qcby.entity.Community;
import com.qcby.mapper.CommunityMapper;
import com.qcby.service.ICommunityService;
import com.qcby.vo.CommunityVO;
import com.qcby.vo.PageVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.ArrayList;
import java.util.List;@Service
public class CommunityServiceImpl extends ServiceImpl<CommunityMapper, Community> implements ICommunityService {@Autowiredprivate CommunityMapper communityMapper;@Overridepublic PageVO communityList(CommunityListFrom communityListForm) {Page<Community> page = new Page<>(communityListForm.getPage(), communityListForm.getLimit());QueryWrapper<Community> queryWrapper = new QueryWrapper<>();queryWrapper.like(StringUtils.isNotBlank(communityListForm.getCommunityName()), "community_name", communityListForm.getCommunityName());Page<Community> resultPage = this.communityMapper.selectPage(page, queryWrapper);PageVO pageVO = new PageVO();List<CommunityVO> list = new ArrayList<>();for (Community record : resultPage.getRecords()) {CommunityVO communityVO = new CommunityVO();BeanUtils.copyProperties(record, communityVO);Integer personCount = communityMapper.getCountByCommunityId(record.getCommunityId());communityVO.setPersonCnt(personCount);list.add(communityVO);}pageVO.setList(list);pageVO.setTotalCount(resultPage.getTotal());pageVO.setPageSize(resultPage.getSize());pageVO.setCurrPage(resultPage.getCurrent());pageVO.setTotalPage(resultPage.getPages());return pageVO;}
}

?根據communityId查詢居民人數的mapper

@Select({"select count(*) from person where community_id = #{communityId} "})Integer getCountByCommunityId(Integer communityId);

分頁?

用于分頁封裝的實體類
package com.qcby.vo;import lombok.Data;import java.util.List;@Data
public class PageVO {private Long totalCount;private Long totalPage;private Long pageSize;private Long currPage;private List list;
}
分頁的相關配置?
package com.qcby.config;import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MyBatisPlusConfig {/*** 配置分頁插件*/@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 添加分頁攔截器(支持MySQL、PostgreSQL等主流數據庫)interceptor.addInnerInterceptor(new PaginationInnerInterceptor());//添加樂觀鎖插件interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;}
}

結果圖

4.2添加小區

傳入參數

{"communityName": "test""lat": "1""lng": "1""seq": 1"termCount": "1"
}

返回參數

 {"msg": "操作成功","code": 200
}

controller

 /*** 添加小區* @param community* @param session* @return*/@RequestMapping("/add")public Result add(@RequestBody Community community, HttpSession session){User user = (User) session.getAttribute("user");community.setCreater(user.getUsername());boolean save = this.communityService.save(community);if(!save) return Result.error("添加失敗");return Result.ok();}

界面

4.3通過id查詢小區

傳入參數

1

返回參數

{"msg": "操作成功","code": 200,"data": {"communityId": 19,"communityName": "北清云際","termCount": 33,"seq": 190,"lng": 116.298904,"lat": 40.091644}
}

controller

 /*** 修改的回顯操作* @param id* @return*/@RequestMapping("/info/{id}")public Result info(@PathVariable("id") Integer id){Community community = this.communityService.getById(id);if(community == null){return Result.error("沒有此小區");}return Result.ok().put("data",community);}

界面

?4.4修改小區

傳入參數

{"communityId": 21,"communityName": "1","termCount": "12","lng": "12","lat": "12","seq": 210
}

返回參數

{"msg": "操作成功","code": 200
}

controller

/*** 修改小區信息* @param community* @return*/@RequestMapping("/edit")public Result edit(@RequestBody Community community){boolean updateById = this.communityService.updateById(community);if(!updateById) return Result.error("修改失敗");return Result.ok();}

界面

4.5刪除小區

傳入參數

[21,20
]

返回參數

{"msg": "操作成功","code": 200
}

controller

   /*** 僅刪除小區信息,不刪除關聯表數據(不使用try-catch)* @param ids 小區ID數組* @return 操作結果*/@RequestMapping("/del")@Transactionalpublic Result del(@RequestBody Integer[] ids) {// 刪除小區數據boolean remove = this.communityService.removeByIds(Arrays.asList(ids));if (!remove) {return Result.error("小區刪除失敗");}return Result.ok();}

界面

注意:在刪除小區的同時也會刪除掉這個小區對應的攝像頭、訪客記錄、小區出入記錄、小區居民,如果數據庫中沒有則會個小區對應的內容則會刪除失敗

5.攝像頭的增刪改查

和上面的小區的實現基本一致

對應的Controller

package com.qcby.controller;import com.qcby.entity.Camera;
import com.qcby.entity.User;
import com.qcby.service.ICameraService;
import com.qcby.utils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpSession;
import java.util.Arrays;
import java.util.List;@RestController
@RequestMapping("/sys/camera")
public class CameraController {@Autowiredprivate ICameraService cameraService;/*** 查詢攝像頭列表*/@GetMapping("/list/{communityId}")public Result getCameraList(@PathVariable Integer communityId) {try {// 調用關聯查詢方法,獲取包含小區名稱的攝像頭列表List<Camera> cameraList = cameraService.getCameraListWithCommunityName(communityId);return Result.ok().put("data", cameraList);} catch (Exception e) {return Result.error("查詢失敗:" + e.getMessage());}}/*** 添加攝像頭*/@RequestMapping("/add")public Result add(@RequestBody Camera camera, HttpSession session){User user = (User) session.getAttribute("user");camera.setCreater(user.getUsername());boolean save = cameraService.save(camera);if(!save) return Result.error("添加失敗");return Result.ok();}/*** 修改的回顯操作* @param id* @return*/@RequestMapping("/info/{id}")public Result info(@PathVariable("id") Integer id){Camera camera = cameraService.getById(id);if(camera == null){return Result.error("沒有此攝像頭");}return Result.ok().put("data",camera);}/*** 修改攝像頭信息* @param camera* @return*/@RequestMapping("/edit")public Result edit(@RequestBody Camera camera){boolean updateById = cameraService.updateById(camera);if(!updateById) return Result.error("修改失敗");return Result.ok();}/*** 刪除攝像頭信息* @param ids 攝像頭ID數組* @return 操作結果*/@RequestMapping("/del")public Result del(@RequestBody Integer[] ids){boolean remove = cameraService.removeByIds(Arrays.asList(ids));if(!remove) return Result.error("刪除失敗");return Result.ok();}
}

對應的實體類

package com.qcby.entity;import lombok.Data;@Data
public class Person {private Integer personId;private Integer communityId;private String termName;private String houseNo;private String userName;private String sex;private String mobile;private String faceUrl;private String personType;private Integer state;private String creater;private String createTime;private String remark;private String faceBase;
}

對應的Mapper.java

package com.qcby.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.qcby.entity.Camera;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Param;
import java.util.List;public interface CameraMapper extends BaseMapper<Camera> {// 聯表查詢,通過 camera 的 community_id 關聯 community 表,獲取小區名稱@Select("SELECT c.*, com.community_name as communityName " +"FROM camera c " +"LEFT JOIN community com ON c.community_id = com.community_id " +"WHERE c.community_id = #{communityId}")List<Camera> selectCameraWithCommunityName(@Param("communityId") Integer communityId);
}

應的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.mapper.CameraMapper"><!-- 與數據庫表字段嚴格映射 --><resultMap id="BaseResultMap" type="com.qcby.entity.Camera"><id column="camera_id" property="cameraId" /><result column="community_id" property="communityId" /><result column="camera_name" property="cameraName" /><result column="mac_id" property="macId" /><result column="direction" property="direction" /><result column="state" property="state" /><result column="seq" property="seq" /><result column="creater" property="creater" /><result column="create_time" property="createTime" /><result column="remark" property="remark" /></resultMap><!-- 完整查詢字段列表 --><sql id="Base_Column_List">camera_id,community_id,camera_name,mac_id,direction,state,seq,creater,create_time,remark</sql><!-- selectById 實現(MyBatis-Plus 基礎方法) --><select id="selectById" resultMap="BaseResultMap">SELECT<include refid="Base_Column_List" />FROM cameraWHERE camera_id = #{id}</select><!--修改攝像頭信息--><update id="updateById" parameterType="com.qcby.entity.Camera">UPDATE camera<set><if test="et.cameraName != null">camera_name = #{et.cameraName},</if><if test="et.macId != null"> mac_id = #{et.macId},</if><if test="et.direction != null"> direction = #{et.direction},</if><if test="et.state != null"> state = #{et.state},</if><if test="et.seq != null"> seq = #{et.seq},</if><if test="et.remark != null"> remark = #{et.remark},</if></set>WHERE camera_id = #{et.cameraId}</update><!--刪除攝像頭--><delete id="deleteBatchIds" parameterType="java.util.Collection">DELETE FROM cameraWHERE camera_id IN<foreach item="id" collection="coll" separator="," open="(" close=")">#{id}</foreach></delete>
</mapper>

對應的ICameraService

package com.qcby.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.qcby.entity.Camera;import java.util.List;public interface ICameraService extends IService<Camera> {List<Camera> getCameraListWithCommunityName(Integer communityId);
}

對應的CameraServiceImpl

package com.qcby.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qcby.entity.Camera;
import com.qcby.mapper.CameraMapper;
import com.qcby.service.ICameraService;
import org.springframework.stereotype.Service;import java.util.List;@Service
public class CameraServiceImpl extends ServiceImpl<CameraMapper, Camera> implements ICameraService {@Overridepublic List<Camera> getCameraListWithCommunityName(Integer communityId) {return baseMapper.selectCameraWithCommunityName(communityId);}
}

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

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

相關文章

K-Means聚類:當數據沒有標簽時,如何讓計算機自動“物以類聚”?

K-Means聚類&#xff1a;當數據沒有標簽時&#xff0c;如何讓計算機自動“物以類聚”&#xff1f;&#x1f44b; 大家好&#xff0c;我是小瑞瑞&#xff01;歡迎回到我的專欄&#xff01; 在我們之前的旅程中&#xff0c;解決的問題大多都有一個明確的“目標”&#xff0c;比如…

萬事皆可用 GeeLark AI

在今年4月&#xff0c;GeeLark AI 全面接入 DeepSeek AI 大模型&#xff0c;你可以在獨立窗口中便捷地使用 GeeLark AI。除了幫助你編寫文案等基礎內容&#xff0c;在使用 GeeLark 過程中&#xff0c;如果遇到問題&#xff0c;也可以通過詢問 GeeLark AI&#xff0c;及時獲取幫…

3D 高保真處理:聲網讓游戲聲音隨角色動作變化

傳統游戲的聲音體驗像老式收音機&#xff0c;不管聲源位置、距離和障礙物&#xff0c;僅靠左右聲道機械調音量&#xff0c;毫無方向感和空間感&#xff0c;如同蒙眼聽聲辨位。射擊游戲中敵人從左邊來&#xff0c;耳機卻兩邊同響且音量相近&#xff0c;讓人暈頭轉向&#xff1b;…

Nestjs框架: 請求生命周期與應用生命周期

概述 在 NestJS 框架中&#xff0c;中間件&#xff08;Middleware&#xff09;、管道&#xff08;Pipes&#xff09;、過濾器&#xff08;Filters&#xff09;、攔截器&#xff08;Interceptors&#xff09; 均屬于請求處理流程的核心組件&#xff0c;它們共同構成了 NestJS 的…

Nastool+cpolar:群暉NAS用戶的全場景影音自由方案

文章目錄前言1. 本地搭建Nastool2. nastool基礎設置3. 群暉NAS安裝內網穿透工具4. 配置公網地址小結5. 配置固定公網地址**第二版&#xff1a;技術整合與效率提升導向****第二版&#xff1a;技術整合與效率提升導向****第二版&#xff1a;技術整合與效率提升導向**Nastool與cpo…

從零開始:Kaggle 競賽實戰入門指南

一、Kaggle社區概述 Kaggle 是全球最大的數據科學和機器學習社區&#xff0c;由Anthony Goldbloom于2010年創立&#xff0c;2017年被Google收購。平臺專注于數據科學競賽、開源數據集共享、協作編程以及技能學習&#xff0c;吸引了從初學者到專業數據科學家的廣泛用戶群體。 …

sqli-labs:Less-16關卡詳細解析

1. 思路&#x1f680; 本關的SQL語句為&#xff1a; $uname".$uname."; $passwd".$passwd."; $sql"SELECT username, password FROM users WHERE username($uname) and password($passwd) LIMIT 0,1";注入類型&#xff1a;字符串型&#xff08;…

Lipschitz連續函數

Lipschitz function 一、說明 在數學分析中&#xff0c;Lipschitz連續性以德國 數學家 魯道夫利普希茨 (Rudolf Lipschitz)的名字命名&#xff0c;是函數一致連續性的強形式。直觀地說&#xff0c;Lipschitz連續函數的變化速度有限&#xff1a;存在一個實數&#xff0c;使得對于…

Dynamics 365 business central 與Shopify集成

Dynamics 365 Business Central&#xff08;簡稱 D365 BC&#xff09; 與 Shopify 的集成&#xff0c;能幫助企業實現前端電商平臺&#xff08;Shopify&#xff09;與后端 ERP 系統&#xff08;Business Central&#xff09;之間的無縫數據同步&#xff0c;是一種典型的 ERP 與…

TCP RTO 與丟包檢測

TCP RTO 是它 40 多年前唯一丟包檢測策略&#xff0c;也是當前最后的丟包檢測兜底策略&#xff0c;它幾乎從沒變過。 有個咨詢挺有趣&#xff0c;以其案例為背景寫篇隨筆。大致意思是&#xff0c;嫌 TCP RTO 太大&#xff0c;游戲場景丟包卡頓怎么辦&#xff1f;我提供了幾行代…

安裝php和配置環境變量

為了簡單方便&#xff0c;先下載vscode然后下載對應的php安裝包&#xff0c;然后配置環境變量&#xff0c;然后點擊運行即可下載對應版本的php&#xff0c;這個版本湊合用然后下載完之后解壓配置環境變量搜索環境變量將路徑添加到環境變量中然后打開vscode添加變量具體看實際路…

Rabbit MQ的消息模式-Java原生代碼

一.簡單模式1.1.核心邏輯生產者 → 隊列 → 單個消費者&#xff08;1:1 直連&#xff09;&#xff0c;消息被消費后自動從隊列刪除。1.2.關鍵特性無交換器&#xff08;其實使用的是默認交換機不是顯示指定&#xff09;&#xff0c;直接指定隊列 消息默認自動確認&#xff08;au…

【lucene】使用docvalues的案例

下面給出一段 可直接跑通 的 Lucene 8.5.0 示例代碼&#xff0c;演示如何1. 建索引時為兩個字段啟用 DocValues&#xff08;一個 NumericDocValues&#xff0c;一個 SortedDocValues&#xff09;&#xff1b; 2. 用 IndexSearcher 按 DocValues 排序&#xff1b; 3. 用 Facet…

IntelliJ IDEA 配置 Maven 阿里云鏡像加速源全流程

1. 為什么要加國內鏡像源&#xff1f;國內網絡訪問 Maven 中央倉庫經常超時、依賴下載極慢或失敗。配置阿里云等國內鏡像后&#xff0c;Java 項目依賴下載飛快&#xff0c;極大提升開發效率&#xff0c;是中國開發者必做優化&#xff01;2. 添加阿里云鏡像源的步驟&#xff08;…

【worklist】worklist的hl7、dicom是什么關系

HL7和DICOM在Worklist系統中是互補的關系&#xff0c;它們各自承擔不同的角色&#xff0c;但協同工作以實現完整的醫療信息系統集成。HL7與DICOM Worklist的關系1. 功能分工DICOM Worklist (Modality Worklist - MWL)主要用于影像設備獲取患者和檢查信息基于DICOM協議&#xff…

位運算-面試題01.01.判定字符是否唯一-力扣(LeetCode)

一、題目解析1、s[i]僅包含小寫字母2、字符串的長度為[0&#xff0c;100]二、算法原理解法1&#xff1a;哈希表用哈希表記錄s[i]的字符&#xff0c;如果有重復的&#xff0c;則返回false優化1&#xff1a;由于s[i]中只有小寫字母&#xff0c;所以可以創建一個int hash[26]的數組…

wsl /lib/x86_64-linux-gnu/libc.so.6: version GLIBC_2.28‘ not found

遇到的問題并沒有解決&#xff0c;這個 glibc-2.28 應該是安裝好了 Ubuntu18 問題描述&#xff1a;Ubuntu18 WSL 無法啟動 VS Code &#xff0c;因為node版本問題 rootUbuntu18:~# code . /lib/x86_64-linux-gnu/libc.so.6: version GLIBC_2.28 not found (required by /root…

Windows系統ffmpeg.dll丟失怎么辦?從錯誤分析到永久修復的完整流程

您是否遇到過這樣的情況&#xff1a;打開心愛的視頻編輯軟件時&#xff0c;系統突然提示無法啟動此程序&#xff0c;因為計算機中丟失ffmpeg.dll&#xff1f;別擔心&#xff0c;這個問題比您想象的要常見得多。作為專業的技術支持團隊&#xff0c;我們已經幫助數千用戶解決了類…

LaTeX 復雜圖形繪制教程:從基礎到進階

系列文章目錄 第一章&#xff1a;深入了解 LaTeX&#xff1a;科技文檔排版的利器 第二章&#xff1a;LaTeX 下載安裝保姆級教程 第三章&#xff1a;LaTeX 創建工程并生成完整文檔指南 第四章&#xff1a;LaTeX 表格制作全面指南 文章目錄系列文章目錄前言一、?LaTeX 繪圖工具…

用 Go Typed Client 快速上手 Elasticsearch —— 從建索引到聚合的完整實戰

1. 準備工作 go get github.com/elastic/go-elasticsearch/v9小貼士 如果你的集群啟用了安全特性&#xff0c;需要在 elasticsearch.Config 中配置 Username/Password 或 APIKey。Typed Client 通過 NewTypedClient 創建&#xff0c;內部復用 *http.Client&#xff0c;建議全局…