【黑马头条】-day01环境搭建SpringBoot-Cloud-Nacos
文章目录
- 1 环境搭建及简介
- 2 项目介绍
- 2.1 应用
- 2.2 业务说明
- 2.3 技术栈
- 2.4 收获
- 2.5 大纲
- 3 Nacos准备
- 3.1 安装Nacos
- 4 初始工程搭建
- 4.1 环境准备
- 4.1.1 导入项目
- 4.1.2 设置本地仓库
- 4.1.3 设置项目编码格式
- 4.2 全局异常
- 4.2.1 自动装配
- 4.3 工程主体结构
- 5 登录功能开发
- 5.1 需求分析
- 5.1.1 表结构分析
- 5.1.2 实体类ApUser的导入
- 5.1.3 表结构中salt的解释
- 5.1.3.1 注册过程
- 5.1.3.2 登录过程
- 6 用户端微服务的搭建
- 6.1 service模块的依赖说明
- 6.2 创建用户微服务模块
- 6.2.1 创建引导类
- 6.2.2 创建controller.v1、service、mapper、config
- 6.2.3 创建resources的配置文件
- 6.2.3.1 bootstrap.yml
- 6.2.3.2 logback.xml
- 6.3 整体用户端框架
- 7 登录接口实现
- 7.1 app登录-接口定义
- 7.1.1 DTO的LoginDto类
- 7.1.2 Controller层ApUserLoginController类
- 7.1.3 Mapper层ApUserMapper接口
- 7.1.4 Service层ApUserService接口
- 7.1.5 实现ApUserService接口
- 7.1.6 完善业务层接口
- 7.2 登录思路分析
- 7.2.1 业务层登录实现
- 7.2.2 Controller注入
- 7.2.3 测试
- 8 App端网关
- 8.1 导入依赖
- 8.2 微服务创建网关
- 8.2.1 AppGateway
- 8.2.2 创建配置文件bootstrap.yml
- 8.2.3 在Nacos中创建配置中心
- 9 认证过滤器
- 9.1 全局过滤器
- 9.2 测试
- 10 app前端项目集成
- 10.1 Nginx反向代理和静态资源配置
1 环境搭建及简介
2 项目介绍
2.1 应用
2.2 业务说明
2.3 技术栈
前端
后端
2.4 收获
2.5 大纲
3 Nacos准备
3.1 安装Nacos
1)拉取镜像
docker pull nacos/nacos-server:1.2.0
2)创建容器
docker run --env MODE=standalone --name nacos --restart=always -d -p 8848:8848 nacos/nacos-server:1.2.0
3)查看日志
docker logs -f nacos
4)访问当前Nacos
http://192.168.204.129:8848/nacos
4 初始工程搭建
4.1 环境准备
4.1.1 导入项目
解压heima-leadnews.zip,并且导入idea,设置jdk为1.8
4.1.2 设置本地仓库
respository_new.zip解压到本地仓库文件夹
打开idea-settings设置本地仓库
修改为
4.1.3 设置项目编码格式
4.2 全局异常
heima-leadnews-common模块下的com.heima.common.exception包下自定义异常类CustomException,如果我们手动抛出异常就需要抛出CustomException类
public class CustomException extends RuntimeException {private AppHttpCodeEnum appHttpCodeEnum;public CustomException(AppHttpCodeEnum appHttpCodeEnum){this.appHttpCodeEnum = appHttpCodeEnum;}public AppHttpCodeEnum getAppHttpCodeEnum() {return appHttpCodeEnum;}
}
另外一个类ExceptionCatch类,全局异常拦截类
注解@ControllerAdvice
:ControllerAdvice本质上是一个Component,因此也会被当成组件扫描,一视同仁,扫扫扫。
- 这个类是为那些声明了(@ExceptionHandler、@InitBinder 或 @ModelAttribute注解修饰的)方法的类而提供的专业化的@Component , 以供多个 Controller类所共享。
@ControllerAdvice //控制器增强类
@Slf4j
public class ExceptionCatch {/*** 处理不可控异常* @param e* @return*/@ExceptionHandler(Exception.class)@ResponseBodypublic ResponseResult exception(Exception e){e.printStackTrace();log.error("catch exception:{}",e.getMessage());return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);}/*** 处理可控异常 自定义异常* @param e* @return*/@ExceptionHandler(CustomException.class)@ResponseBodypublic ResponseResult exception(CustomException e){log.error("catch exception:{}",e);return ResponseResult.errorResult(e.getAppHttpCodeEnum());}
}
在heima-leadnews-model模块下的com.heima.model包下的common包下的enums包下有个枚举类AppHttpCodeEnum,用来存放对异常的说明
public enum AppHttpCodeEnum {// 成功段0SUCCESS(200,"操作成功"),// 登录段1~50NEED_LOGIN(1,"需要登录后操作"),LOGIN_PASSWORD_ERROR(2,"密码错误"),// TOKEN50~100TOKEN_INVALID(50,"无效的TOKEN"),TOKEN_EXPIRE(51,"TOKEN已过期"),TOKEN_REQUIRE(52,"TOKEN是必须的"),// SIGN验签 100~120SIGN_INVALID(100,"无效的SIGN"),SIG_TIMEOUT(101,"SIGN已过期"),// 参数错误 500~1000PARAM_REQUIRE(500,"缺少参数"),PARAM_INVALID(501,"无效参数"),PARAM_IMAGE_FORMAT_ERROR(502,"图片格式有误"),SERVER_ERROR(503,"服务器内部错误"),// 数据错误 1000~2000DATA_EXIST(1000,"数据已经存在"),AP_USER_DATA_NOT_EXIST(1001,"ApUser数据不存在"),DATA_NOT_EXIST(1002,"数据不存在"),// 数据错误 3000~3500NO_OPERATOR_AUTH(3000,"无权限操作"),NEED_ADMIND(3001,"需要管理员权限");int code;String errorMessage;AppHttpCodeEnum(int code, String errorMessage){this.code = code;this.errorMessage = errorMessage;}public int getCode() {return code;}public String getErrorMessage() {return errorMessage;}
}
4.2.1 自动装配
resource下META-INF有spring.factories,只有有微服务引用了heima-leadnews-common,服务器初始化spring容器的时候就会找到spring.factories,把spring.factories中需要自动配置的文件加载到当前微服务的容器中,也就能用全局处理器了。
4.3 工程主体结构
5 登录功能开发
5.1 需求分析
5.1.1 表结构分析
打开本地sql工具,引入sql脚本,创建leadnews_user,有四张表
5.1.2 实体类ApUser的导入
在heima-leadnews-model模块下创建com.heima.model.user.pojos包下创建实体类ApUser
@TableName("ap_user")
:表的映射
@TableId(value = "id", type = IdType.AUTO)
:主键的映射
@TableField("name")
:其他字段的映射
@Data
@TableName("ap_user")
public class ApUser implements Serializable {private static final long serialVersionUID = 1L;/*** 主键*/@TableId(value = "id", type = IdType.AUTO)private Integer id;/*** 密码、通信等加密盐*/@TableField("salt")private String salt;/*** 用户名*/@TableField("name")private String name;/*** 密码,md5加密*/@TableField("password")private String password;/*** 手机号*/@TableField("phone")private String phone;/*** 头像*/@TableField("image")private String image;/*** 0 男1 女2 未知*/@TableField("sex")private Boolean sex;/*** 0 未1 是*/@TableField("is_certification")private Boolean certification;/*** 是否身份认证*/@TableField("is_identity_authentication")private Boolean identityAuthentication;/*** 0正常1锁定*/@TableField("status")private Boolean status;/*** 0 普通用户1 自媒体人2 大V*/@TableField("flag")private Short flag;/*** 注册时间*/@TableField("created_time")private Date createdTime;}
5.1.3 表结构中salt的解释
salt:密码、通信等加密盐
5.1.3.1 注册过程
5.1.3.2 登录过程
6 用户端微服务的搭建
heima-leadnews-service模块是管理其他所有微服务模块
6.1 service模块的依赖说明
6.2 创建用户微服务模块
在heima-leadnews-service下创建模块
6.2.1 创建引导类
然后创建一个包com.heima.user,再创建一个引导类UserApplication
@SpringBootApplication
: 启动类注解
@EnableDiscoveryClient
:集成当前的注册中心,加入注册中心
@MapperScan("com.heima.user.mapper")
:继承MybatisPlus,扫描Mapper接口,没有就在com.heima.user下创建mapper包
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan("com.heima.user.mapper")
public class UserApplication {public static void main(String[] args) {SpringApplication.run(UserApplication.class, args);}
}
6.2.2 创建controller.v1、service、mapper、config
controller.v1是不同版本的controller
6.2.3 创建resources的配置文件
6.2.3.1 bootstrap.yml
若application.yml 和bootstrap.yml在同一目录下:bootstrap.yml 先加载 application.yml后加载,application.yml会覆盖
创建bootstrap.yml
server:port: 51801
spring:application:name: leadnews-usercloud:nacos:discovery:server-addr: 192.168.204.129:8848config:server-addr: 192.168.204.129:8848file-extension: yml
这里面暂时只有Nacos的配置,关于数据库的等等都需要在Nacos的配置中心进行配置
spring:datasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/leadnews_user?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=falseusername: rootpassword: 123sjbsjb
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:mapper-locations: classpath*:mapper/*.xml# 设置别名包扫描路径,通过该属性可以给包中的类注册别名type-aliases-package: com.heima.model.user.pojos
发布查看
6.2.3.2 logback.xml
创建日志文件logback.xml
<?xml version="1.0" encoding="UTF-8"?><configuration><!--定义日志文件的存储地址,使用绝对路径--><property name="LOG_HOME" value="D:\Code\JavaCode\HeimaToutiao\logs"/><!-- Console 输出设置 --><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><encoder><!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern><charset>utf8</charset></encoder></appender><!-- 按照每天生成日志文件 --><appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!--日志文件输出的文件名--><fileNamePattern>${LOG_HOME}/leadnews.%d{yyyy-MM-dd}.log</fileNamePattern></rollingPolicy><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder></appender><!-- 异步输出 --><appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender"><!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 --><discardingThreshold>0</discardingThreshold><!-- 更改默认的队列的深度,该值会影响性能.默认值为256 --><queueSize>512</queueSize><!-- 添加附加的appender,最多只能添加一个 --><appender-ref ref="FILE"/></appender><logger name="org.apache.ibatis.cache.decorators.LoggingCache" level="DEBUG" additivity="false"><appender-ref ref="CONSOLE"/></logger><logger name="org.springframework.boot" level="debug"/><root level="info"><!--<appender-ref ref="ASYNC"/>--><appender-ref ref="FILE"/><appender-ref ref="CONSOLE"/></root>
</configuration>
6.3 整体用户端框架
7 登录接口实现
7.1 app登录-接口定义
7.1.1 DTO的LoginDto类
heima-leadnews-model模块下的com.heima.model.user.pojos.dtos包下创建LoginDto类
@Data
public class LoginDto {private String phone;private String password;
}
7.1.2 Controller层ApUserLoginController类
再在heima-leadnews-service模块下的com.heima.user.controller.v1下创建ApUserLoginController类
POST请求采用@RequestBody
@RestController
@RequestMapping("/api/v1/login")
public class ApUserLoginController {@PostMapping("/login_auth")public ResponseResult login(@RequestBody(required=false) LoginDto dto) {return null;}
}
7.1.3 Mapper层ApUserMapper接口
使用mybatisplus
在com.heima.user.mapper创建ApUserMapper接口
@Mapper
public interface ApUsermapper extends BaseMapper<ApUser> {}
7.1.4 Service层ApUserService接口
public interface ApUserService extends IService<ApUser>{
}
7.1.5 实现ApUserService接口
@Service
@Transactional
@Slf4j
public class ApUserServiceImpl extends ServiceImpl<ApUsermapper, ApUser> implements ApUserService {
}
@Service
标注业务层实现
@Transactional
标注事务
7.1.6 完善业务层接口
public interface ApUserService extends IService<ApUser>{/*** 登录功能* @param dto* @return*/public ResponseResult login(LoginDto dto);
}
实现方法
@Service
@Transactional
@Slf4j
public class ApUserServiceImpl extends ServiceImpl<ApUsermapper, ApUser> implements ApUserService {@Overridepublic ResponseResult login(LoginDto dto) {return null;}
}
7.2 登录思路分析
7.2.1 业务层登录实现
在ApUserServiceImpl类中实现思路
@Service
@Transactional
@Slf4j
public class ApUserServiceImpl extends ServiceImpl<ApUsermapper, ApUser> implements ApUserService {@Overridepublic ResponseResult login(LoginDto dto) {//1.正常登录 用户名、密码if(StringUtils.isNotBlank(dto.getPhone()) && StringUtils.isNotBlank(dto.getPassword())) {//1.1 查询用户信息,根据手机号查询用户信息ApUser dbUser = getOne(Wrappers.<ApUser>lambdaQuery().eq(ApUser::getPhone, dto.getPhone()));if(dbUser == null) {return ResponseResult.errorResult(AppHttpCodeEnum.AP_USER_DATA_NOT_EXIST, "用户不存在");}//1.2 比对密码String salt = dbUser.getSalt();String password = dto.getPassword();String pwd = DigestUtils.md5DigestAsHex((password + salt).getBytes());if(!pwd.equals(dbUser.getPassword())) {return ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_PASSWORD_ERROR, "密码错误");}//1.3 没问题的话,返回数据,生成jwtString token = AppJwtUtil.getToken(dbUser.getId().longValue());Map<String,Object> map=new HashMap<>();map.put("token",token);//清空敏感信息,前端只要id,手机号,昵称ApUser userVO=new ApUser();userVO.setId(dbUser.getId());userVO.setPhone(dbUser.getPhone());userVO.setName(dbUser.getName());map.put("user",userVO);return ResponseResult.okResult(map);}else{//2.游客登录Map<String,Object> map=new HashMap<>();map.put("token",AppJwtUtil.getToken(0L));return ResponseResult.okResult(map);}}
}
加密采用DigestUtils.md5DigestAsHex
传入字节流
生成JWT令牌是使用heima-leadnews-utils模块下的com.heima.utils.common包下的AppJWTUtil
public class AppJwtUtil {// TOKEN的有效期一天(S)private static final int TOKEN_TIME_OUT = 3_600;// 加密KEYprivate static final String TOKEN_ENCRY_KEY = "MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjY";// 最小刷新间隔(S)private static final int REFRESH_TIME = 300;// 生产IDpublic static String getToken(Long id){Map<String, Object> claimMaps = new HashMap<>();claimMaps.put("id",id);long currentTime = System.currentTimeMillis();return Jwts.builder().setId(UUID.randomUUID().toString()).setIssuedAt(new Date(currentTime)) //签发时间.setSubject("system") //说明.setIssuer("heima") //签发者信息.setAudience("app") //接收用户.compressWith(CompressionCodecs.GZIP) //数据压缩方式.signWith(SignatureAlgorithm.HS512, generalKey()) //加密方式.setExpiration(new Date(currentTime + TOKEN_TIME_OUT * 1000)) //过期时间戳.addClaims(claimMaps) //cla信息.compact();}/*** 获取token中的claims信息** @param token* @return*/private static Jws<Claims> getJws(String token) {return Jwts.parser().setSigningKey(generalKey()).parseClaimsJws(token);}/*** 获取payload body信息** @param token* @return*/public static Claims getClaimsBody(String token) {try {return getJws(token).getBody();}catch (ExpiredJwtException e){return null;}}/*** 获取hearder body信息** @param token* @return*/public static JwsHeader getHeaderBody(String token) {return getJws(token).getHeader();}/*** 是否过期** @param claims* @return -1:有效,0:有效,1:过期,2:过期*/public static int verifyToken(Claims claims) {if(claims==null){return 1;}try {claims.getExpiration().before(new Date());// 需要自动刷新TOKENif((claims.getExpiration().getTime()-System.currentTimeMillis())>REFRESH_TIME*1000){return -1;}else {return 0;}} catch (ExpiredJwtException ex) {return 1;}catch (Exception e){return 2;}}/*** 由字符串生成加密key** @return*/public static SecretKey generalKey() {byte[] encodedKey = Base64.getEncoder().encode(TOKEN_ENCRY_KEY.getBytes());SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");return key;}public static void main(String[] args) {/* Map map = new HashMap();map.put("id","11");*/System.out.println(AppJwtUtil.getToken(1102L));Jws<Claims> jws = AppJwtUtil.getJws("eyJhbGciOiJIUzUxMiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAAADWLQQqEMAwA_5KzhURNt_qb1KZYQSi0wi6Lf9942NsMw3zh6AVW2DYmDGl2WabkZgreCaM6VXzhFBfJMcMARTqsxIG9Z888QLui3e3Tup5Pb81013KKmVzJTGo11nf9n8v4nMUaEY73DzTabjmDAAAA.4SuqQ42IGqCgBai6qd4RaVpVxTlZIWC826QA9kLvt9d-yVUw82gU47HDaSfOzgAcloZedYNNpUcd18Ne8vvjQA");Claims claims = jws.getBody();System.out.println(claims.get("id"));}}
7.2.2 Controller注入
@RestController
@RequestMapping("/api/v1/login")
public class ApUserLoginController {@Autowiredprivate ApUserService apUserService;@PostMapping("/login_auth")public ResponseResult login(@RequestBody LoginDto dto) {return apUserService.login(dto);}
}
7.2.3 测试
启动redis报错
修改bootstrap.yml文件,添加redis地址
redis:host: 127.0.0.1port: 6379database: 0
启动,Nacos的服务管理中有leadnews-user
访问http://localhost:51801/api/v1/login/login_auth
8 App端网关
8.1 导入依赖
在heima-leadnews-gateway导入以下依赖
<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId></dependency>
</dependencies>
8.2 微服务创建网关
8.2.1 AppGateway
针对各个微服务创建相应的网关
创建引导类com.heima.app.gateway.AppGatewayApplication
@SpringBootApplication
@EnableDiscoveryClient
public class AppGatewayApplication {public static void main(String[] args) {SpringApplication.run(AppGatewayApplication.class, args);}
}
8.2.2 创建配置文件bootstrap.yml
server:port: 51601
spring:application:name: leadnews-app-gatewaycloud:nacos:discovery:server-addr: 192.168.204.129:8848config:server-addr: 192.168.204.129:8848file-extension: yml
8.2.3 在Nacos中创建配置中心
spring:cloud:gateway:globalcors:add-to-simple-url-handler-mapping: truecorsConfigurations:'[/**]':allowedHeaders: "*"allowedOrigins: "*"allowedMethods:- GET- POST- DELETE- PUT- OPTIONroutes:# 平台管理- id: useruri: lb://leadnews-userpredicates:- Path=/user/**filters:- StripPrefix= 1
id: user
: 这是此路由的唯一标识符。uri: lb://leadnews-user
: 当请求匹配到该路由时,它会被路由到"leadnews-user"服务的实例。URI的前缀"lb://"表示路由到负载均衡器。predicates
: 定义了路由的匹配规则。在这种情况下,请求路径必须以"/user/"开头才会匹配到此路由。filters
: 定义了路由的过滤器。在这里,使用了"StripPrefix"过滤器,该过滤器会将请求的路径中的一层前缀移除。具体来说,这里是将路径中的第一层"/user"移除,以便在转发请求到"leadnews-user"服务时去除不必要的前缀。
访问http://localhost:51601/user/api/v1/login/login_auth
9 认证过滤器
9.1 全局过滤器
要实现这个功能,要实现一个全局的过滤器
在heima-leadnews-gateway模块下创建com.heima.app.gateway.filter.AuthorizeFilter类用作全局过滤器
@Component
@Slf4j
public class AuthorizeFilter implements Ordered, GlobalFilter {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//1.获取Request对象和Response对象ServerHttpRequest request = exchange.getRequest();ServerHttpResponse response = exchange.getResponse();//2.判断当前请求是否为登录请求,如果是,直接放行if (request.getURI().getPath().contains("/login")) {//放行return chain.filter(exchange);}//3.获取当前请求的token信息String token = request.getHeaders().getFirst("token");//4.判断token是否存在if(StringUtils.isBlank(token)) {response.setStatusCode(HttpStatus.UNAUTHORIZED);return response.setComplete();}//5.判断token是否有效//5.1 解析tokentry{Claims body = AppJwtUtil.getClaimsBody(token);//5.2 判断token是否有效int result = AppJwtUtil.verifyToken(body);if(result == 1||result == 2) {//5.3 token过期response.setStatusCode(HttpStatus.UNAUTHORIZED);return response.setComplete();}}catch (Exception e) {e.printStackTrace();//5.4 token无效response.setStatusCode(HttpStatus.UNAUTHORIZED);return response.setComplete();}//6.放行return chain.filter(exchange);}/*** 过滤器的执行顺序,返回值越小,执行优先级越高* @return*/@Overridepublic int getOrder() {return 0;}
}
把AppJwtUtil放入gateway的工具包中
9.2 测试
包含/login直接放行
10 app前端项目集成
10.1 Nginx反向代理和静态资源配置
访问http://localhost:80
将静态资源和nginx都放在工作目录下
在nginx的conf目录下创建文件夹leadnews.conf,新建文件heimi-leadnews-app.conf
nginx端口8801然后转发到gateway端口51601,gateway添加user路径后通过Nacos路由到leadnews-user也就是端口51801完成访问
静态资源存放在D:/Code/JavaCode/HeimaToutiao/app-web/展示其目录下的index.html
upstream heima-app-gateway{server localhost:51601;
}server {listen 8801;location / {root D:/Code/JavaCode/HeimaToutiao/app-web/;index index.html;}location ~/app/(.*) {proxy_pass http://heima-app-gateway/$1;proxy_set_header HOST $host; # 不改变源请求头的值proxy_pass_request_body on; #开启获取请求体proxy_pass_request_headers on; #开启获取请求头proxy_set_header X-Real-IP $remote_addr; # 记录真实发出请求的客户端IPproxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #记录代理信息}
}
在nginx.conf中引入
#user nobody;
worker_processes 1;events {worker_connections 1024;
}
http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;# 引入自定义配置文件include leadnews.conf/*.conf;
}
访问http://localhost:8801
访问成功
相关文章:

【黑马头条】-day01环境搭建SpringBoot-Cloud-Nacos
文章目录 1 环境搭建及简介2 项目介绍2.1 应用2.2 业务说明2.3 技术栈2.4 收获2.5 大纲 3 Nacos准备3.1 安装Nacos 4 初始工程搭建4.1 环境准备4.1.1 导入项目4.1.2 设置本地仓库4.1.3 设置项目编码格式 4.2 全局异常4.2.1 自动装配 4.3 工程主体结构 5 登录功能开发5.1 需求分…...
HTML发展史
为什么要讲 HTML 发展史呢? 唐太宗告诉我们: 以铜为镜,可以正衣冠;以史为镜,可以知兴替;以人为镜,可以明得失。 那了解了 HTML 的发展史,可以知道什么呢? 答案是兼容 国内在 淘宝…...

Java进阶—GC回收(垃圾回收)
1. 什么是垃圾回收 垃圾回收(Garbage Collection,GC)是Java虚拟机(JVM)的一项重要功能,用于自动管理程序中不再使用的内存。在Java中,程序员不需要手动释放内存,因为GC会自动检测并回收不再使用的对象,从而减少内存泄…...

C++默认构造函数(二)
目录 构造函数补充 构造函数初始化列表的使用 赋值运算符重载函数 运算符重载函数介绍 运算符重载函数的使用 赋值运算符重载函数 赋值运算符重载函数的使用 拷贝构造函数和赋值运算符重载函数 重载前置和后置 前置 后置 重载流插入<<与流提取>> 流插…...

云原生部署手册02:将本地应用部署至k8s集群
(一)部署集群镜像仓库 1. 集群配置 首先看一下集群配置: (base) ➜ ~ multipass ls Name State IPv4 Image master Running 192.168.64.5 Ubuntu 22.04 LTS1…...

AJAX——JSON
目录 一、JSON概述 二、JSON对象语法 三、JSON序列化方法 四、JSON与XML比较 五、Java对象与Json对象的转换 六、Js解析服务器发送过来的JSON字符串 七、$.getJSON() 一、JSON概述 JSON简介:JSON的全称为JavaScript Object Nation(JavaScript 对象表示语法),…...

Nexus3 Docker 私有仓库
Nexus3 Docker 私有仓库 安装并部署 Nexus3 $ docker search nexus3$ docker pull sonatype/nexus3$ mkdir /home/tester/data/docker/nexus3/sonatype-work $ sudo chown -R 200 /home/tester/data/docker/nexus3/sonatype-work$ docker run -d --namenexus3 \ --restartalw…...
Element UI el-dialog自由拖动功能
1.创建drag .js文件 /*** 拖拽移动* param {elementObjct} bar 鼠标点击控制拖拽的元素* param {elementObjct} target 移动的元素* param {function} callback 移动后的回调*/ export function startDrag(bar, target, callback) {var params {top: 0,left: 0,currentX: …...
RPC浅析,加密数据解析
个人总结 其实就是HOOK注入wbsocket 链接创建服务端和客户端进行通信,直接调用js代码中的加密方法 将结果通过浏览器客户端传入服务端。一种比较好实用的一种技术 https://blog.csdn.net/qq_36759224/article/details/123082574 (搬运记录下ÿ…...

光速论文能用吗 #媒体#知识分享#学习方法
光速论文是一个非常有效的论文写作、查重降重工具,它的使用非常简单方便,而且功能强大,是每个写作者必备的利器。 首先,光速论文具有强大的查重降重功能,能够快速检测论文中的抄袭部分,帮助作者避免不必要的…...

智慧工地解决方案,智慧工地项目管理系统源码,支持大屏端、PC端、手机端、平板端
智慧工地解决方案依托计算机技术、物联网、云计算、大数据、人工智能、VR&AR等技术相结合,为工程项目管理提供先进技术手段,构建工地现场智能监控和控制体系,弥补传统方法在监管中的缺陷,最线实现项目对人、机、料、法、环的全…...

【前端寻宝之路】学习和使用label标签
🌈个人主页: Aileen_0v0 🔥热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法|MySQL| 💫个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-2nm9oQQVtSL8hDS1 {font-family:"trebuchet ms",verdana,arial,sans-serif;f…...
项目————网络聊天室
服务器 #include <myhead.h> typedef struct msg{char flag;char name[20];char cont[128]; }msg_t;typedef struct link{struct sockaddr_in cin;struct link* next; }link_t;void do_login(int sfd,msg_t msg,link_t *L,struct sockaddr_in cin){link_t* pL;if(sendto…...

【计算机网络】基本概念
基本概念 IP 地址端口号协议协议分层封装分用客户端服务器请求和响应两台主机之间的网络通信流程 IP 地址 概念:IP 地址主要是用于唯一标识网络主机、其他网络设备(如路由器)的网络地址。简单来说,IP地址用来唯一定位主机。格式&…...

Redis入门到实战-第七弹
Redis实战热身Sets篇 完整命令参考官网 官网地址 声明: 由于操作系统, 版本更新等原因, 文章所列内容不一定100%复现, 还要以官方信息为准 https://redis.io/Redis概述 Redis是一个开源的(采用BSD许可证),用作数据库、缓存、消息代理和流…...
图像处理学习笔记(一)
本文主要介绍,以供读者能够理解该技术的定义、原理、应用。 🎬个人简介:一个全栈工程师的升级之路! 📋个人专栏:ISP处理 🎀CSDN主页 发狂的小花 🌄人生秘诀:学习的本质就…...
duckdb学习-1
DuckDB is a fast in-process analytical database DuckDB supports a feature-rich SQL dialect complemented with deep integrations into client APIs 在notebook中使用duckdb 安装 pip install duckdb 示例代码: #> pip install jupysql #> pip install duckdb-en…...
GEE高阶案例——Landsat/Sentinel/MODIS影像进行缨帽变换一行代码实现
本教程的主要目的是利用eemont中的tasseledCap()的函数进行缨帽变换实现。 在 eemont 中,可使用扩展到 ee.Image 和 ee.ImageCollection 对象的 tasseledCap 方法计算缨帽亮度、绿度和湿度组件。只需从支持的平台加载图像,然后使用 tasseledCap 添加分量带即可。 代码: !p…...
数独游戏(c++题解)
题目描述 给出一个的表格,部分格子已经填好数。请填完所有空白格子,使得表格每一行、每一列、每个的九宫格,都恰好填满这9个数字。 输入格式 9行9列的方阵状态,0代表空格。 输出格式 输出完成后的方阵状态,每一个…...
【开发方案】Android 应用双卡搜网功能
一、功能简介 需求:开机自动开始搜网并显示网络列表 那么就不能将相关类做成单例,不能将subId、phoneId等卡相关的属性作为UI、服务的全局变量。 二、流程设计 NetworkSelectReceiver:监听开机广播,触发拉起搜网服务 NetworkOperatorService:搜网服务,完成后调起用户…...

铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...

P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...

(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...