企业网站哪个好/做销售最挣钱的10个行业
写在前面
本人开发的框架在2021年年初开发完成,后面没有再做过任何维护和修改。是仅供大家参考交流的学习项目,请勿使用在生产环境,也勿用作商业用途。
框架地址:
https://github.com/yijiebaiyi/fast_framework
整体思路
开发一款web框架,首先要考虑这个框架的整体运行架构,然后具体到那些功能的扩展。那么我开发框架的时候想的是,精简为主,实用为主。主要功能需要包括入口文件、路由解析、异常处理、日志记录、ORM、缓存、类依赖注入。
入口文件
入口文件需要定义全局变量,主要是核心框架文件的所在路径,然后,通过include_once引入框架核心类文件,初始化框架进行初始化操作。
<?phpdefine("FAST_PATH", $_SERVER["DOCUMENT_ROOT"] . DIRECTORY_SEPARATOR . "fast");// 初始化
include_once FAST_PATH . DIRECTORY_SEPARATOR . "App.php";
(new \fast\App())->init();
应用核心类
应用核心类主要是用来注册类的自动加载、加载环境变量文件、注册错误异常以及注册路由。下面是应用初始化init方法。
public function init(){if (false === $this->isInit) {define("DOCUMENT_ROOT", $_SERVER["DOCUMENT_ROOT"]);define("ROOT_PATH", $_SERVER["DOCUMENT_ROOT"]);define("RUNTIME_PATH", $_SERVER["DOCUMENT_ROOT"] . DIRECTORY_SEPARATOR . "runtime");define("APP_PATH", $_SERVER["DOCUMENT_ROOT"]);// 注册自动加载require_once FAST_PATH . DIRECTORY_SEPARATOR . "Autoload.php";(new Autoload())->init();// 注册配置(new Config())->init();// 加载env(new Env())->init();// 注册错误和异常(new Exception())->init();(new Error())->init();(new Shutdown())->init();// 检验运行环境$this->validateEnv();// 注册路由(new Route())->init();$this->isInit = true;}}
上面初始化的方法中,我们需要先判断框架是否已经初始化,如果已经初始化则不需要再进行操作了。init方法中所涉及到的类都在框架核心文件根目录下面,需要注意的是,一定要先注册自动加载,不然使用new 关键字生成对象就会报错。下面是自动加载类的自动加载方法。
public function init(){if (false === $this->isInit) {spl_autoload_register(array($this, 'autoload'));$this->isInit = true;}}/*** @var array 类加载次*/private static array $loadedClassNum = [];/*** 自动加载* @param $name* @throws Exception*/public static function autoload($name): void{if (trim($name) == '') {throw new Exception("No class for loading");}$file = self::formatClassName($name);if (isset(self::$loadedClassNum[$file])) {self::$loadedClassNum[$file]++;return;}if (!$file || !is_file($file)) {return;}// 导入文件include $file;if (empty(self::$loadedClassNum[$file])) {self::$loadedClassNum[$file] = 1;}}/*** 返回全路径* @param $className* @return string*/private static function formatClassName($className): string{return $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . $className . '.php';}
使用PHP提供的spl_autoload_register自动加载器函数,注册autoload方法实现自动加载,可以看到我们自动加载的类必须都在项目根目录下才可以实现。这是一个简单的约定。
加载配置
我们知道php使用include 导入文件是可以获取到文件的返回值的(如果有的话),所以使用php文件返回一个数组来实现项目的配置文件,框架里面支持默认的config.php文件,以及额外用户可以自定义的配置:extra.php。这个也是我们约定好的。
配置文件示例代码config.php:
<?phpreturn ["Cache" => ["default" => "redis","redis" => ["master" => ["pconnect" => false,"host" => "localhost","port" => 6379,"timeout" => 0,],],],"Log" => ["default" => "file","file" => ["path" => RUNTIME_PATH],]
];
引入配置文件的关键代码:
/*** 加载配置* @param $filename*/private static function addConfig($filename): void{$configArr = include_once($filename);if (is_array($configArr)) {self::$configs = Arr::arrayMergeRecursiveUnique(self::$configs, $configArr);}}/*** 导入配置* @param $paths*/private static function importConfig($paths): void{foreach ($paths as $path) {self::addConfig($path);}}
加载环境变量
环境变量文件,我们默认的就是项目根目录的.env文件。.env文件配置项是标准的*.ini类型配置文件的书写方式,且.env文件里面的配置项不区分大小写,小写配置项最终会被转化成大写。.env文件的加载使用php的函数parse_ini_file来实现:
/*** 加载环境变量定义文件* @param string $file 环境变量定义文件* @return void*/public static function load(string $file): void{$env = parse_ini_file($file, true) ?: [];static::set($env);}
框架支持环境变量的写入、读取和检测。
错误和异常
异常信息抓取到之后,我们将他格式化处理,主要记录异常码、异常文件和所在行号。然后将异常写入日志。(注意,如果是生产模式,需要关闭错误显示)
public static function handler($exception){// 设置http状态码,发送headerif (in_array($exception->getCode(), array_keys(Http::$httpStatus))) {self::$httpCode = $exception->getCode();} else {self::$httpCode = 500;}Http::sendHeader(self::$httpCode);// 异常信息格式化输出$echoExceptionString = "<b>message</b>: {$exception->getMessage()}<br/>" ."<b>code</b>: {$exception->getCode()}<br/>" ."<b>file</b>: {$exception->getFile()}<br/>" ."<b>line</b>: {$exception->getLine()}<br/>";$serverVarDump = Str::dump(false, $_SERVER);$postVarDump = Str::dump(false, $_POST);$filesVarDump = Str::dump(false, $_FILES);$cookieVarDump = Str::dump(false, $_COOKIE);$logExceptionString = "message: {$exception->getMessage()}" . PHP_EOL ."code: {$exception->getCode()}" . PHP_EOL ."file: {$exception->getFile()}" . PHP_EOL ."line: {$exception->getLine()}" . PHP_EOL ."\$_SERVER: {$serverVarDump}" . PHP_EOL ."\$_POST: {$postVarDump}" . PHP_EOL ."\$_COOKIE: {$cookieVarDump}" . PHP_EOL ."\$_FILES: {$filesVarDump}";Log::write($logExceptionString, Log::ERROR);// debug模式将错误输出if (static::isDebugging()) {if (self::$isJson) {echo Json::encode(["message" => $exception->getMessage(), "code" => 0]);App::_end();} else {echo $echoExceptionString;}}}
路由分发
路由的实现思路是:我们根据请求的地址,截取到请求的路径信息(根据PHP全局变量$_SERVER[‘PATH_INFO’]获取),根据路径信息的格式,定位到某个控制器类的某个方法,然后将其触发。实现代码:
public function distribute(){// 解析path_infoif (isset($_SERVER['PATH_INFO'])) {$url = explode('/', trim($_SERVER['PATH_INFO'], "/"));if (count($url) < 3) {$url = array_pad($url, 3, "index");}} else {$url = array_pad([], 3, "index");}// 获取类名和方法名$className = self::formatClassName($url);$actionName = self::formatActionName($url);if (!class_exists($className)) {throw new Exception("the controller is not exist: {$className}", 404);}$class = new $className();if (!is_callable([$class, $actionName])) {throw new Exception("the action is not exist: {$className} -> {$actionName}", 404);}if (!$class instanceof Controller) {throw new Exception("the controller not belongs to fast\\Controller: {$className}", 403);}// 将请求分发$class->$actionName();}
实现缓存
框架中的缓存、日志、ORM都是使用适配器模式。即定义一个抽象类,抽象类中定义若干抽象方法。这样的话,继承了抽象类的方法必须要实现这些抽象方法。我们就可以通过统一的入口去根据配置去调用对应的适配器类了。
其中缓存适配了Redis、Memcache以及Memcached三种。开发者可以在config.php配置文件中自行配置。
缓存主要实现了将数据写入缓存和获取缓存数据两个方法,我们以redis为例,redis缓存主要是使用redis字符串存储结构,使用set和get方法来实现。
public function get($key, &$time = null, &$expire = null){$_key = $this->makeKey($key);$res = $this->slaveObj->get($_key);if (is_null($res) || false === $res) {return null;}$res = unserialize($res);if ($res && isset($res['value'])) {$time = $res['time'];$expire = $res['expire'];return $res['value'];}return null;}public function set($key, $value = null, $expire = 3600): bool{return $this->masterObj->set($this->makeKey($key), serialize($this->makeValue($value, $expire)), $expire);}
前面的代码只是适配器的实现,那么我们怎么调用适配器类中的方法呢。我这边想到的是,在框架核心代码根目录创建一个缓存文件类,实现一个单例,通过配置来读取我们要使用什么类型的缓存(即使用哪个适配器类),配置中配置项是缓存适配器类的类名称,读取到了我们就加载他。具体实现代码:
public static function instance($type = "default"): CacheDriver{if ($type === "default") {$_type = Config::get("Cache.default");} else {$_type = $type;}if (!$_type) {throw new Exception("The type can not be set to empty!");}if (!isset(self::$_instance[$_type])) {$conf = Config::get("Cache.{$_type}");if (empty($conf)) {throw new Exception("The '{$_type}' type cache config does not exists!");}$class = self::getNamespace() . "\\" . ucfirst($_type);$obj = new $class();if (!$obj instanceof CacheDriver) {throw new Exception("The '{$class}' not instanceof CacheDriver!");}$obj->init($conf);self::$_instance[$_type] = $obj;} else {$obj = self::$_instance[$_type];}return $obj;}
注:日志以及ORM的实现方法和缓存的实现类似,也是通过实现一个适配器,然后通过加载配置中定义的适配器类来加载。
实现完了之后我们测试一下:
设置:
$cacheObj = Cache::instance('redis');$setRes = $cacheObj->setModuleName("user")->set(["id" => 1], ["name" => "ZhangSan"], 1000);if ($setRes) {echo "设置成功";} else {echo "设置失败";}
获取:
$cacheObj = Cache::instance('redis');$res = $cacheObj->setModuleName("user")->get(["id" => 1], $time, $expire);var_dump($res, $time, $expire);
实现日志
日志的实现比较简单,主要值实现了日志的写入功能,通过php函数file_put_contents实现写入文件。当然也可以使用别的方法来实现。
相关代码:
public function write(string $message, string $type){if (empty($message)) {trigger_error('$message dose not empty! ');return false;}if (empty($type)) {trigger_error('$type dose not empty! ');return false;}$path = APP_PATH . DIRECTORY_SEPARATOR . 'runtime' . DIRECTORY_SEPARATOR . 'logs' . DIRECTORY_SEPARATOR . $type . '/' . date('Ym/d') . '.log';$mark = "\n\n===========================================================================\n";$mark .= 'time:' . date('Y/m/d H:i:s') . "\n";return \fast\util\File::write($mark . $message, $path, (FILE_APPEND | LOCK_EX));}
public static function write($content, $path, $flags = 0){$path = trim($path);if (empty($path)) {trigger_error('$path must to be set!');return false;}$dir = dirname($path);if (!self::exists($dir)) {if (false == self::mkdir($dir)) {trigger_error('filesystem is not writable: ' . $dir);return false;}}$path = str_replace("//", "/", $path);return file_put_contents($path, $content, ((empty($flags)) ? (LOCK_EX) : $flags));}
应用层调用:
Log::write("这是一条info类型的log", Log::INFO);
实现操作数据库
数据库目前只实现了Mysql,如果需要支持别的数据库,只需要新增适配器即可。区别于缓存的实现,数据库使用接口interface作为适配器的约定。
mysql的实现主要依赖mysqli库,它对mysql库做了优化,防注入更完善一些。CURD的具体实现思路是,先获取要处理的数据,最终拼接成sql来执行。
注:链式调用通过方法返回$this来实现
简单看一下select查询的实现:
public function select(){$this->checkMysqlOperate("table_empty");empty($this->_fields) && $this->_fields = "*";$sql = "SELECT {$this->_fields} FROM {$this->_table}";!empty($this->_where) && $sql .= " WHERE {$this->_where}";!empty($this->_order) && $sql .= " ORDER BY {$this->_order}";!empty($this->_group) && $sql .= " GROUP BY {$this->_group}";!empty($this->_limit) && $sql .= " LIMIT {$this->_offset}, {$this->_limit}";$this->_sql = $sql;$mysqliResult = mysqli_query($this->_connection, $this->_sql);if (false === $mysqliResult) {$this->_error = mysqli_error($this->_connection);return false;}return mysqli_fetch_all($mysqliResult, MYSQLI_ASSOC);}
我们在应用层调用一下select:
$dbInstance = Db::getInstance();$result = $dbInstance->table('student')->where('SId in (01, 02, 13)')->order("SId DESC")->select();
update:
$dbInstance = Db::getInstance();$dbInstance->table('student');$dbInstance->where(['Sid' => '01']);$result = $dbInstance->update($data);
数据验证器
数据验证器主要是用来验证数据是否符合我们的规范,可以用来验证表单数据,也可以用来验证业务数据。
主要实现是列举所有的验证规则依次校验,主要有这些规则校验:必传校验、类型校验、字符校验、数字校验、正则校验。
主要实现代码:
public function check(array $data, array $rules): self{foreach ($rules as $rule => $message) {$dataRule = explode(".", $rule);if (count($dataRule) < 2) {continue;}// 必传校验if ($dataRule[1] == "required" && !isset($data[$dataRule[0]])) {array_push($this->errors, $message);continue;}if (!isset($data[$dataRule[0]])) {continue;}// 类型校验if (in_array($dataRule[1], $this->typeCheckName)) {if (false === self::typeCheck(strval($dataRule[1]), $data[$dataRule[0]])) {array_push($this->errors, $message);continue;}}// 字符校验if (in_array($dataRule[1], $this->stringCheckName) && isset($dataRule[2])) {if (false === self::stringCheck(strval($dataRule[1]), $dataRule[2], $data[$dataRule[0]])) {array_push($this->errors, $message);continue;}}// 数字校验if (in_array($dataRule[1], $this->operatorCheckName) && isset($dataRule[2])) {if (false === self::operatorCheck(strval($dataRule[1]), $dataRule[2], $data[$dataRule[0]])) {array_push($this->errors, $message);continue;}}// 正则校验if (in_array($dataRule[1], array_keys($this->pregCheckRules))) {if (false === self::pregCheck(strval($dataRule[1]), $data[$dataRule[0]])) {array_push($this->errors, $message);continue;}}}return $this;}
字符传校验部分代码:
public function stringCheck(string $rule, $value, $dataValue): bool{$flag = true;switch ($rule) {case "max":strlen($dataValue) > $value && $flag = false;break;case "min":strlen($dataValue) < $value && $flag = false;break;case "length":strlen($dataValue) != $value && $flag = false;break;case "in":$value = explode(",", $value);!in_array($dataValue, $value) && $flag = false;break;case "notIn":$value = explode(",", $value);in_array($dataValue, $value) && $flag = false;break;}return $flag;}
业务层这样调用:
public function testValidate(){$validate = new ValidateData();$data = ["age" => 17,"weight" => "50公斤","name" => "ZhangSan","country" => "这里是中国abc","sex" => "未知","mobile" => "11098186452",];$rules = ["age.required" => "请输入年龄","email.required" => "请输入邮箱","age.gt.18" => "年龄必须大于18","weight.float" => "体重必须为浮点数","name.max.6" => "姓名最大长度为6","country.alphaNum" => "国家必须为数字或者字母","sex.in.男,女" => "性别必须是男或者女","mobile.mobile" => "手机号码不合法",];$validate->check($data, $rules);var_dump($validate->getErrors());}
实现容器依赖注入
首先我们先了解概念。框架中的容器指的是什么?什么是依赖注入?
容器(当前所指)是一个用于管理和存储应用程序中各种对象的工具。它允许你注册、创建和解析对象,以及管理它们之间的依赖关系。当前框架中的容器通常使用关联数组来存储对象和服务。
依赖注入是一种设计模式,它允许你将一个对象的依赖关系传递给它,而不是在对象内部直接创建或管理依赖关系。
这可以使代码更加可测试、可维护和可扩展,因为它将对象的依赖性解耦,并使它们更容易替换和修改。
依赖注入通常通过构造函数注入、方法注入或属性注入来实现。
在当前框架中,依赖注入和容器一起使用,容器负责实例化和解析对象,并自动注入它们的依赖关系。
那么如何实现呢?通过php的反射,来获取类的相关信息来解决依赖。
我们从容器中拿一个服务对象,如果没有拿到,则需要创建。创建的时候通过下面几步我们来解决依赖。
- 根据类名获取目标类(实际是反射类)
$reflection = new \ReflectionClass($className)
- 进一步获取目标类的构造方法(实际是构造方法类)
$reflection->getConstructor()
- 获取构造方法所需参数类(是一个数组)
$constructorParameters = $constructor->getParameters()
- 循环所需参数,如果参数没有默认值,则是一个服务对象,我们继续从容器中获取,直到解决所有的依赖。
foreach ($constructorParameters as $param) {if (version_compare(PHP_VERSION, '5.6.0', '>=') && $param->isVariadic()) {break;} elseif ($param->isDefaultValueAvailable()) {$dependencies[] = $param->getDefaultValue();} else {$c = $param->getClass();$dependencies[] = $this->get($c->getName(), $this->_params[$c->getName()] ?? []);}
}
注:请避免出现循环嵌套,否则会出现未知问题
创建的完整代码:
public function build(string $className, array $params = []): ?object{if (isset($this->_reflections[$className])) {$reflection = $this->_reflections[$className];} else {try {$reflection = new \ReflectionClass($className);} catch (ReflectionException $exception) {throw new Exception("Failed to reflect class " . $className . ", error: " . $exception->getMessage());}$this->_reflections[$className] = $reflection;}if (!$reflection->isInstantiable()) {throw new Exception("Is not instantiable:" . $reflection->name);}$dependencies = [];$constructor = $reflection->getConstructor();if ($constructor !== null) {$constructorParameters = $constructor->getParameters();foreach ($constructorParameters as $param) {if (version_compare(PHP_VERSION, '5.6.0', '>=') && $param->isVariadic()) {break;} elseif ($param->isDefaultValueAvailable()) {$dependencies[] = $param->getDefaultValue();} else {$c = $param->getClass();$dependencies[] = $this->get($c->getName(), $this->_params[$c->getName()] ?? []);}}}$this->_dependencies[$className] = Arr::arrayMergeBase($dependencies, $params);$object = $reflection->newInstanceArgs($this->_dependencies[$className]);$this->_objects[$className] = $object;return $object;}
}
解决完依赖,我们就把改服务存入容器中。
业务层调用:
$container = new Container();$container->set("app\service\Group", [123]);$container->set("app\service\User");$container->set("app\service\UserList");$group = $container->get("app\service\Group");$userList = $container->get("app\service\UserList");$group->getA();$userList->getUserList();
Group.php:
<?php
namespace app\service;class Group
{public static $a = 0;function __construct($a =1){static::$a = $a;}public function getA(){echo self::$a;}
}
User.php:
<?php
namespace app\service;class User
{public function __construct(Group $group){}function user(){}
}
UserList.php:
<?php
namespace app\service;class UserList
{public function __construct(User $user){}public function getUserList(){echo "this is the user-list";}
}
尾声
至此,这款简易的php框架的实现过程就介绍完了。更多详细的内容请异步:
https://github.com/yijiebaiyi/fast_framework
这里有详细的代码示例和完整的实现过程。
相关文章:

怎么从0到1实现一个PHP框架?
写在前面 本人开发的框架在2021年年初开发完成,后面没有再做过任何维护和修改。是仅供大家参考交流的学习项目,请勿使用在生产环境,也勿用作商业用途。 框架地址: https://github.com/yijiebaiyi/fast_framework 整体思路 开发…...

脚本:python实现樱花树
文章目录 代码效果 代码 from turtle import * from random import * from math import * def tree(n, l):pd () # 下笔# 阴影效果t cos ( radians ( heading () 45 ) ) / 8 0.25pencolor ( t, t, t )pensize ( n / 3 )forward ( l ) # 画树枝if n > 0:b random () *…...

公司内部传文件怎么安全——「用绿盾透明加密软件」
为保证公司内部文件传递的安全性,可以使用天锐绿盾透明加密软件来进行保护。以下是具体的操作步骤: 在公司内部部署天锐绿盾加密软件,确保需要传递的文件都能受到加密保护。 在员工的工作电脑上安装天锐绿盾客户端,并设置好相关的…...

提高使用VS Code工作效率的技巧
提高使用VS Code工作效率的技巧 时间轴视图:本地源代码控制 时间轴视图为我们提供了内置的源代码控制。 我们中的许多人都知道 Git 和其他源代码控制工具有多么有用,它们可以帮助我们轻松跟踪文件更改并在需要时恢复到之前的状态。 因此,…...

软件系统兼容性测试都要注意哪些问题?
兼容性 软件兼容性测试具有相同的含义,它是任何第三方 Web 应用程序测试服务不可分割的一部分。在众多不同的设置中,最重要的是完全的客户满意度,并且可以通过全面的兼容性测试来达到最佳效果。众所周知,软件质量保证是克服 IT 挑…...

索尼 toio™应用创意开发征文|toio俄罗斯方块游戏
目录 引言 摘要 创意简述 准备工作|手工开始 代码编写|合理集成 使用体验|近乎奇妙 引言 索尼toio™编程机器人是一款引领技术创新的产品,为开发者提供了一个全新的编程和创造平台。toio™的设计旨在将技术、塑性和乐趣融为…...

C#事件event
事件模型的5个组成部分 事件拥有者(event source)(类对象)(有些书将其称为事件发布者) 事件成员(event)(事件拥有者的成员)(事件成员就是事件本身…...

气传导耳机什么牌子好?盘点五款好用的气传导耳机分享
对于气传导耳机,大家最关心的可能是佩戴会不会不舒服?音质好不好?会不会漏音?等问题。面对这些问题,今天我就为大家推荐几款市面上最好的气传导耳机,总有一款适合你的! ①NANK南卡00压气传导…...

业绩走低,毛利率下滑,海外市场能否成为极米科技救命稻草?
撰稿|行星 来源|贝多财经 8月30日,成都极米科技股份有限公司(SH:688696,下称“极米科技”)发布2023年半年度业绩报告。财报显示,极米科技2023年上半年的业绩出现了大幅下滑,其中收入同比减少两成…...

轻松敏捷开发流程之Scrum
Scrum是一种敏捷开发流程,它旨在使软件开发更加高效和灵活。Scrum将软件开发过程分为多个短期、可重复的阶段,称为“Sprint”。每个Sprint通常为两周,旨在完成一部分开发任务。 在Scrum中,有一个明确的角色分工: 产品…...

Vue3+Element Plus实现el-table跨行显示(非脚手架)
Vue3Element Plus实现el-table跨行显示 app组件内容使用:span-method"objectSpanMethod"自定义方法实现跨行显示查询方法初始化挂载新建一个html即可进行测试,完整代码如下效果图 app组件内容 <div id"app"><!-- 远程搜索 --><e…...

生成订单30分钟未支付,则自动取消,该怎么实现?
今天给大家上一盘硬菜,并且是支付中非常重要的一个技术解决方案,有这块业务的同学注意自己试一把了哈! 在开发中,往往会遇到一些关于延时任务的需求。例如 生成订单30分钟未支付,则自动取消 生成订单60秒后,给用户…...

WebGIS外包开发流程
WebGIS开发流程需要综合考虑前端和后端开发、地理信息数据处理、用户需求和安全性等多个方面。成功的WebGIS应用程序需要不断地进行更新和维护,以适应变化的需求和技术。WebGIS开发是一个复杂的过程,通常包括以下主要步骤。北京木奇移动技术有限公司&…...

pytorch学习——LSTM和GRU
参考书籍:https://zh-v2.d2l.ai/chapter_recurrent-modern/lstm.html 参考论文: https://colah.github.io/posts/2015-08-Understanding-LSTMs/ 简介: LSTM(长短期记忆网络)和GRU(门控循环单元)…...

【Python】Python 利用模块实现单例模式
Python 利用模块实现单例模式 在GOF的23种设计模式中,单例是最常使用的模式,通过单例模式可以保证系统中 一个类只有一个实例而且该实例易于被外界访问,从而方便对实例个数的控制并节约系统资 源。每当大家想要实现一个名为XxxMangcr的类时&…...

雅思写作 三小时浓缩学习顾家北 笔记总结(四)
目录 The company should provide maternity leave and other assistance to female employees with children. Community redevelopment provides opportunities for offenders to acquire vocational skills. The law should classify drunk driving as a criminal offens…...

深入学习与探索:高级数据结构与复杂算法
文章目录 学习高级数据结构B树:数据库引擎的骨干线段树:高效的区间查询Trie树:高效的字符串检索 探索复杂算法领域图算法:解决复杂网络问题字符串匹配算法:处理文本搜索近似算法:在NP难题上取得近似解 结论…...

CV:计算机视觉CV运用领域
计算机视觉是一项涉及大量算法和技术的跨学科领域,已经在众多领域得到广泛的应用。以下是计算机视觉的一些主要应用领域: 图像处理和图像分析:计算机视觉技术可以用于图像处理和图像分析,识别和检测特定的图像特征,例如…...

开源机密计算平台:蓬莱-OpenHarmony
演讲嘉宾 | 杜 东 回顾整理 | 廖 涛 排版校对 | 李萍萍 嘉宾简介 杜东,上海交通大学助理研究员。中国计算机学会CCF会员,ACM会员。研究兴趣为操作系统与体系结构、服务器无感知(Serverless)计算、系统安全。在包括ASPLOS、ISC…...

大一大二一心学算法的利弊
学习算法是现代计算机科学和软件工程领域中的重要组成部分。它们是解决复杂问题、优化资源利用以及提高效率的关键。学习算法的过程可以帮助培养系统性思维、分析问题能力和创造性解决方案的能力。然而,学习算法也有一些利弊,我们将在下文中详细探讨。 …...

c#using关键字的作用
https://blog.csdn.net/Mona_Zhao/article/details/91363446 using关键字的三种作用: 1. 引用命名空间; 2. 为命名空间或者类型创建别名; 3. 使用using语句。 (1)引用命名空间 类似于c和c的#include<>, pyt…...

只依赖OPENCV的工作服安全帽检测YOLOV8S
工地安全帽工作服检测Y8S,采用YOLOV8S训练模型,然后使用OPENCV的DNN调用,彻底拜托PYTORCH依赖,可以在C,PYTHON,ANDROID上跑。附件是C生成的效果测试(只需解压将图片或者视频放入VIDEOS文件夹,文件夹没图片或…...

MFC|选择获取文件路径
参考:mfc按钮选择文件或者文件夹(https://blog.csdn.net/qq_39433050/article/details/130261518) 点击按钮槽函数,选择文件 void CMFCStartGrabDlg::OnBnClickedSelectfile() {// TODO: Add your control notification handler…...

实时操作系统Freertos开坑学习笔记:(七):队列
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、队列是什么?而在freertos中,队列是什么呢?①如果要进行中断、任务的交流,那我用全局变量行吗?②…...

专业游戏翻译公司怎么选择比较合适
近年来,游戏行业持续繁荣,市场需求也在不断扩大,其中游戏翻译的需求越来越旺盛。无论是引进游戏还是让游戏走向国际市场,都需要专业的翻译公司来帮忙。那么,怎么选择合适的游戏翻译公司呢?让我们一起来看看…...

阿里云Maven和Gradle仓库最新配置
文章目录 一、简介二、仓库地址三、如何配置1、Maven配置2、Gradle配置 一、简介 阿里云云效 Maven 是什么? 阿里云Maven中央仓库为 阿里云云效 提供的公共代理仓库,帮助研发人员提高研发生产效率,使用阿里云Maven中央仓库作为下载源&am…...

尚硅谷大数据项目《在线教育之离线数仓》笔记007
视频地址:尚硅谷大数据项目《在线教育之离线数仓》_哔哩哔哩_bilibili 目录 第12章 报表数据导出 P112 01、创建数据表 02、修改datax的jar包 03、ads_traffic_stats_by_source.json文件 P113 P114 P115 P116 P117 P118 P119 P120 P121 P122【122_在…...

python考研志愿填报模拟系统vue
本系统提供给管理员对学生、院校、研究生信息、专业信息、学院信息等诸多功能进行管理。本系统对于学生输入的任何信息都进行了一定的验证,为管理员操作提高了效率,也使其数据安全性得到了保障。本考研志愿填报模拟系统以Django作为框架,B/S模…...

【LeetCode-面试经典150题-day20】
目录 70.爬楼梯 198.打家劫舍 139.单词拆分 322.零钱兑换 300.最长递增子序列 70.爬楼梯 题意: 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? 提示: 1 < n < …...
回归与聚类算法系列②:线性回归
目录 1、定义与公式 2、应用场景 3、特征与目标的关系分析 线性回归的损失函数 为什么需要损失函数 损失函数 ⭐如何减少损失 4、优化算法 正规方程 梯度下降 优化动态图 偏导 正规方程和梯度下降比较 5、优化方法GD、SGD、SAG 6、⭐线性回归API 7、实例&#…...