前端技术
HTML
CSS
Javascript
前端框架和UI库
VUE
ReactJS
AngularJS
JQuery
NodeJS
JSON
Element-UI
Bootstrap
Material UI
服务端和客户端
Java
Python
PHP
Golang
Scala
Kotlin
Groovy
Ruby
Lua
.net
c#
c++
后端WEB和工程框架
SpringBoot
SpringCloud
Struts2
MyBatis
Hibernate
Tornado
Beego
Go-Spring
Go Gin
Go Iris
Dubbo
HessianRPC
Maven
Gradle
数据库
MySQL
Oracle
Mongo
中间件与web容器
Redis
MemCache
Etcd
Cassandra
Kafka
RabbitMQ
RocketMQ
ActiveMQ
Nacos
Consul
Tomcat
Nginx
Netty
大数据技术
Hive
Impala
ClickHouse
DorisDB
Greenplum
PostgreSQL
HBase
Kylin
Hadoop
Apache Pig
ZooKeeper
SeaTunnel
Sqoop
Datax
Flink
Spark
Mahout
数据搜索与日志
ElasticSearch
Apache Lucene
Apache Solr
Kibana
Logstash
数据可视化与OLAP
Apache Atlas
Superset
Saiku
Tesseract
系统与容器
Linux
Shell
Docker
Kubernetes
[数据源连接]的搜索结果
这里是文章列表。热门标签的颜色随机变换,标签颜色没有特殊含义。
点击某个标签可搜索标签相关的文章。
点击某个标签可搜索标签相关的文章。
转载文章
...媒资信息 需求分析 数据模型 Dao Service 测试 0x03 Logstash:扫描课程计划媒资 创建索引 创建模板文件 配置 mysql.conf 启动 logstash.bat Logstash多实例运行 0x04 搜素服务:查询课程媒资接口 需求分析 Api接口定义 Service Controller 测试 三、在线学习:接口开发 0x01 需求分析 0x02 搭建开发环境 0x03 Api接口 0x04 服务端开发 需求分析 搜索服务注册Eureka 搜索服务客户端 自定义错误代码 Service Controller 测试 0x05 前端开发 需求分析 api方法 配置代理 视频播放页面 简单的测试 完整的测试 1、上传文件 一些问题 ~~方案1:删除本地分块文件重新尝试上传~~ 方案2:检查前端提交的MD5值是否正确 2、为课程计划选择媒资信息 3、前端门户测试 四、待完善的一些功能 😁 认识作者 一、学习页面:查询课程计划 0x01 需求分析 到目前为止,我们已可以编辑课程计划信息并上传课程视频,下一步我们要实现在线学习页面动态读取章节对应的视频并进行播放。在线学习页面所需要的信息有两类: 课程计划信息 课程学习信息(视频地址、学习进度等) 如下图: 在线学习集成媒资管理的需求如下: 1、在线学习页面显示课程计划 2、点击课程计划播放该课程计划对应的视频 本章节实现学习页面动态显示课程计划,进入不同课程的学习页面右侧动态显示当前课程的课程计划。 0x02 Api接口 课程计划信息从哪里获取? 在课程发布完成后会自动发布到一个 course_pub 的表中,logstash 会自动将课程发布后的信息自动采集到 ES 索引库中,这些信息也包含课程计划信息。 所以考虑性能要求,课程发布后对课程的查询统一从 ES 索引库中查询。 前端通过请求 搜索服务 获取课程信息,需要单独在 搜索服务 中定义课程信息查询接口。 本接口接收课程id,查询课程所有信息返回给前端。 我们在搜素服务 API 下添加以下方法 @ApiOperation("根据id搜索课程发布信息")public Map<String,CoursePub> getdetail(String id); 返回的课程信息为 json 结构:key 为课程id,value 为课程内容。 0x03 服务端开发 在搜索服务中开发查询课程信息接口。 Controller 在搜素服务下添加以下方法 / 根据id搜索课程发布信息 @param id 课程id @return JSON数据/@Override@GetMapping("/getdetail/{id}")public Map<String, CoursePub> getdetail(@PathVariable("id")String id) {return esCourseService.getdetail(id);} Service / 根据id搜索课程发布信息 @param id 课程id @return JSON数据/public Map<String, CoursePub> getdetail(String id) {//设置索引SearchRequest searchRequest = new SearchRequest(es_index);//设置类型searchRequest.types(es_type);//创建搜索源对象SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//设置查询条件,根据id进行查询searchSourceBuilder.query(QueryBuilders.termQuery("id",id));//这里不使用source的原字段过滤,查询所有字段// searchSourceBuilder.fetchSource(new String[]{"name", "grade", "charge","pic"}, newString[]{});//设置搜索源对象searchRequest.source(searchSourceBuilder);//执行搜索SearchResponse searchResponse = null;try {searchResponse = restHighLevelClient.search(searchRequest);} catch (IOException e) {e.printStackTrace();}//获取搜索结果SearchHits hits = searchResponse.getHits();SearchHit[] searchHits = hits.getHits(); //获取最优结果Map<String,CoursePub> map = new HashMap<>();for (SearchHit hit: searchHits) {//从搜索结果中取值并添加到coursePub对象Map<String, Object> sourceAsMap = hit.getSourceAsMap();String courseId = (String) sourceAsMap.get("id");String name = (String) sourceAsMap.get("name");String grade = (String) sourceAsMap.get("grade");String charge = (String) sourceAsMap.get("charge");String pic = (String) sourceAsMap.get("pic");String description = (String) sourceAsMap.get("description");String teachplan = (String) sourceAsMap.get("teachplan");CoursePub coursePub = new CoursePub();coursePub.setId(courseId);coursePub.setName(name);coursePub.setPic(pic);coursePub.setGrade(grade);coursePub.setTeachplan(teachplan);coursePub.setDescription(description);//设置map对象map.put(courseId,coursePub);}return map;} 测试 使用 swagger-ui 或 postman 测试查询课程信息接口。 0x04 前端开发 配置NGINX虚拟主机 学习中心的二级域名为 ucenter.xuecheng.com ,我们在 nginx 中配置 ucenter 虚拟主机。 学成网用户中心server {listen 80;server_name ucenter.xuecheng.com;个人中心location / {proxy_pass http://ucenter_server_pool;} } 前端ucenterupstream ucenter_server_pool{server 127.0.0.1:7081 weight=10;server 127.0.0.1:13000 weight=10;} 在学习中心要调用搜索的 API,使用 Nginx 解决代理,如下图: 在 ucenter 虚拟主机下配置搜索 Api 代理路径 后台搜索(公开api)upstream search_server_pool{server 127.0.0.1:40100 weight=10;} 学成网用户中心server {listen 80;server_name ucenter.xuecheng.com;个人中心location / {proxy_pass http://ucenter_server_pool;}后端搜索服务location /openapi/search/ {proxy_pass http://search_server_pool/search/;} } 前端 API 方法 在学习中心 xc-ui-pc-leanring 对课程信息的查询属于基础常用功能,所以我们将课程查询的 api 方法定义在base 模块下,如下图: 在system.js 中定义课程查询方法: import http from './public'export const course_view = id => {return http.requestGet('/openapi/search/course/getdetail/'+id);} 前端 API 方法调用 在 learning_video.vue 页面中调用课程信息查询接口得到课程计划,将课程计划json 串转成对象。 xc-ui-pc-leanring/src/module/course/page/learning_video.vue 1、定义视图 课程计划 <!--课程计划部分代码--><div class="navCont"><div class="course-weeklist"><div class="nav nav-stacked" v-for="(teachplan_first, index) in teachplanList"><div class="tit nav-justified text-center"><i class="pull-left glyphicon glyphicon-th-list"></i>{ {teachplan_first.pname} }<i class="pull-right"></i></div><li v-if="teachplan_first.children!=null" v-for="(teachplan_second, index) in teachplan_first.children"><i class="glyphicon glyphicon-check"></i><a :href="url" @click="study(teachplan_second.id)">{ {teachplan_second.pname} }</a></li><!-- <div class="tit nav-justified text-center"><i class="pull-left glyphicon glyphicon-th-list"></i>第一章<i class="pull-right"></i></div><li ><i class="glyphicon glyphicon-check"></i><a :href="url" >第一节</a></li>--><!--<li><i class="glyphicon glyphicon-unchecked"></i>为什么分为A、B、C部分</li>--></div></div></div> 课程名称 <div class="top text-center">{ {coursename} }</div> 定义数据对象 data() {return {url:'',//当前urlcourseId:'',//课程idchapter:'',//章节Idcoursename:'',//课程名称coursepic:'',//课程图片teachplanList:[],//课程计划playerOptions: {//播放参数autoplay: false,controls: true,sources: [{type: "application/x-mpegURL",src: ''}]},} } 在 created 钩子方法中获取课程信息 created(){//当前请求的urlthis.url = window.location//课程idthis.courseId = this.$route.params.courseId//章节idthis.chapter = this.$route.params.chapter//查询课程信息systemApi.course_view(this.courseId).then((view_course)=>{if(!view_course || !view_course[this.courseId]){this.$message.error("获取课程信息失败,请重新进入此页面!")return ;} let courseInfo = view_course[this.courseId]console.log(courseInfo)this.coursename = courseInfo.nameif(courseInfo.teachplan){let teachplan = JSON.parse(courseInfo.teachplan);this.teachplanList = teachplan.children;} })}, 测试 在浏览器请求:http://ucenter.xuecheng.com//learning/4028e581617f945f01617f9dabc40000/0 4028e581617f945f01617f9dabc40000:第一个参数为课程 id,测试时从 ES索引库找一个课程 id 0:第二个参数为课程计划 id,此参数用于点击课程计划播放视频。 如果出现跨域问题,但是确定已经配置了跨域,请尝试结束所以 nginx.exe 的进程 和 清空浏览器缓存。 如果还没有解决?重启电脑试试。 二、学习页面:获取视频播放地址 0x01 需求分析 用户进入在线学习页面,点击课程计划将播放该课程计划对应的教学视频。 业务流程如下: 业务流程说明: 1、用户进入在线学习页面,页面请求搜索服务获取课程信息(包括课程计划信息)并且在页面展示。 2、在线学习请求学习服务获取视频播放地址。 3、学习服务校验当前用户是否有权限学习,如果没有权限学习则提示用户。 4、学习服务校验通过,请求搜索服务获取课程媒资信息。 5、搜索服务请求ElasticSearch获取课程媒资信息。 为什么要请求 ElasticSearch 查询课程媒资信息? 出于性能的考虑,公开查询课程信息从搜索服务查询,分摊 mysql 数据库的访问压力。 什么时候将课程媒资信息存储到 ElasticSearch 中? 课程媒资信息是在课程发布的时候存入 ElasticSearch,因为课程发布后课程信息将基本不再修改。 0x02 课程发布:储存媒资信息 需求分析 课程媒资信息是在课程发布的时候存入 ElasticSearch 索引库,因为课程发布后课程信息将基本不再修改,具体的业务流程如下。 1、课程发布,向课程媒资信息表写入数据。 1)根据课程 id 删除 teachplanMediaPub 中的数据 2)根据课程 id 查询 teachplanMedia 数据 3)将查询到的 teachplanMedia 数据插入到 teachplanMediaPub 中 2、Logstash 定时扫描课程媒资信息表,并将课程媒资信息写入索引库。 数据模型 在 xc_course 数据库创建课程计划媒资发布表: CREATE TABLE teachplan_media_pub (teachplan_id varchar(32) NOT NULL COMMENT '课程计划id',media_id varchar(32) NOT NULL COMMENT '媒资文件id',media_fileoriginalname varchar(128) NOT NULL COMMENT '媒资文件的原始名称',media_url varchar(256) NOT NULL COMMENT '媒资文件访问地址',courseid varchar(32) NOT NULL COMMENT '课程Id',timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT'logstash使用',PRIMARY KEY (teachplan_id)) ENGINE=InnoDB DEFAULT CHARSET=utf8 数据模型类如下: package com.xuecheng.framework.domain.course;import lombok.Data;import lombok.ToString;import org.hibernate.annotations.GenericGenerator;import javax.persistence.;import java.io.Serializable;import java.util.Date;@Data@ToString@Entity@Table(name="teachplan_media_pub")@GenericGenerator(name = "jpa-assigned", strategy = "assigned")public class TeachplanMediaPub implements Serializable {private static final long serialVersionUID = -916357110051689485L;@Id@GeneratedValue(generator = "jpa-assigned")@Column(name="teachplan_id")private String teachplanId;@Column(name="media_id")private String mediaId;@Column(name="media_fileoriginalname")private String mediaFileOriginalName;@Column(name="media_url")private String mediaUrl;@Column(name="courseid")private String courseId;@Column(name="timestamp")private Date timestamp;//时间戳} Dao 创建 TeachplanMediaPub 表的 Dao,向 TeachplanMediaPub 存储信息采用先删除该课程的媒资信息,再添加该课程的媒资信息,所以这里定义根据课程 id 删除课程计划媒资方法: public interface TeachplanMediaPubRepository extends JpaRepository<TeachplanMediaPub, String> {//根据课程id删除课程计划媒资信息long deleteByCourseId(String courseId);} 从TeachplanMedia查询课程计划媒资信息 //从TeachplanMedia查询课程计划媒资信息public interface TeachplanMediaRepository extends JpaRepository<TeachplanMedia, String> {List<TeachplanMedia> findByCourseId(String courseId);} Service 编写保存课程计划媒资信息方法,并在课程发布时调用此方法。 1、保存课程计划媒资信息方法 本方法采用先删除该课程的媒资信息,再添加该课程的媒资信息,在 CourseService 下定义该方法 //保存课程计划媒资信息private void saveTeachplanMediaPub(String courseId){//查询课程媒资信息List<TeachplanMedia> byCourseId = teachplanMediaRepository.findByCourseId(courseId);if(byCourseId == null) return; //没有查询到媒资数据则直接结束该方法//将课程计划媒资信息储存到待索引表//删除原有的索引信息teachplanMediaPubRepository.deleteByCourseId(courseId);//一个课程可能会有多个媒资信息,遍历并使用list进行储存List<TeachplanMediaPub> teachplanMediaPubList = new ArrayList<>();for (TeachplanMedia teachplanMedia: byCourseId) {TeachplanMediaPub teachplanMediaPub = new TeachplanMediaPub();BeanUtils.copyProperties(teachplanMedia, teachplanMediaPub);teachplanMediaPubList.add(teachplanMediaPub);}//保存所有信息teachplanMediaPubRepository.saveAll(teachplanMediaPubList);} 2、课程发布时调用此方法 修改课程发布的 coursePublish 方法: ....//保存课程计划媒资信息到待索引表saveTeachplanMediaPub(courseId);//页面urlString pageUrl = cmsPostPageResult.getPageUrl();return new CoursePublishResult(CommonCode.SUCCESS,pageUrl);..... 测试 测试课程发布后是否成功将课程媒资信息存储到 teachplan_media_pub 中,测试流程如下: 1、指定一个课程 2、为课程计划添加课程媒资 3、执行课程发布 4、观察课程计划媒资信息是否存储至 teachplan_media_pub 中 注意:由于此测试仅用于测试发布课程计划媒资信息的功能,可暂时将 cms页面发布的功能暂时屏蔽,提高测试效率。 测试结果如下 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vrzs5589-1595567273126)(https://qnoss.codeyee.com/20200704_15/image7)] 0x03 Logstash:扫描课程计划媒资 Logstash 定时扫描课程媒资信息表,并将课程媒资信息写入索引库。 创建索引 1、创建 xc_course_media 索引 2、并向此索引创建如下映射 POST: http://localhost:9200/xc_course_media/doc/_mapping {"properties" : {"courseid" : {"type" : "keyword"},"teachplan_id" : {"type" : "keyword"},"media_id" : {"type" : "keyword"},"media_url" : {"index" : false,"type" : "text"},"media_fileoriginalname" : {"index" : false,"type" : "text"} }} 索引创建成功 创建模板文件 在 logstach 的 config 目录文件 xc_course_media_template.json 文件路径为 %ES_ROOT_DIR%/logstash6.8.8/config/xc_course_media_template.json %ES_ROOT_DIR% 为 ElasticSearch 和 logstash 的安装目录 内容如下: {"mappings" : {"doc" : {"properties" : {"courseid" : {"type" : "keyword"},"teachplan_id" : {"type" : "keyword"},"media_id" : {"type" : "keyword"},"media_url" : {"index" : false,"type" : "text"},"media_fileoriginalname" : {"index" : false,"type" : "text"} }},"template" : "xc_course_media"} } 配置 mysql.conf 在logstash的 config 目录下配置 mysql_course_media.conf 文件供 logstash 使用,logstash 会根据 mysql_course_media.conf 文件的配置的地址从 MySQL 中读取数据向 ES 中写入索引。 参考https://www.elastic.co/guide/en/logstash/current/plugins-inputs-jdbc.html 配置输入数据源和输出数据源。 input {stdin {} jdbc {jdbc_connection_string => "jdbc:mysql://localhost:3306/xc_course?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC" 数据库信息jdbc_user => "root"jdbc_password => "123123" MYSQL 驱动地址,修改为maven仓库对应的位置jdbc_driver_library => "D:/soft/apache-maven-3.5.4/repository/mysql/mysql-connector-java/5.1.40/mysql-connector-java-5.1.40.jar" the name of the driver class for mysqljdbc_driver_class => "com.mysql.jdbc.Driver"jdbc_paging_enabled => "true"jdbc_page_size => "50000"要执行的sql文件statement_filepath => "/conf/course.sql"statement => "select from teachplan_media_pub where timestamp > date_add(:sql_last_value,INTERVAL 8 HOUR)"定时配置schedule => " "record_last_run => truelast_run_metadata_path => "D:/soft/elasticsearch/logstash-6.8.8/config/xc_course_media_metadata"} } output {elasticsearch {ES的ip地址和端口hosts => "localhost:9200"hosts => ["localhost:9200","localhost:9202","localhost:9203"]ES索引库名称index => "xc_course_media"document_id => "%{teachplan_id}"document_type => "doc"template => "D:/soft/elasticsearch/logstash-6.8.8/config/xc_course_media_template.json"template_name =>"xc_course_media"template_overwrite =>"true"} stdout {日志输出codec => json_lines} } 启动 logstash.bat 启动 logstash.bat 采集 teachplan_media_pub 中的数据,向 ES 写入索引。 logstash.bat -f ../config/mysql_course_media.conf 课程发布成功后,Logstash 会自动参加 teachplan_media_pub 表中新增的数据,效果如下 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ILPBxfXi-1595567273134)(https://qnoss.codeyee.com/20200704_15/image10)] Logstash多实例运行 由于之前我们还启动了一个 Logstash 对课程的发布信息进行采集,所以如果想两个 logstash 实例同时运行,因为每个实例都有一个.lock文件,所以不能使用同一个目录来存放数据,所以我们需要使用 --path.data= 为每个实例指定单独的数据目录,具体的代码如下: 该配置是在windows下进行的 课程发布实例 logstash_start_course_pub.bat @title logstash in course_publogstash.bat -f ..\config\mysql.conf --path.data=../data/course_pub 课程计划媒体发布实例 logstash_start_teachplan_media.bat @title logstash i n teachplan_media_publogstash.bat -f ../config/mysql_course_media.conf --path.data=../data/teachplan_media/ 同时运行效果如下 0x04 搜素服务:查询课程媒资接口 需求分析 搜索服务 提供查询课程媒资接口,此接口供学习服务调用。 Api接口定义 @ApiOperation("根据课程计划查询媒资信息")public TeachplanMediaPub getmedia(String teachplanId); Service 1、配置课程计划媒资索引库等信息 在 application.yml 中配置 xuecheng:elasticsearch:hostlist: ${eshostlist:127.0.0.1:9200} 多个结点中间用逗号分隔course:index: xc_coursetype: docsource_field: id,name,grade,mt,st,charge,valid,pic,qq,price,price_old,status,studymodel,teachmode,expires,pub_time,start_time,end_timemedia:index: xc_course_mediatype: docsource_field: courseid,media_id,media_url,teachplan_id,media_fileoriginalname 2、service 方法开发 在 课程搜索服务 中定义课程媒资查询接口,为了适应后续需求,service 参数定义为数组,可一次查询多个课程计划的媒资信息。 / 根据一个或者多个课程计划id查询媒资信息 @param teachplanIds 课程id @return QueryResponseResult/public QueryResponseResult<TeachplanMediaPub> getmedia(String [] teachplanIds){//设置索引SearchRequest searchRequest = new SearchRequest(media_index);//设置类型searchRequest.types(media_type);//创建搜索源对象SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//源字段过滤String[] media_index_arr = media_field.split(",");searchSourceBuilder.fetchSource(media_index_arr, new String[]{});//查询条件,根据课程计划id查询(可以传入多个课程计划id)searchSourceBuilder.query(QueryBuilders.termsQuery("teachplan_id", teachplanIds));searchRequest.source(searchSourceBuilder);SearchResponse searchResponse = null;try {searchResponse = restHighLevelClient.search(searchRequest);} catch (IOException e) {e.printStackTrace();}//获取结果SearchHits hits = searchResponse.getHits();long totalHits = hits.getTotalHits();SearchHit[] searchHits = hits.getHits();//数据列表List<TeachplanMediaPub> teachplanMediaPubList = new ArrayList<>();for(SearchHit hit:searchHits){TeachplanMediaPub teachplanMediaPub =new TeachplanMediaPub();Map<String, Object> sourceAsMap = hit.getSourceAsMap();//取出课程计划媒资信息String courseid = (String) sourceAsMap.get("courseid");String media_id = (String) sourceAsMap.get("media_id");String media_url = (String) sourceAsMap.get("media_url");String teachplan_id = (String) sourceAsMap.get("teachplan_id");String media_fileoriginalname = (String) sourceAsMap.get("media_fileoriginalname");teachplanMediaPub.setCourseId(courseid);teachplanMediaPub.setMediaUrl(media_url);teachplanMediaPub.setMediaFileOriginalName(media_fileoriginalname);teachplanMediaPub.setMediaId(media_id);teachplanMediaPub.setTeachplanId(teachplan_id);//将对象加入到列表中teachplanMediaPubList.add(teachplanMediaPub);}//构建返回课程媒资信息对象QueryResult<TeachplanMediaPub> queryResult = new QueryResult<>();queryResult.setList(teachplanMediaPubList);queryResult.setTotal(totalHits);return new QueryResponseResult<TeachplanMediaPub>(CommonCode.SUCCESS,queryResult);} Controller / 根据课程计划id搜索发布后的媒资信息 @param teachplanId @return/@GetMapping(value="/getmedia/{teachplanId}")@Overridepublic TeachplanMediaPub getmedia(@PathVariable("teachplanId") String teachplanId) {//为了service的拓展性,所以我们service接收的是数组作为参数,以便后续开发查询多个ID的接口String[] teachplanIds = new String[]{teachplanId};//通过service查询ES获取课程媒资信息QueryResponseResult<TeachplanMediaPub> mediaPubQueryResponseResult = esCourseService.getmedia(teachplanIds);QueryResult<TeachplanMediaPub> queryResult = mediaPubQueryResponseResult.getQueryResult();if(queryResult!=null&& queryResult.getList()!=null&& queryResult.getList().size()>0){//返回课程计划对应课程媒资return queryResult.getList().get(0);} return new TeachplanMediaPub();} 测试 使用 swagger-ui 和 postman 测试课程媒资查询接口。 三、在线学习:接口开发 0x01 需求分析 根据下边的业务流程,本章节完成前端学习页面请求学习服务获取课程视频地址,并自动播放视频。 0x02 搭建开发环境 1、创建数据库 创建 xc_learning 数据库,学习数据库将记录学生的选课信息、学习信息。 导入:资料/xc_learning.sql 2、创建学习服务工程 参考课程管理服务工程结构,创建学习服务工程: 导入:资料/xc-service-learning.zip 项目工程结构如下 0x03 Api接口 此 api 接口是课程学习页面请求学习服务获取课程学习地址。 定义返回值类型: package com.xuecheng.framework.domain.learning.response;import com.xuecheng.framework.model.response.ResponseResult;import com.xuecheng.framework.model.response.ResultCode;import lombok.Data;import lombok.NoArgsConstructor;import lombok.ToString;@Data@ToString@NoArgsConstructorpublic class GetMediaResult extends ResponseResult {public GetMediaResult(ResultCode resultCode, String fileUrl) {super(resultCode);this.fileUrl = fileUrl;}//媒资文件播放地址private String fileUrl;} 定义接口,学习服务根据传入课程 ID、章节 Id(课程计划 ID)来取学习地址。 @Api(value = "录播课程学习管理",description = "录播课程学习管理")public interface CourseLearningControllerApi {@ApiOperation("获取课程学习地址")public GetMediaResult getMediaPlayUrl(String courseId,String teachplanId);} 0x04 服务端开发 需求分析 学习服务根据传入课程ID、章节Id(课程计划ID)请求搜索服务获取学习地址。 搜索服务注册Eureka 学习服务要调用搜索服务查询课程媒资信息,所以需要将搜索服务注册到 eureka 中。 1、查看服务名称是否为 xc-service-search 注意修改application.xml中的服务名称:spring:application:name: xc‐service‐search 2、配置搜索服务的配置文件 application.yml,加入 Eureka 配置 如下: eureka:client:registerWithEureka: true 服务注册开关fetchRegistry: true 服务发现开关serviceUrl: Eureka客户端与Eureka服务端进行交互的地址,多个中间用逗号分隔defaultZone: ${EUREKA_SERVER:http://localhost:50101/eureka/,http://localhost:50102/eureka/}instance:prefer-ip-address: true 将自己的ip地址注册到Eureka服务中ip-address: ${IP_ADDRESS:127.0.0.1}instance-id: ${spring.application.name}:${server.port} 指定实例idribbon:MaxAutoRetries: 2 最大重试次数,当Eureka中可以找到服务,但是服务连不上时将会重试,如果eureka中找不到服务则直接走断路器MaxAutoRetriesNextServer: 3 切换实例的重试次数OkToRetryOnAllOperations: false 对所有操作请求都进行重试,如果是get则可以,如果是post,put等操作没有实现幂等的情况下是很危险的,所以设置为falseConnectTimeout: 5000 请求连接的超时时间ReadTimeout: 6000 请求处理的超时时间 3、添加 eureka 依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring‐cloud‐starter‐netflix‐eureka‐client</artifactId></dependency> 4、修改启动类,在class上添加如下注解: @EnableDiscoveryClient 搜索服务客户端 在 学习服务 创建搜索服务的客户端接口,此接口会生成代理对象,调用搜索服务: package com.xuecheng.learning.client;import com.xuecheng.framework.domain.course.TeachplanMediaPub;import org.springframework.cloud.openfeign.FeignClient;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;@FeignClient(value = "xc‐service‐search")public interface CourseSearchClient {@GetMapping(value="/getmedia/{teachplanId}")public TeachplanMediaPub getmedia(@PathVariable("teachplanId") String teachplanId);} 自定义错误代码 我们在 com.xuecheng.framework.domain.learning.response 包下自定义一个错误消息模型 package com.xuecheng.framework.domain.learning.response;import com.xuecheng.framework.model.response.ResultCode;import lombok.ToString;@ToStringpublic enum LearningCode implements ResultCode {LEARNING_GET_MEDIA_ERROR(false,23001,"学习中心获取媒资信息错误!");//操作代码boolean success;//操作代码int code;//提示信息String message;private LearningCode(boolean success, int code, String message){this.success = success;this.code = code;this.message = message;}@Overridepublic boolean success() {return success;}@Overridepublic int code() {return code;}@Overridepublic String message() {return message;} } 该消息模型基于 ResultCode 来实现,代码如下 package com.xuecheng.framework.model.response;/ Created by mrt on 2018/3/5. 10000-- 通用错误代码 22000-- 媒资错误代码 23000-- 用户中心错误代码 24000-- cms错误代码 25000-- 文件系统/public interface ResultCode {//操作是否成功,true为成功,false操作失败boolean success();//操作代码int code();//提示信息String message(); 从 ResultCode 中我们可以看出,我们约定了用户中心的错误代码使用 23000,所以我们定义的一些错误信息的代码就从 23000 开始计数。 Service 在学习服务中定义 service 方法,此方法远程请求课程管理服务、媒资管理服务获取课程学习地址。 package com.xuecheng.learning.service.impl;import com.netflix.discovery.converters.Auto;import com.xuecheng.framework.domain.course.TeachplanMediaPub;import com.xuecheng.framework.domain.learning.response.GetMediaResult;import com.xuecheng.framework.exception.ExceptionCast;import com.xuecheng.framework.model.response.CommonCode;import com.xuecheng.learning.client.CourseSearchClient;import com.xuecheng.learning.service.LearningService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Servicepublic class LearningServiceImpl implements LearningService {@AutowiredCourseSearchClient courseSearchClient;/ 远程调用搜索服务获取已发布媒体信息中的url @param courseId 课程id @param teachplanId 媒体信息id @return/@Overridepublic GetMediaResult getMediaPlayUrl(String courseId, String teachplanId) {//校验学生权限,是否已付费等//远程调用搜索服务进行查询媒体信息TeachplanMediaPub mediaPub = courseSearchClient.getmedia(teachplanId);if(mediaPub == null) ExceptionCast.cast(CommonCode.FAIL);return new GetMediaResult(CommonCode.SUCCESS, mediaPub.getMediaUrl());} } Controller 调用 service 根据课程计划 id 查询视频播放地址: @RestController@RequestMapping("/learning/course")public class CourseLearningController implements CourseLearningControllerApi {@AutowiredLearningService learningService;@Override@GetMapping("/getmedia/{courseId}/{teachplanId}")public GetMediaResult getMediaPlayUrl(@PathVariable String courseId, @PathVariable String teachplanId) {//获取课程学习地址return learningService.getMedia(courseId, teachplanId);} } 测试 使用 swagger-ui 或postman 测试学习服务查询课程视频地址接口。 0x05 前端开发 需求分析 需要在学习中心前端页面需要完成如下功能: 1、进入课程学习页面需要带上 课程 Id参数及课程计划Id的参数,其中 课程 Id 参数必带,课程计划 Id 可以为空。 2、进入页面根据 课程 Id 取出该课程的课程计划显示在右侧。 3、进入页面后判断如果请求参数中有课程计划 Id 则播放该章节的视频。 4、进入页面后判断如果 课程计划id 为0则需要取出本课程第一个 课程计划的Id,并播放第一个课程计划的视频。 进入到模块 xc-ui-pc-leanring/src/module/course api方法 let sysConfig = require('@/../config/sysConfig')let apiUrl = sysConfig.xcApiUrlPre;/获取播放地址/export const get_media = (courseId,chapter) => {return http.requestGet(apiUrl+'/api/learning/course/getmedia/'+courseId+'/'+chapter);} 配置代理 在 Nginx 中的 ucenter.xuecheng.com 虚拟主机中配置 /api/learning/ 的路径转发,此url 请转发到学习服务。 学习服务upstream learning_server_pool{server 127.0.0.1:40600 weight=10;}学成网用户中心server {listen 80;server_name ucenter.xuecheng.com;个人中心location / {proxy_pass http://ucenter_server_pool;}后端搜索服务location /openapi/search/ {proxy_pass http://search_server_pool/search/; }学习服务location ^~ /api/learning/ {proxy_pass http://learning_server_pool/learning/;} } 视频播放页面 1、如果传入的课程计划id为0则取出第一个课程计划id 在 created 钩子方法中完成 created(){//当前请求的urlthis.url = window.location//课程idthis.courseId = this.$route.params.courseId//章节idthis.chapter = this.$route.params.chapter//查询课程信息systemApi.course_view(this.courseId).then((view_course)=>{if(!view_course || !view_course[this.courseId]){this.$message.error("获取课程信息失败,请重新进入此页面!")return ;}let courseInfo = view_course[this.courseId]console.log(courseInfo)this.coursename = courseInfo.nameif(courseInfo.teachplan){console.log("准备开始播放视频")let teachplan = JSON.parse(courseInfo.teachplan);this.teachplanList = teachplan.children;//开始学习if(this.chapter == "0" || !this.chapter){//取出第一个教学计划this.chapter = this.getFirstTeachplan();console.log("第一个教学计划id为 ",this.chapter);this.study(this.chapter);}else{this.study(this.chapter);} }})}, 取出第一个章节 id,用户未输入课程计划 id 或者输入为 0 时,播放第一个。 //取出第一个章节getFirstTeachplan(){for(var i=0;i<this.teachplanList.length;i++){let firstTeachplan = this.teachplanList[i];//如果当前children存在,则取出第一个返回if(firstTeachplan.children && firstTeachplan.children.length>0){let secondTeachplan = firstTeachplan.children[0];return secondTeachplan.id;} }return ;}, 开始学习: //开始学习study(chapter){// 获取播放地址courseApi.get_media(this.courseId,chapter).then((res)=>{if(res.success){let fileUrl = sysConfig.videoUrl + res.fileUrl//播放视频this.playvideo(fileUrl)}else if(res.message){this.$message.error(res.message)}else{this.$message.error("播放视频失败,请刷新页面重试")} }).catch(res=>{this.$message.error("播放视频失败,请刷新页面重试")});}, 2、点击右侧课程章节切换播放 在原有代码基础上添加 click 事件,点击调用开始学习方法(study)。 <li v‐if="teachplan_first.children!=null" v‐for="(teachplan_second, index) inteachplan_first.children"><i class="glyphicon glyphicon‐check"></i><a :href="url" @click="study(teachplan_second.id)">{ {teachplan_second.pname} }</a></li> 3、地址栏路由url变更 这里需要注意一个问题,在用户点击课程章节切换播放时,地址栏的 url 也应该同步改变为当前所选择的课程计划 id 4、在线学习按钮 将 learnstatus 默认更改为 1,这样就能显示出马上学习的按钮,方便我们后续的集成测试。 文件路径为 xc-ui-pc-static-portal/include/course_detail_dynamic.html 部分代码块如下 <script>var body= new Vue({ //创建一个Vue的实例el: "body", //挂载点是id="app"的地方data: {editLoading: false,title:'测试',courseId:'',charge:'',//203001免费,203002收费learnstatus: 1 ,//课程状态,1:马上学习,2:立即报名、3:立即购买course:{},companyId:'template',company_stat:[],course_stat:{"s601001":"","s601002":"","s601003":""} }, 简单的测试 访问在线学习页面:http://ucenter.xuecheng.com//learning/课程id/课程计划id 通过 url 传入两个参数:课程id 和 课程计划id 如果没有课程计划则传入0 测试项目如下: 1、传入正确的课程id、课程计划id,自动播放本章节的视频 2、传入正确的课程id、课程计划id传入0,自动播放第一个视频 3、传入错误的课程id 或 课程计划id,提示错误信息。 4、通过右侧章节目录切换章节及播放视频。 访问: http://ucenter.xuecheng.com//learning/4028e58161bcf7f40161bcf8b77c0000/4028e58161bd18ea0161bd1f73190008 传入正确的课程id、课程计划id,自动播放本章节的视频 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ef0xxym7-1595567273153)(https://qnoss.codeyee.com/20200704_15/image17)] 传入正确的课程id、课程计划id传入0,自动播放第一个视频 访问 http://ucenter.xuecheng.com//learning/4028e58161bcf7f40161bcf8b77c0000/0 识别出第一个课程计划的 id 需要注意的是这里的 chapter 参数是我自己在 study 函数里加上去的,可以忽略。 传入错误的课程id或课程计划id,提示错误信息。 通过右侧章节目录切换章节及播放视频。 点击章节即可播放,但是点击制定章节后 url 没有发生改变,这个问题暂时还没有解决,关注笔记后面的内容。 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TOGdxwb4-1595567273158)(https://qnoss.codeyee.com/20200704_15/image20)] 完整的测试 准备工作 启动 RabbitMQ,启动 Logstash、ElasticSearch 建议把所有后端服务都开起来 启动 前端静态门户、启动 nginx 、启动课程管理前端 我们整理一下测试的流程 上传两个媒资视频文件,用于测试 进入到课程管理,为课程计划选择媒资信息 发布课程,等待 logstash 将数据采集到 ElasticSearch 的索引库中 进入学成网主页,点击课程,进入到搜索门户页面 搜索课程,进入到课程详情页面 点击开始学习,进入到课程学习页面,选择课程计划中的一个章节进行学习。 1、上传文件 首先我们使用之前开发的媒资管理模块,上传两个视频文件用于测试。 第一个文件上传成功 一些问题 在上传第二个文件时,发生了错误,我们来检查一下问题出在了哪里 在媒体服务的控制台中可以看到,在 mergeChunks 方法在校验文件 md5 时候抛出了异常 我们在 MD5 校验这里打个断点,重新上传文件,分析一下问题所在。 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OpEMZGI8-1595567273166)(https://qnoss.codeyee.com/20200704_15/image23)] 单步调试后发现,合并文件后的MD5值与用户上传的源文件值不相等 方案1:删除本地分块文件重新尝试上传 考虑到可能是在用户上传完 视频的分块文件时发生了一些问题,导致合并文件后与源文件的大小不等,导致MD5也不相同,这里我们把这个视频上传到本地的文件全部删除,在媒资上传页面重新上传文件。 对比所有分块文件的字节大小和本地源文件的大小,完全是相等的 删除所有文件后重新上传,md5值还是不等,考虑从调试一下文件合并的代码。 方案2:检查前端提交的MD5值是否正确 在查阅是否有其他的MD5值获取方案时,发现了一个使用 windows 本地命令获取文件MD5值的方法 certutil -hashfile .\19-在线学习接口-集成测试.avi md5 惊奇的发现,TM的原来是前端那边转换的MD5值不正确,后端这边是没有问题的。 从前面的图可以看出,本地和后端转换的都是以一个 f6f0 开头的MD5值 那么问题就出现在前端了,还需要花一些时间去分析一下,这里暂时就先告一段落,因为上传了几个文件测试中只有这一个文件出现了问题。 2、为课程计划选择媒资信息 进入到一个课程的管理页面 http://localhost:12000//course/manage/baseinfo/4028e58161bcf7f40161bcf8b77c0000 将刚才我们上传的媒资文件的信息和课程计划绑定 选择效果如下 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-epKaqzCD-1595567273178)(https://qnoss.codeyee.com/20200704_15/image29)] 2、发布课程,等待 logstash 从 course_pub 以及 teachplan_media_pub 表中采集数据到 ElasticSearch 当中 发布成功后,我们可以从 teachplan_media_pub 表中看到刚才我们发布的媒资信息 再观察 Logstash 的控制台,发现两个 Logstash 的实例都对更新的课程发布信息进行了采集 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hTUve2ik-1595567273183)(https://qnoss.codeyee.com/20200704_15/image32)] 3、前端门户测试 打开我们的门户主站 http://www.xuecheng.com/ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4wZe9R84-1595567273185)(https://qnoss.codeyee.com/20200704_15/image33)] 点击导航栏的课程,进入到我们的搜索门户页面 如果无法进入到搜索门户,请检查你的 xc-ui-pc-portal 前端工程是否已经启动 进入到搜索门户后,可以看到一些初始化时搜索的课程数据,默认是搜索第一页的数据,每页2个课程。 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BJ1AKoJb-1595567273187)(https://qnoss.codeyee.com/20200704_15/image34)] 我们可以测试搜索一下前面我们选择媒资信息时所用的课程 点击课程,进入到课程详情页面,然后再点击开始学习。 点击马上学习后,会进入到该课程的在线学习页面,默认自动播放我们第一个课程计划中的视频。 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tcuLWnf2-1595567273193)(https://qnoss.codeyee.com/20200704_15/image37)] 我们可以在右侧的目录中选择第二个课程计划,会自动播放所选的课程计划所对应的媒资视频播放地址,该 播放地址正是我们刚才通过 Logstash 自动采集到 ElasticSearch 的索引信息,效果图如下 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Cvi9Dr0Y-1595567273195)(https://qnoss.codeyee.com/20200704_15/image38)] 四、待完善的一些功能 课程发布前,校验课程计划里面是否包含二级课程计划 课程发布前,校验课程计划信息里面是否全部包含媒资信息 删除媒资信息,并且同步删除ES中的索引 在获取该课程的播放地址时校验用户的合法、 在线学习页面,点击右侧目录中的课程计划同时改变url中的课程计划地址 视频文件 19-在线学习接口-集成测试.avi 前端上传时提交的MD5值不正确 😁 认识作者 作者:👦 LCyee ,全干型代码🐕 自建博客:https://www.codeyee.com 记录学习以及项目开发过程中的笔记与心得,记录认知迭代的过程,分享想法与观点。 CSDN 博客:https://blog.csdn.net/codeyee 记录和分享一些开发过程中遇到的问题以及解决的思路。 欢迎加入微服务练习生的队伍,一起交流项目学习过程中的一些问题、分享学习心得等,不定期组织一起刷题、刷项目,共同见证成长。 本篇文章为转载内容。原文链接:https://blog.csdn.net/codeyee/article/details/107558901。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-12-16 12:41:01
73
转载
JQuery插件下载
...方式来组织和导航层次数据。它能够优雅地呈现复杂的继承或嵌套关系,如文件目录结构、组织架构、菜单层级视图等。开发者可以通过JSON格式的数据源轻松配置和动态加载树形结构,实现对列表项的折叠、展开以及节点选择等功能。其简洁而灵活的设计风格使得bootstrap-treeview易于集成到各种Web项目中,尤其适合那些需要清晰展示层级关联信息的后台管理系统或前端交互界面。总之,bootstrap-treeview是一个功能强大且高度定制化的jQuery插件,它极大地简化了在Bootstrap基础上创建和操作多级列表树的过程,提升了用户体验和页面交互效率。 点我下载 文件大小:116.88 KB 您将下载一个JQuery插件资源包,该资源包内部文件的目录结构如下: 本网站提供JQuery插件下载功能,旨在帮助广大用户在工作学习中提升效率、节约时间。 本网站的下载内容来自于互联网。如您发现任何侵犯您权益的内容,请立即告知我们,我们将迅速响应并删除相关内容。 免责声明:站内所有资源仅供个人学习研究及参考之用,严禁将这些资源应用于商业场景。 若擅自商用导致的一切后果,由使用者承担责任。
2024-01-15 20:12:45
329
本站
JQuery插件下载
...需要展示复杂层级结构数据的场景。这款插件不仅具有强大的功能,而且非常易于使用和扩展。它能够轻松地与各种不同的主题配合使用,让您的网站或应用界面更加美观。jstree支持从HTML和JSON格式的数据源加载内容,使得数据管理变得更加便捷。此外,它还具备异步回调数据的功能,这意味着您可以动态地加载大量数据而不会影响页面性能。jstree的一个显著优势在于其对旧版浏览器的支持,比如IE8,这使得更多的用户群体能够无障碍地访问您的网站或应用。无论您是在构建文件管理系统,还是在开发复杂的组织架构图,jstree都能提供必要的工具来实现这一目标。它支持多级树结构,可以轻松处理从简单到复杂的各种层级关系,满足了不同项目的需求。总之,jstree凭借其易用性、可扩展性和广泛的功能集,成为了一款不可多得的jQuery目录树插件。无论是前端开发者还是设计师,都可以借助jstree快速创建出美观且功能丰富的目录树界面。 点我下载 文件大小:887.95 KB 您将下载一个JQuery插件资源包,该资源包内部文件的目录结构如下: 本网站提供JQuery插件下载功能,旨在帮助广大用户在工作学习中提升效率、节约时间。 本网站的下载内容来自于互联网。如您发现任何侵犯您权益的内容,请立即告知我们,我们将迅速响应并删除相关内容。 免责声明:站内所有资源仅供个人学习研究及参考之用,严禁将这些资源应用于商业场景。 若擅自商用导致的一切后果,由使用者承担责任。
2025-02-19 11:29:37
67
本站
JQuery插件下载
...滚动、自定义JSON数据源以及可选的进度条等功能,为开发者提供了高度定制化的人物信息展示解决方案,既满足了美观需求,又保证了代码的轻量化和高效运行。 点我下载 文件大小:67.30 KB 您将下载一个JQuery插件资源包,该资源包内部文件的目录结构如下: 本网站提供JQuery插件下载功能,旨在帮助广大用户在工作学习中提升效率、节约时间。 本网站的下载内容来自于互联网。如您发现任何侵犯您权益的内容,请立即告知我们,我们将迅速响应并删除相关内容。 免责声明:站内所有资源仅供个人学习研究及参考之用,严禁将这些资源应用于商业场景。 若擅自商用导致的一切后果,由使用者承担责任。
2023-11-27 12:20:46
124
本站
JQuery插件下载
...还能轻松实现更复杂的数据可视化需求。无论是简单的数据展示还是复杂的统计分析,jqPlot都能满足你的需求。此插件的核心优势在于其强大的定制能力和灵活性。用户可以根据具体需求调整图表样式、颜色方案、数据点样式等,甚至可以自定义图表元素的位置和大小。此外,jqPlot支持多种数据源格式,能够轻松导入或导出数据,极大地提高了数据处理的效率和便利性。除了基础图表功能外,jqPlot还提供了丰富的交互特性,如缩放、平移、点击选择等功能,使得用户可以更深入地探索数据背后的故事。同时,该插件在移动端也有良好的表现,支持响应式设计,确保图表在不同设备上均能呈现最佳视觉效果。总之,jqPlot凭借其强大的功能集、高度的自定义能力以及优秀的用户体验,成为开发人员创建动态、交互式图表的理想选择。无论是用于商业报告、学术研究还是个人项目,jqPlot都能帮助你以最直观的方式展现数据的魅力。 点我下载 文件大小:1.80 MB 您将下载一个JQuery插件资源包,该资源包内部文件的目录结构如下: 本网站提供JQuery插件下载功能,旨在帮助广大用户在工作学习中提升效率、节约时间。 本网站的下载内容来自于互联网。如您发现任何侵犯您权益的内容,请立即告知我们,我们将迅速响应并删除相关内容。 免责声明:站内所有资源仅供个人学习研究及参考之用,严禁将这些资源应用于商业场景。 若擅自商用导致的一切后果,由使用者承担责任。
2024-11-06 20:35:10
73
本站
JQuery插件下载
...ion.js支持多种数据源方式,无论是从服务器端获取的数据,还是本地静态数据,都能灵活应对。此外,通过丰富的配置参数,开发者可以高度定制化分页条的外观与行为,满足不同场景下的需求。插件中包含了大量的配置选项,允许用户调整分页条的位置、样式以及显示逻辑等。不仅如此,Pagination.js还提供了强大的回调函数机制,使得在特定事件触发时执行自定义操作成为可能,例如加载更多内容或更新页面标题等。为了进一步增强其灵活性和美观性,Pagination.js内置了五种不同的分页条皮肤风格,用户可以根据个人喜好或网站的整体设计风格选择最合适的样式。总之,无论是对于希望快速集成分页功能的小型项目,还是需要高度可定制化的大型网站,Pagination.js都是一个理想的选择。它不仅极大地简化了开发流程,同时也确保了最终产品具备出色的性能和用户体验。 点我下载 文件大小:74.85 KB 您将下载一个JQuery插件资源包,该资源包内部文件的目录结构如下: 本网站提供JQuery插件下载功能,旨在帮助广大用户在工作学习中提升效率、节约时间。 本网站的下载内容来自于互联网。如您发现任何侵犯您权益的内容,请立即告知我们,我们将迅速响应并删除相关内容。 免责声明:站内所有资源仅供个人学习研究及参考之用,严禁将这些资源应用于商业场景。 若擅自商用导致的一切后果,由使用者承担责任。
2024-10-30 21:21:23
75
本站
JQuery插件下载
...求调整外观、行为以及数据源,确保与现有UI风格无缝融合。由于其轻量化特性,Awesomplete对性能影响极小,即使在处理大量数据时也能保持流畅。这使得它在处理大数据集或实时搜索场景中表现优异。此外,由于其开源的本质,开发者社区活跃,意味着能得到及时的技术支持和持续的更新。总之,Awesomplete是一款理想的自动完成解决方案,它以简约的设计和强大的功能性,简化了前端开发中常见的输入框自动补全功能,是提升网站交互体验的理想选择。无论你是新手还是经验丰富的前端开发者,都能在Awesomplete中找到价值。 点我下载 文件大小:54.09 KB 您将下载一个JQuery插件资源包,该资源包内部文件的目录结构如下: 本网站提供JQuery插件下载功能,旨在帮助广大用户在工作学习中提升效率、节约时间。 本网站的下载内容来自于互联网。如您发现任何侵犯您权益的内容,请立即告知我们,我们将迅速响应并删除相关内容。 免责声明:站内所有资源仅供个人学习研究及参考之用,严禁将这些资源应用于商业场景。 若擅自商用导致的一切后果,由使用者承担责任。
2023-10-28 08:40:18
298
本站
MySQL
...L是一个开源的关系型数据库管理系统,广泛应用于互联网行业和企业级应用中,支持多种SQL语句进行数据查询、更新、管理等操作。在本文的上下文中,MySQL是用户权限管理、查看与配置的核心平台。 mysql.user , mysql.user是MySQL系统内部的一个重要表,用于存储关于所有用户的账户信息和权限设置。该表中记录了每个用户的用户名(User)、允许连接的主机名或IP地址(Host)以及各个用户的全局权限分配情况,如SELECT、INSERT、UPDATE和DELETE等基本权限。 SHOW GRANTS , SHOW GRANTS是MySQL中的一个内置SQL命令,专门用来显示指定用户的所有权限。在文章中,通过执行SHOW GRANTS FOR username @ hostname 语句,可以详细列出该用户从特定主机登录时所拥有的所有全局权限或数据库权限,有助于管理员理解和管理各个用户的实际操作权限范围。
2023-04-12 13:59:00
92
软件工程师
HTML
...易读且能避免因字符串连接产生的潜在错误。 innerHTML属性 , innerHTML是DOM元素的一个标准属性,用于获取或设置一个HTML元素内部的所有HTML代码,包括其子节点的HTML内容。在文章上下文中,通过将包含JavaScript表达式的HTML字符串赋值给某个DOM元素的innerHTML属性,可以动态更新该元素及其子元素的内容,实现页面内容的动态生成。 第三方库 , 在软件开发中,第三方库是指由非原始开发团队或个人编写的、针对特定功能或需求而创建的预编译代码集合。在本文中提到的Handlebars和Mustache即是此类库,它们提供了额外的模板渲染功能,帮助开发者更方便地将JavaScript数据转换成HTML字符串,尤其适用于处理较为复杂的模板结构与逻辑。通过引入和使用这些第三方库,前端开发者能够提高开发效率、增强代码复用性和降低复杂度。
2023-11-22 11:28:15
474
电脑达人
Python
...洁高效。此外,对于大数据处理或科学计算场景,NumPy库提供的ndarray对象在性能上远超Python原生列表,可以实现快速的矩阵运算和统计分析。 近期,一篇发布于“Real Python”网站的文章深入探讨了如何利用列表推导式(List Comprehensions)和生成器表达式(Generator Expressions)对列表进行复杂操作,如过滤、映射和压缩数据,从而提升代码可读性和运行效率。文章还介绍了functools模块中的reduce函数,用于对列表元素执行累积操作,如求乘积、求序列中最长连续子序列等。 另外,在实际编程实践中,掌握列表的排序、切片、连接、复制等基本操作同样至关重要。例如,使用sorted()函数或列表的sort()方法对列表进行排序;利用切片技术实现列表的部分提取或替换;通过extend()和+运算符完成列表合并等。这些操作不仅能丰富你对Python列表的理解,更能在日常开发任务中助你事半功倍。 总的来说,深入学习和熟练运用Python列表的各种特性与功能,不仅有助于数据分析和处理,更能提升代码编写质量,使程序更加简洁、高效。同时,关注Python社区的最新动态和最佳实践,将能持续拓展你的编程技能边界,紧跟时代发展步伐。
2023-10-05 18:16:18
359
算法侠
MySQL
... 是一款流行的关系型数据库,可以根据需要进行配置,并决定系统参数的数值。本文将介绍如何配置 MySQL 的系统参数。 1. 查看系统参数 要配置 MySQL 的系统参数,首先需要查看现有的系统参数。可以通过以下命令启动 MySQL 终端: mysql -u username -p password 然后键入你的账户名和口令。接下来,键入以下命令: SHOW VARIABLES; 这将展示 MySQL 现有的系统参数及其数值。 2. 变更系统参数 要变更 MySQL 的系统参数,可以使用以下命令: SET GLOBAL VARIABLE_NAME=value; 其中,VARIABLE_NAME 是你想要变更的系统参数的名字,value 是你要将其配置为的数值。比如,要将 max_connections 系统参数配置为 200,可以键入以下命令: SET GLOBAL max_connections=200; 3. 配置永久系统参数 要使所做的更改在 MySQL 重启后持续保留,请将其写入 MySQL 的 my.cnf 文件。该文件包括了 MySQL 的配置配置,包括系统参数。 可以使用以下命令启动该文件进行编辑: sudo vi /etc/mysql/my.cnf 在文件中找到你要更改的参数,并进行变更。比如,若要将 max_connections 系统参数配置为 200,可以使用以下命令: max_connections=200 然后保存文件并重启 MySQL 服务: sudo service mysql restart 现在, MySQL 应该以 200 为最大并发连接数来运行了。 总结 本文介绍了如何配置 MySQL 的系统参数。首先要查看现有的系统参数,然后变更它们。要确保所做的更改在 MySQL 重启后持续保留,请将其写入 MySQL 的 my.cnf 文件。下次你需要配置 MySQL 系统参数时,不妨试试这些方法吧。
2023-09-12 09:01:49
113
算法侠
MySQL
...个问题,反馈你不存在数据库表,可能是由于以下缘由: 问题信息:Table 'database_name.table_name' doesn't exist. 问题缘由可能是: 1. 表空间名称输入问题。请核实您输入的表空间名称是否准确。 比方说,输入“my_database”而不是“myDataBase”。 2. 数据表名问题。请核实您输入的数据表名是否准确。 比方说,输入“user”而不是“users”。 3. 您没有许可查阅该数据库表。请核实您是否有查阅该表所需的许可。 4. 数据库表已被删除。请核实您输入的表名是否准确,或者您的表是否已被删除。 5. 数据库连接故障。请核实您的MySQL连接是否正常工作。 比方说,您的MySQL服务器是否正常工作,或者您是否使用了准确的用户名和密码。 解决方法: 1. 确认表空间名称和表名称是否准确。 2. 确认您是否具有查阅该数据库表的许可。 3. 如果表已经被删除,请尝试恢复表或使用备份复制该表。 4. 确认MySQL连接是否正常。 如果您还是无法解决问题,请联系MySQL管理员或开发人员进行支持。
2023-11-28 12:42:54
55
算法侠
MySQL
...何在MySQL中写入数据后,我们可以进一步关注数据库管理系统的最新动态和最佳实践。近日,MySQL 8.0版本引入了一系列重大更新,包括对安全性、性能以及SQL语法的改进。例如,新的窗口函数提供了更强大的数据分析能力,而Caching_sha2_password身份验证插件则增强了数据库连接的安全性。 同时,随着云技术的发展,各大云服务商如阿里云、AWS等纷纷推出MySQL托管服务,用户无需关心底层服务器运维,即可轻松实现高可用性和扩展性。对于开发人员来说,了解如何在云环境下高效地进行数据写入操作,比如利用批量插入API减少网络延迟,或者通过参数化查询防止SQL注入攻击,成为了必不可少的知识点。 此外,关于数据库优化策略,一篇来自Oracle官方博客的文章《Maximizing MySQL Performance: Tips from the Experts》深度解读了如何通过索引设计、查询优化以及合理使用存储引擎等手段提升MySQL的数据写入效率。文中引用了大量实战案例,为数据库管理员和开发者提供了宝贵的参考经验。 综上所述,在掌握基本的MySQL数据写入操作之外,紧跟数据库技术发展的步伐,关注安全增强、云服务特性及性能优化技巧,是现代开发者必备的技能升级路径。
2023-06-05 22:29:31
72
算法侠
MySQL
...广泛使用的开源关系型数据库管理系统,由Oracle公司开发并维护。在本文的语境中,用户需要了解如何从其操作系统中完全卸载MySQL,以便进行版本升级、更换其他数据库系统或解决相关问题。 caching_sha2_password身份验证插件 , 这是MySQL 8.0版本开始引入的一种新的默认密码加密和认证方式,相较于旧版的mysql_native_password,它提供了更高级别的安全性,使用SHA-256算法进行密码哈希,并支持缓存机制以提高连接性能。在文章提及的场景下,如果应用不支持此新插件,可能需要回退到旧版认证方式或者更新应用以适应新版MySQL的安全特性。 云服务(Cloud Service) , 在本文语境中,云服务是指通过互联网提供按需访问的共享计算资源和软件服务,无需直接管理底层基础设施。例如,阿里云RDS MySQL服务就是一种云服务产品,它允许用户在云端轻松部署、管理和维护MySQL数据库,而无需关心硬件购置、网络配置等复杂运维工作。此类服务通常具备高可用性、可扩展性和弹性伸缩等特点,使得用户可以根据业务需求快速调整资源配置,同时享受到自动备份、无缝升级等便利功能。
2023-09-27 12:06:50
55
码农
JQuery
...ml DOM结构。而连接HTML和关联事件是JQuery中最常用的两个作用之一。 // 运用JQuery连接html代码 var html = ""; $.each(data, function(index, item){ html += " " + item.title + " " + item.content + " "; }); $("container").html(html); 在这个例子中,我们运用JQuery的each方法对数据进行循环,每次循环都会创建一个包含题目和文本的item,并将它们连接到一个大字符串中。最终运用html方法将这个字符串呈现成DOM结构。 // 给动态创建的元素关联事件 $("container").on("click", ".item", function(){ // 点击item时的处理 }); 在这个例子中,我们运用JQuery的on方法给动态创建的元素关联事件。由于item元素是动态创建的,所以我们需要运用事件委托的方式进行关联。这样可以确保关联的元素都可以响应事件。
2023-12-04 09:15:37
395
逻辑鬼才
MySQL
...流程来开启MySQL数据库: 1. 开启指令行终端,进入MySQL的bin文件夹 cd /d C:\Program Files\MySQL\MySQL Server 8.0\bin 2. 执行以下指令来开启MySQL服务端 mysqld --console 3. 等候MySQL服务端开启结束,可以看到类似以下显示信息 2022-01-03T02:11:00.880724Z 0 [System] [MY-010116] [Server] C:\Program Files\MySQL\MySQL Server 8.0\bin\mysqld.exe (mysqld 8.0.29) starting as process 908 4. 开启新的指令行终端,进入MySQL的bin文件夹 cd /d C:\Program Files\MySQL\MySQL Server 8.0\bin 5. 执行以下指令来连接到MySQL服务端 mysql -u root -p 6. 输入MySQL的root用户密码,进入MySQL指令行界面 Enter password: 7. 成功连接到MySQL服务端后,可以执行各种MySQL指令来管理数据库了 通过以上流程,就可以在Windows操作OS下成功地开启MySQL数据库,并进入MySQL指令行界面来管理数据库了。
2023-12-12 11:10:15
135
数据库专家
Java
...编程、函数式编程以及数据库查询语句中的应用也非常重要。例如,在多线程环境下的锁机制实现时,常常会用到逻辑与(&&)来确保多个条件同时满足才进行特定操作,以避免竞态条件的发生;而在SQL查询中,WHERE子句中的AND、OR等逻辑运算符则是构建复杂查询的基础元素。 更进一步,逻辑运算符不仅仅局限于二元操作,还有诸如三元运算符(Ternary Operator)和逻辑非(Not Operator)等形式,它们在简化代码结构、增强可读性方面同样发挥着不可忽视的作用。因此,持续探索和实践逻辑运算符在不同编程场景下的应用,将有助于我们编写出更加精炼、高效且易于维护的代码。
2024-02-21 16:05:44
275
码农
JQuery
...pt编程语言中的基本数据结构之一,用于存储有序的元素集合,可以容纳任何类型的数据(包括数字、字符串、对象等)。数组中的每个元素可以通过其索引进行访问和操作,而.join()方法则是Array对象的一个内建方法,用于将数组的所有元素连接成一个字符串,元素之间可以自定义分隔符。 AJAX(Asynchronous JavaScript and XML) , AJAX是一种创建快速动态网页的技术,通过在后台与服务器交换少量数据并更新部分网页内容,而无需重新加载整个页面。在前端开发中,jQuery和其他库提供了对AJAX请求的便捷封装,尽管文章并未直接涉及AJAX,但.join()方法可用于序列化数据以准备发送至服务器,这是AJAX请求中的常见场景。例如,可以将用户填写的表单数据转换为字符串形式以便通过AJAX提交给后端处理。
2023-04-28 20:55:09
44
码农
Java
...如何在生产者消费者、数据库连接池等常见场景中合理运用Semaphore进行线程同步控制,从而避免死锁并优化系统性能。 此外,对于更复杂的同步问题,读者还可以进一步了解和研究其他Java并发工具类,例如ReentrantLock、CountDownLatch、CyclicBarrier等。这些工具通过灵活的设计和API,能够更好地适应不同场景下的同步需求,并帮助开发者编写出更加健壮、高效的多线程程序。 同时,值得注意的是,虽然诸如Semaphore这样的工具能有效解决同步问题,但过度依赖或不恰当使用也可能导致新的问题产生。因此,在实际开发过程中,理解并发编程的本质,遵循“最小权限原则”来设计线程间的交互,始终是提高程序并发能力的关键所在。在最新的Java版本更新中,也不断有针对并发特性的改进和完善,持续关注并跟进学习最新技术动态,将有助于开发者更好地应对高并发环境下的挑战。
2023-07-08 19:38:20
352
键盘勇士
MySQL
关系型数据库管理系统 , 关系型数据库管理系统(RDBMS)是一种用于存储、管理和检索数据的软件系统,其数据按照表格的形式组织,并通过预定义的关系连接在一起。在MySQL中,数据以行和列的形式存储在表内,且支持SQL(结构化查询语言)进行数据操作,如插入、更新、删除和查询等。结合文章语境,MySQL作为一个流行的关系型数据库管理系统,因其开放源代码和高度稳定性而被广泛应用于企业应用中。 终端(Terminal) , 终端在本文中的含义是操作系统提供的命令行界面,用户可以通过输入特定指令与系统交互,执行各种操作,如启动服务、管理文件等。在Linux环境下启动MySQL服务时,用户需要打开终端并输入相应的命令来启动或停止MySQL服务。 sudo命令 , sudo是一个在Unix/Linux操作系统中广泛使用的命令,全称为“SuperUser DO”,即超级用户执行。当普通用户使用sudo命令时,可以在经过系统权限验证后,暂时获得管理员权限去执行原本需要更高权限才能执行的命令。在启动或停止MySQL服务的过程中,由于涉及系统服务管理,因此需要通过sudo命令获取管理员权限来执行相应的启动/停止脚本。
2023-10-18 17:15:18
48
电脑达人
Docker
...卡进行通讯,达成网络连接。 $ docker run -it --net=host imageName 可以使用上面的指令来执行一个Docker容器,其中--net=host选项许可容器共享宿主机的网络命名空间,即使用宿主机的网络栈。 例如,如果你有一个Python应用软件在容器中执行,并且需要连接宿主机上的MySQL数据库,则可以使用以下代码来连接: import mysql.connector cnx = mysql.connector.connect(user='root', password='password', host='127.0.0.1', database='test', auth_plugin='mysql_native_password') cursor = cnx.cursor() 在这个示例中,Python应用软件在容器中执行,但是与宿主机共享网络,因此可以连接到宿主机上的MySQL数据库。 总而言之,在Docker中与宿主机共享网络是非常容易的。只需使用--net=host选项执行容器即可达成。这个特性在很多场景下非常有用,如连接数据库、调用API等。
2023-03-28 21:41:55
589
逻辑鬼才
MySQL
关系型数据库管理系统 , 关系型数据库管理系统(RDBMS)是一种用于存储、管理和检索数据的软件系统,其设计基于关系模型。在MySQL中,数据以表格的形式组织,表格之间通过预定义的关系相互连接,确保数据的一致性和完整性。用户可以使用SQL语句进行数据查询、更新和管理等操作。 SQL命令 , SQL(Structured Query Language)是一种专门用来与关系型数据库进行交互的标准计算机语言。在本文提到的MySQL环境下,诸如SHOW DATABASES、USE database、SHOW TABLES和DESCRIBE table等都是SQL命令的具体实例。它们分别用于展示所有数据库列表、切换到指定数据库、列出当前数据库中的所有表以及详细描述特定表的结构信息。 DESCRIBE 命令 , 在MySQL中,DESCRIBE或DESC命令用于获取一个已存在的表的详细结构信息。当执行这个命令并提供表名称时,MySQL将返回该表的所有字段名、字段类型、是否可为空、键类型以及其他可能的属性,如默认值和额外注释,帮助用户理解和维护表的内部结构。例如,在文中提及的“DESCRIBE table;”命令,将会显示“table”表的所有字段及其详细属性。
2023-08-18 09:15:20
63
算法侠
站内搜索
用于搜索本网站内部文章,支持栏目切换。
知识学习
实践的时候请根据实际情况谨慎操作。
随机学习一条linux命令:
date "+%Y-%m-%d %H:%M:%S"
- 显示当前日期时间。
推荐内容
推荐本栏目内的其它文章,看看还有哪些文章让你感兴趣。
2023-04-28
2023-08-09
2023-06-18
2023-04-14
2023-02-18
2023-04-17
2024-01-11
2023-10-03
2023-09-09
2023-06-13
2023-08-07
2023-03-11
历史内容
快速导航到对应月份的历史文章列表。
随便看看
拉到页底了吧,随便看看还有哪些文章你可能感兴趣。
时光飞逝
"流光容易把人抛,红了樱桃,绿了芭蕉。"