当前位置: 首页 > news >正文

【SpringBoot项目】SpringBoot+MyBatis+MySQL电脑商城

在b站听了袁老师的开发课,做了一点笔记。

01-项目环境搭建_哔哩哔哩_bilibili

基于springboot框架的电脑商城项目(一)_springboot商城项目_失重外太空.的博客-CSDN博客

项目环境搭建

1.项目分析

1.项目功能:登录、注册、热销商品、用户管理(密码、个人信息、头像、收货地址)、购物车(展示、增加、删除) 、订单模块。
2.开发顺序:注册、登录、用户管理、购物车、商品、订单模块。
3.某一个模块的开发

  • 持久层开发:依据前端页面的设置规划相关的SQL语句,以及进行配置
  • 业务层开发:核心功能控制、业务操作以及异常的处理
  • 控制层开发: 接受请求、处理响应
  • 前端开发: JS、Query、AJAX这些技术来连接后台

2.开发环境

  • JDK: 1.8版本及以上的版本
  • maven:配置到idea,3.6.1版本
  • 数据库: MariaDB、MySQL,要求是5.1及以上的版本
  • 开发的平台: idea开发

3.搭建项目

1.项目名称:store

2.结构:com.cy.store

java web

mybatis

mysql driver

3.资源文件:resource文件夹下(static放静态资源、templates模板)

4.单元测试:test.com.cy.store

5.在properties文件中配置数据的连接源信息

spring.datasource.url=jdbc:mysql://localhost:3306/store?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=root

6.创建一个store数据库

create database store character set utf8;

7.测试连接:

  • 启动SpringBoot主类,是否有对应的Spring图形输出
  • 在单元测试类中测试数据库的连接是否可以正常的加载

数据库连接池:
1.DBCP
2.C3P0
3.Hikari: 管理数据库的连接对象

8.访问项目的静态资源是否可以正常的加载。所有的静态资源复制static目录下。

注意:idea对于JS代码的兼容性较差,编写了js代码可能不能正常加载。五种解决:在项目的maven下clear清理项目、install重新部署;在项目的file选项下 cash清理缓存;重新构建项目:build选项下 rebuild选项;重启idea;重启电脑。

用户注册

1.创建数据表

CREATE TABLE t_user (uid INT AUTO_INCREMENT COMMENT '用户id',username VARCHAR(20) NOT NULL UNIQUE COMMENT '用户名',password CHAR(32) NOT NULL COMMENT '密码',salt CHAR(36) COMMENT '盐值',phone VARCHAR(20) COMMENT '电话号码',email VARCHAR(30) COMMENT '电子邮箱',gender INT COMMENT '性别:0-女,1-男',avatar VARCHAR(50) COMMENT '头像',is_delete INT COMMENT '是否删除:0-未删除,1-已删除',created_user VARCHAR(20) COMMENT '日志-创建人',created_time DATETIME COMMENT '日志-创建时间',modified_user VARCHAR(20) COMMENT '日志-最后修改执行人',modified_time DATETIME COMMENT '日志-最后修改时间',PRIMARY KEY (uid)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

2.创建用户的实体类

2.1通过表的结构提取表的公共字段,放在实体类的基类中

public class baseEntity implements Serializable {private String createdUser;private Date createdTime; //import java.util.Dataprivate String modifiedUser;private Date modifiedTime;//再手动声明get、set方法,equals() and hashCode();toString();}

为什么要用implements Serializable:实体类User因为要在网络中以流的形式传输,所以需要serialize序列化(为什么要用implements Serializable_IT_wjj的博客-CSDN博客)

2.2创建用户的实体类,需要继承baseEntity基类

public class User extends baseEntity implements Serializable {private Integer uid;private String username;private String password;private String salt;private String phone;private String email;private Integer gender;private String avatar;private Integer isDelete;//再手动声明get、set方法,equals() and hashCode();toString();
}

任何实体类都要:get和set方法、equals()和hashCode()、toString()

3.注册-持久层

通过MyBatis来操作数据库。在做mybatis开发的流程。

3.1规划需要执行的SQL语句

1.用户的注册功能,相当于在做数据的插入操作。

insert into t_user (username, password) values (值列表)

2.在用户注册时首先查询当前用户名是否存在,如果存在则不能注册,相当于一条查询语句。

select * from t_user where username=?

3.2设计接口和抽象方法

1.定义Mapper接口。在项目的目录结构下创建一个mapper包,在这个包下根据不同的功能模块创建mapper接口。创建UserMapper的接口(interface)。要在接口中定义这两个SQL语句的抽象方法。

package com.cy.store.mapper;
import com.cy.store.entity.User;/** 处理用户数据操作的持久层接口 */
public interface UserMapper {/*** 插入用户数据* @param user 用户数据* @return 受影响的行数(在增删改都有受影响的行数作为返回值,可以根据返回值来判断是否执行成功)*/Integer insert(User user);/*** 根据用户名查询用户数据* @param username 用户名* @return 找到对应的用户数据则返回用户的数据,如果没有找到的数据则返回null*/User findByUsername(String username);
}

2.在启动类配置mapper接口文件的位置

//MapperScan注解指定当前项目中的Mapper接口路径的位置,在项目启动的时候会自动加载所有的接口。

@MapperScan("com.cy.store.mapper")

package com.cy.store;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.unit.DataSize;
import org.springframework.util.unit.DataUnit;import javax.servlet.MultipartConfigElement;@Configuration
@SpringBootApplication
@MapperScan("com.cy.store.mapper")
public class StoreApplication {public static void main(String[] args) {SpringApplication.run(StoreApplication.class, args);}@Beanpublic MultipartConfigElement getMultipartConfigElement() {MultipartConfigFactory factory = new MultipartConfigFactory();// DataSize dataSize = DataSize.ofMegabytes(10);// 设置文件最大10M,DataUnit提供5中类型B,KB,MB,GB,TBfactory.setMaxFileSize(DataSize.of(10, DataUnit.MEGABYTES));factory.setMaxRequestSize(DataSize.of(10, DataUnit.MEGABYTES));// 设置总上传数据总大小10Mreturn factory.createMultipartConfig();}
}

3.3编写映射

1.定义xml映射文件,与对应的接口进行关联。所有映射文件属于资源文件,需要放在resource目录结构下,在这个目录下创建一个mapper文件夹(Directory),然后在这个文件夹下存放mapper的映射文件。

2.创建接口对应的映射文件,遵循和接口的名称保持一致即可。创建一个UserMapper.xml文件(file)

namespace的属性:用于指定当前的映射文件和那个接口进行映射,需要指定接口的文件路径,需要标注包的完整路径结构。

<?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.cy.store.mapper.UserMapper"><resultMap id="UserEntityMap" type="com.cy.store.entity.User"><id column="uid" property="uid"/><result column="is_delete" property="isDelete"/><result column="created_user" property="createdUser"/><result column="created_time" property="createdTime"/><result column="modified_user" property="modifiedUser"/><result column="modified_time" property="modifiedTime"/></resultMap><!-- 插入用户数据:Integer insert(User user) --><insert id="insert" useGeneratedKeys="true" keyProperty="uid">INSERT INTOt_user (username, password, salt, phone, email, gender, avatar, is_delete, created_user, created_time, modified_user, modified_time)VALUES(#{username}, #{password}, #{salt}, #{phone}, #{email}, #{gender}, #{avatar}, #{isDelete}, #{createdUser}, #{createdTime}, #{modifiedUser}, #{modifiedTime})</insert><!-- 根据用户名查询用户数据:User findByUsername(String username) --><select id="findByUsername" resultMap="UserEntityMap">SELECT*FROMt_userWHEREusername = #{username}</select></mapper>

3.配置接口中的方法对应上SQL语句。需要借助标签完成,insert/update/delete/selete,对应SQL语句的增删改查操作。

insert

  • id属性:表示映射的接口中方法的名称,直接在标签的内容部来编写SQL语句。
  • useGeneratedKeys属性:表示开启某个字段的值递增(主键设置为递增)
  • keyProperty属性:表示将表中的哪个字段作为主键进行递增。

select在执行的时候,查询的结果是一个对象、多个对象。

  • resultType表示查询的结果集类型,只需要指定对应映射的类的类型,并且包含完整的包接口。resultType="com.cy.store.entity.User"。这种要求表的字段名字和类属性的名字一模一样。
  • resultMap表示当表的字段和类的对象属性的字段名称不一致时,来自定义查询结果集的映射规则。resultMap id属性表示给映射规则分配唯一的id值,对应resultMap="id属性的值"属性的取值。type属性取值是一个类,表示的是数据库中的查询结果与java中的哪个实体类进行结果集的映射,将表的字段和类的属性不一致的字段进行匹配指定,名称一致的字段可以省略不写。column属性:表示表中的字段名称;proprerty属性:表示类中的属性名称。column属性、proprerty属性配合完成名称不一致的映射。在定义映射规则时,主键是不可以省略的

4.将mapper文件的位置注册到properties对应的配置文件中。(固定写法)

mybatis.mapper-locations=classpath:mapper/*.xml

5.单元测试:每个独立的层编写完毕后需要编写单元测试方法,来测试当前的功能。在test包结构下创建一个mapper包,在这个包下在创建持久层的功能测试。

@SpringBootTest:表示标注当前的类是一个测试类,不会随同项目一块打包发送。

@RunWith(SpringRunner.class):表示启动这个单元测试类(如果不写-单元测试类是不能运行的),需要传递一个固定的参数,必须是SpringRunner的实例类型。

单元测试方法(可以单独的独立运行,不用启动整个项目,可以做单元测试,提升了代码的测试效率必须被@Test注解所修饰,返回值类型必须是void,方法的参数列表不能指定任何类型,方法的访问修饰符必须是public。

package com.cy.store.mapper;import com.cy.store.entity.User;
import com.cy.store.mapper.UserMapper;
import org.junit.Test;//记住
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.text.SimpleDateFormat;
import java.util.Date;// @RunWith(SpringRunner.class)注解是一个测试启动器,可以加载Springboot测试注解
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTests {//idea有检测的功能,接口是不能直接创建Bean的(动态代理技术来解决)@Autowiredprivate UserMapper userMapper;@Testpublic void insert() {User user = new User();user.setUsername("user05");user.setPhone("12345678910");Integer rows = userMapper.insert(user);System.out.println("rows=" + rows);}@Testpublic void findByUsername() {String username = "user02";User result = userMapper.findByUsername(username);System.out.println(result);}
}

4.注册-业务层

4.1规划异常

1.RuntimeException异常,作为这个异常的子类,再去定义具体的异常类型来继承这个异常。业务层异常的基类ServiceException,这个异常继承RuntimeException异常。异常机制就建立起来了。

Alt+insert --override methods 

package com.cy.store.service.ex;/** 业务异常的基类 */
public class ServiceException extends RuntimeException {public ServiceException() {super();}public ServiceException(String message) {super(message);}public ServiceException(String message, Throwable cause) {super(message, cause);}public ServiceException(Throwable cause) {super(cause);}protected ServiceException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {super(message, cause, enableSuppression, writableStackTrace);}
}

根据业务层不同的业务功能来详细定义具体异常类型,统一去继承ServiceException。

2.用户在进行注册的时候可能会产生用户名被占用的错误,抛出一个异常:UsernameDuplicatedException

3.正在执行数据插入操作的时候,服务器宕机、数据库宕机。处于正在执行插入的过程中所产生的异常:InsertException异常。

4.2设计接口和抽象方法

1.在service包下创建一个IUserService接口(interface)。

package com.cy.store.service;
import com.cy.store.entity.User;/** 处理用户数据的业务层接口 */
public interface IUserService {/*** 用户注册* @param user 用户数据的对象*/void reg(User user);
}

@Service注解:将当前类的对象交给Spring来管理,自动创建对象以及对象的维护。

2.创建一个实现类UserServiceImpl类,需要实现这个接口,并且实现抽象的方法。

package com.cy.store.service.impl;import java.util.UUID;
import com.cy.store.entity.User;
import com.cy.store.mapper.UserMapper;
import com.cy.store.service.IUserService;
import com.cy.store.service.ex.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;import java.util.Date;/** 处理用户数据的业务层实现类 */
@Service
public class UserServiceImpl implements IUserService {@Autowiredprivate UserMapper userMapper;@Overridepublic void reg(User user) {// 根据参数user对象获取注册的用户名String username = user.getUsername();// 调用持久层的User findByUsername(String username)方法,根据用户名查询用户数据User result = userMapper.findByUsername(username);// 判断查询结果是否不为nullif (result != null) {// 是:表示用户名已被占用,则抛出UsernameDuplicateException异常throw new UsernameDuplicateException("尝试注册的用户名[" + username + "]已经被占用");}// 创建当前时间对象Date now = new Date();// 补全数据:加密后的密码。盐值是一个随机的字符串。String salt = UUID.randomUUID().toString().toUpperCase();String md5Password = getMd5Password(user.getPassword(), salt);user.setPassword(md5Password);// 补全数据:盐值user.setSalt(salt);// 补全数据:isDelete(0)user.setIsDelete(0);// 补全数据:4项日志属性user.setCreatedUser(username);user.setCreatedTime(now);user.setModifiedUser(username);user.setModifiedTime(now);// 表示用户名没有被占用,则允许注册// 调用持久层Integer insert(User user)方法,执行注册并获取返回值(受影响的行数)Integer rows = userMapper.insert(user);// 判断受影响的行数是否不为1if (rows != 1) {// 是:插入数据时出现某种错误,则抛出InsertException异常throw new InsertException("添加用户数据出现未知错误,请联系系统管理员");}}/*** 执行密码加密* @param password 原始密码* @param salt 盐值* @return 加密后的密文*/private String getMd5Password(String password, String salt) {/** 加密规则:* 1、无视原始密码的强度* 2、使用UUID作为盐值,在原始密码的左右两侧拼接* 3、循环加密3次*/for (int i = 0; i < 3; i++) {password = DigestUtils.md5DigestAsHex((salt + password + salt).getBytes()).toUpperCase();}return password;}}

3.在单元测试包下创建一个UserServiceTests类,在这个类中添加单元测试功能。

package com.cy.store.service;import com.cy.store.entity.User;
import com.cy.store.service.ex.ServiceException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTests {@Autowiredprivate IUserService iUserService;@Testpublic void reg() {try {User user = new User();user.setUsername("lower");user.setPassword("123456");iUserService.reg(user);System.out.println("注册成功!");} catch (ServiceException e) {//获取类的对象,再获取类的名称System.out.println("注册失败!" + e.getClass().getSimpleName());//获取异常的具体描述信息System.out.println(e.getMessage());}}
}

5.注册-控制层

接收请求和处理响应。

5.1创建响应

状态码、状态描述信息、数据。这部分功能封装在一个类中,将这个类作为方法的返回值,返回给前端浏览器。

package com.cy.store.util;
import java.io.Serializable;/*** 响应结果类* Json格式的数据进行相应* @param <E> 响应数据的类型*/
public class JsonResult<E> implements Serializable {/** 状态码 */private Integer state;/** 状态描述信息 */private String message;/** 数据 */private E data;public JsonResult() {super();}public JsonResult(Integer state) {super();this.state = state;}/** 出现异常时调用 */public JsonResult(Throwable e) {super();// 获取异常对象中的异常信息this.message = e.getMessage();}public JsonResult(Integer state, E data) {super();this.state = state;this.data = data;}public Integer getState() {return state;}public void setState(Integer state) {this.state = state;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public E getData() {return data;}public void setData(E data) {this.data = data;}
}

5.2设计请求

依据当前的业务功能模块进行请求的设计。

  • 请求路径:/users/reg
  • 请求参数:User user
  • 请求类型:POST(有敏感数据)、GET
  • 请求结果:JsonResult<void>

5.3处理请求

创建一个控制层对应的UserController类,依赖于业务层的接口。

/** 处理用户相关请求的控制器类 */
@RestController
@RequestMapping("users")
public class UserController extends BaseController {@Autowiredprivate IUserService userService;/*@RequestMapping("reg")public JsonResult<Void> reg(User user) {// 调用业务对象执行注册userService.reg(user);// 返回return new JsonResult<Void>(OK);}*/@RequestMapping("reg")public JsonResult<Void> reg(User user) {// 创建返回值(创建响应结果对象)JsonResult<Void> result = new JsonResult<Void>();try {// 调用业务对象执行注册userService.reg(user);// 响应成功result.setState(200);} catch (UsernameDuplicateException e) {// 用户名被占用result.setState(4000);result.setMessage("用户名已经被占用");} catch (InsertException e) {// 插入数据异常result.setState(5000);result.setMessage("注册失败,请联系系统管理员");}return result;}
}

 @RestController

@RestController 详解_换个角度看代码的博客-CSDN博客

@RestController是@controller和@ResponseBody 的结合

@Controller 将当前修饰的类注入SpringBoot IOC容器,使得从该类所在的项目跑起来的过程中,这个类就被实例化。
@ResponseBody 它的作用简短截说就是指该类中所有的API接口返回的数据,甭管你对应的方法返回Map或是其他Object,它会以Json字符串的形式进行数据的响应给到前端。

@RequestMapping注解能将请求和处理请求的控制器方法关联起来,建立映射关系。

SpringMvc---@RequestMapping注解和它的属性_@requestmapping 定义数组_妙Lin的博客-CSDN博客

5.4控制层优化设计

在控制层抽离一个父类,在这个父类中统一的处理关于异常的操作。编写BaseController类统一处理异常。

@ExceptionHandler 用于统一处理抛出的异常

/** 控制器类的基类 */
public class BaseController {/** 操作成功的状态码 */public static final int OK = 200;/** @ExceptionHandler用于统一处理方法抛出的异常 *///请求处理方法,这个方法的返回值就是需要传递给前端的数据//自动将异常对象传递给此方法的参数列表上//当项目中产生了异常,会被统一拦截到此方法中,这个方法此时充当请求处理方法,方法的返回值直接给到前端@ExceptionHandler({ServiceException.class, FileUploadException.class})public JsonResult<Void> handleException(Throwable e) {JsonResult<Void> result = new JsonResult<Void>(e);if (e instanceof UsernameDuplicateException) {result.setState(4000);} } else if (e instanceof InsertException) {result.setState(5000);}return result;}
}

重新构建了reg()方法。

@RequestMapping("reg")public JsonResult<Void> reg(User user) {// 调用业务对象执行注册userService.reg(user);// 返回return new JsonResult<Void>(OK);}

6.注册-前端页面

1.在\store\src\main\resources\static\web\register.html页面编写发送请求的方法,点击事件来完成,先选中对应的按钮($(“选择器”)),再去添加点击事件,$.ajax()函数发送异步请求。

2.JQuery封装了一个函数,称之为$.ajax()函数,通过对象调用ajax()函数,可以异步加载相关的请求。依靠的是JavaScript提供的一个对象XHR(XmlHttpResponse),封装了这个对象。

3.ajax()使用方式。需要传递一个方法体作为方法的参数来使用,一对大括号称之为方法体,ajax接收多个参数,参数与参数之间要求使用英文逗号分割,每一组参数之间使用英文冒号分割,参数的组成部分是参数名称(不能随意定义)和参数的值(要求使用字符串来表示"双引号引起来"),参数的声明顺序没有要求。语法结构:

$.ajax(fun());

function fun(){

        //TODO

}

$.ajax({url:"",type:"",data:"",   dataType:"",success:function(){},error:function(){},
});

4. ajax()函数参数的含义: 

参数功能描述
url标识请求的地址(url地址),不能包含参数列表部分的内容。例如:url:"localhost:8080/users/reg"
type请求的类型(GET、POST)。例如:type:"POST"
data向指定请求url地址提交的数据。例如:data:"username=tom&pwd=123"
dataType提交数据的类型。数据类型一般指定为json类型。dataType:"json"

success

当服务器正常响应客户端是,会自动调用success参数的方法,并将服务器返回的数据以参数的形式传递给这个方法的参数上

error

当服务器未正常响应客户端是,会自动调用error参数的方法,并将服务器返回的数据以参数的形式传递给这个方法的参数上

5.js代码可以独立存放在一个后缀为js的文件里,或者声明在一个script标签中。

<script type="text/javascript">//1.监听注册按钮是否被点击,如果被点击可以执行一个方法$("#btn-reg").click(function() {//麻烦 动态获取表单中控件的数据//麻烦 let username = $("#username").val();//麻烦 let pwd = $("#password").val(); //console.log($("#from-reg").serialize());//输出表单看看       //2.发送ajax()的异步请求来完成用户的注册功能$.ajax({url: "/users/reg",type: "POST",data: $("#form-reg").serialize(),//麻烦 data: "username="+username+"&password="+pwd,dataType: "json",success: function(json) {if (json.state == 200) {alert("注册成功!");// location.href = "login.html";} else {alert("注册失败!" + json.message);}}error: function(xhr){alert("注册时产生未知错我!" + xhr.status);}});});
</script>

6.js代码无法正常被服务器解析执行,体现在点击页面中的按钮没有任何响应,解决方案:

  • 在项目的maven下clear清理项目、install重新部署
  • 在项目的file选项下 cash清理缓存
  • 重新构建项目:build选项下 rebuild选项
  • 重启idea
  • 重启电脑



PostMapping和GetMapping区别

PostMapping和GetMapping区别,使用场景个人理解_BACKLS的博客-CSDN博客

相关文章:

【SpringBoot项目】SpringBoot+MyBatis+MySQL电脑商城

在b站听了袁老师的开发课&#xff0c;做了一点笔记。 01-项目环境搭建_哔哩哔哩_bilibili 基于springboot框架的电脑商城项目&#xff08;一&#xff09;_springboot商城项目_失重外太空.的博客-CSDN博客 项目环境搭建 1.项目分析 1.项目功能&#xff1a;登录、注册、热销…...

互联网医院|互联网医院系统引领医疗科技新风潮

互联网的迅速发展已经改变了人们的生活方式&#xff0c;而医疗领域也不例外。近年来&#xff0c;互联网医院应运而生&#xff0c;为患者和医生提供了更便捷、高效的医疗服务。本文将深入探讨互联网医院的系统特点、功能以及未来的发展方向&#xff0c;为您展现医疗行业的新时代…...

Mock安装及应用

1、安装 npm install mockjs 2、Mock.Random属性 该属性是一个工具类&#xff0c;用于生成各种随机数据。它提供的方法如下&#xff1a; Basic: boolean,natural,integer,float,character,string,range,date,time,datetime,now; Image: image,dataImage; Color: color; Text: p…...

一起来看看UI设计流程详解吧!通俗易懂

UI设计2023 通俗易懂的UI设计流程详解 首先&#xff0c;大家要明确一下范围&#xff1a;一般分为新产品的从0-1和已有产品上新的模块或功能的从0-1&#xff0c;这两个方向的环节和产出物会有比较大的区别。其实在UI设计师介入之前&#xff0c;我们是需要去了解一些大的方向和…...

TikTok营销成功秘籍:ROI指标的黄金法则

在当今数字营销领域&#xff0c;TikTok已经崭露头角&#xff0c;成为了品牌和营销者们争相追逐的热门平台。 然而&#xff0c;要在TikTok上取得成功&#xff0c;不仅需要创意和内容&#xff0c;还需要精确的ROI&#xff08;投资回报率&#xff09;指标来衡量和优化你的营销策略…...

17.适配器模式(Adapter)

意图&#xff1a;将一个类的接口转换为Client希望的另一个接口&#xff0c;使得原本由于接口不兼容而不能一起工作的那些类在一起工作。 UML图 Target&#xff1a;定义Client使用的与特定领域相关的接口。 Client&#xff1a;与符合Target接口的对象协同工作。 Adaptee&#xf…...

leetcode做题笔记154. 寻找旋转排序数组中的最小值 II

已知一个长度为 n 的数组&#xff0c;预先按照升序排列&#xff0c;经由 1 到 n 次 旋转 后&#xff0c;得到输入数组。例如&#xff0c;原数组 nums [0,1,4,4,5,6,7] 在变化后可能得到&#xff1a; 若旋转 4 次&#xff0c;则可以得到 [4,5,6,7,0,1,4]若旋转 7 次&#xff0…...

什么是推挽电路?

推挽电路原理&#xff1a; 可以简单理解为推和拉&#xff1b; 此电路总共用到两个元器件&#xff0c;对应图中的Q1----NPN三极管&#xff0c;Q2----PNP三极管&#xff0c;两个电阻R1和R2起到限流的作用&#xff1b;两个三极管的中间对应信号的输出。 下面就举例说明是如何工作的…...

208.Flink(三):窗口的使用,处理函数的使用

目录 一、窗口 1.窗口的概念 2.窗口的分类 (1)按照驱动类型分 (2)按照窗口分配数据的规则分类 3.窗口api概览 (1)按键分区(Keyed)和非按键分区(Non-Keyed) *1)按键分区窗口(Keyed Windows) *2)非按键分区(Non-Keyed Windows) (2)代码中窗口API的调…...

时序预测 | MATLAB实现POA-CNN-BiLSTM鹈鹕算法优化卷积双向长短期记忆神经网络时间序列预测

时序预测 | MATLAB实现POA-CNN-BiLSTM鹈鹕算法优化卷积双向长短期记忆神经网络时间序列预测 目录 时序预测 | MATLAB实现POA-CNN-BiLSTM鹈鹕算法优化卷积双向长短期记忆神经网络时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 MATLAB实现POA-CNN-BiLSTM鹈鹕算…...

【知识点】增量学习、在线学习、离线学习的区别

参考链接&#xff1a;https://www.6aiq.com/article/1613258706447?p1&m0 离线学习 常见的学习方式&#xff0c;一次性将所有数据参与进训练。 离线学习完成了目标函数的优化将不会在改变了离线学习需要一次提供整个训练集时间和空间成本效率低发生数据变更或模型漂移需…...

c++ 学习 之 运算符重载 之 前置++和后置++

前言 int a1;cout << (a) << endl;cout << a << endl;int b1;cout << (b) << endl; // 这个是错误的cout << b << endl;上面样例中&#xff0c; 前置 返回的是引用&#xff0c;所以a 的值变成了3 后置 返回的不是可以改变的…...

K8s Kubelet 垃圾回收机制

前言 Kubelet 垃圾回收(Garbage Collection)是一个非常有用的功能,它负责自动清理节点上的无用镜像和容器。Kubelet 每隔 1 分钟进行一次容器清理,每隔 5 分钟进行一次镜像清理(截止到 v1.15 版本,垃圾回收间隔时间还都是在源码中固化的,不可自定义配置)。如果节点上已…...

docker安装高斯数据库openGauss数据库

1.创建容器 #创建数据没有挂在的容器 docker run --name opengauss --privilegedtrue -d -e GS_PASSWORDEnmo123 -p 8090:5432 enmotech/opengauss:latest 2. 进入容器&#xff0c;并切换omm用户&#xff0c;使用gsql连接高斯数据库 [rootansible ~]# docker ps -a CONTAIN…...

新手学习:ArcGIS 提取SHP 路网数据、节点

新手学习&#xff1a;ArcGIS 提取SHP 路网数据、节点 参考连接 OSM路网提取道路节点 ArcGIS&#xff1a;如何创建地理数据库、创建要素类数据集、导入要素类、表&#xff1f; 1. 导入开源路网SHP文件 2. 在交点处打断路网数据 未打断路网数据 有一些路径很长&#xff0c;…...

性能测试 —— Tomcat监控与调优:Jconsole监控

JConsole的图形用户界面是一个符合Java管理扩展(JMX)规范的监测工具&#xff0c;JConsole使用Java虚拟机(Java VM)&#xff0c;提供在Java平台上运行的应用程序的性能和资源消耗的信息。在Java平台&#xff0c;标准版(Java SE平台)6&#xff0c;JConsole的已经更新到目前的外观…...

刷题笔记26——图论二分图判定

世界上的事情,最忌讳的就是个十全十美,你看那天上的月亮,一旦圆满了,马上就要亏厌;树上的果子,一旦熟透了,马上就要坠落。凡事总要稍留欠缺,才能持恒。 ——莫言 visited数组是在如果有环的情况下&#xff0c;防止在图中一直绕圈设置的&#xff0c;类似于剪枝操作&#xff0c;走…...

网站整站优化-网站整站优化工具

您是否曾为您的网站在搜索引擎中的排名而感到焦虑&#xff1f;是否苦苦思考如何提高流量、吸引更多用户&#xff1f; 什么是整站优化。简而言之&#xff0c;它是一项用于提升网站在搜索引擎中排名的策略和技巧。通过对网站的内容、结构、速度等方面进行优化&#xff0c;可以使…...

冲刺十五届蓝桥杯P0001阶乘求和

文章目录 题目描述思路分析代码解析 题目描述 思路分析 阶乘是蓝桥杯中常考的知识。 首先我们需要知道 int 和long的最大值是多少。 我们可以知道19的阶乘就已经超过了long的最大值&#xff0c;所以让我们直接计算202320232023&#xff01;的阶乘是不现实的。 所以我们需要…...

c++ 学习 之 运算符重载

前言 运算符重载的概念&#xff1a; 对已有的运算符重新进行定义&#xff0c;赋予其另外一种功能&#xff0c;以适应不同的数据类型 加号运算符重载 作用&#xff1a;定义两个自定义的数据类型相加的运算 正常情况下&#xff0c;如果想要实现类中两个int 类型的相加&#xf…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

分布式增量爬虫实现方案

之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面&#xff0c;避免重复抓取&#xff0c;以节省资源和时间。 在分布式环境下&#xff0c;增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路&#xff1a;将增量判…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

MySQL:分区的基本使用

目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区&#xff08;Partitioning&#xff09;是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分&#xff08;分区&#xff09;可以独立存储、管理和优化&#xff0c;…...

通过MicroSip配置自己的freeswitch服务器进行调试记录

之前用docker安装的freeswitch的&#xff0c;启动是正常的&#xff0c; 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...