O2OA开发平台前端源码级二次开发(Vue3,React)

news2024/11/18 5:38:49

在使用O2OA进行项目定制化开发时,我们可以开发新的前端组件(x_component)以扩展O2OA来实现更多的业务。这种新增前端组件或者前端业务的开发通常会配合后端自定义应用实现的服务来完成系统内数据的交互。在当系统默认的界面不符合系统UI/UE设计需要,希望重新设计现有功能的前端展现时,我们也需要新增或者修改原有的组件源码。

上述要求我们除了使用O2OA平台的门户页面设计达到目标,针对于复杂的前端交互设计,开发属于自己的x_component也是一个有效的方式。

本文主要介绍几种前端二次开发的方式,以及与流行前端框架(Vue、React)的集成。

先决条件

  1. 获取到O2OA的源码,参照前面的课程所介绍的内容。

  2. 有一台运行的O2OA服务器,作为开发服务器。

  3. 开发机安装了Node.js环境,版本要求16及以上版本。

  4. 为了方便开发,最好有您熟悉的前端开发IDE工具,如WebStorm 或 VSCode。但这并不是强制的。本文后续的操作,我们以VSCode为例。

用VSCode打开O2OA的源码目录,并打开终端,输入以下命令:

npm install -g @o2oa/component-tools

image (15).png

image (15).png

此命令全局安装了@o2oa/component-tools,用于创建O2OAcomponent。建议每次需要创建component时运行此命令,以获取最新的更新。

然后进入o2web/source目录,然后运行npm install。

cd o2web/source

npm install

执行完成后,就可以创建component了。

o2oa原生方式的component

创建component组件

创建component的命令格式是:o2-cmpt create name ,其中的“name”就是要创建的component名称。如创建一个名为“custom.homepage”的component。

o2-cmpt create custom.homepage

image (16).png

运行后需要选择使用什么框架模式来创建component,目前支持两种方式:vue3、o2oa原生方式。(对于其它框架如react或者Angular的集成可以查询官方文档,有比较详细的步骤和说明。)

现在我们先介绍o2oa原生方式。选择“o2_native”然后回车,看到以下界面,就说明创建成功了。

image (17).png

此时就可以在目录列表中看到“x_component_custom_homepage”这个目录了。

image (18).png

展开目录后,看到文件结构是:

$Main/目录:存放静态文件资源,包括图标、css、html模板文件等

lp/目录:存放国际化语言包,zh-cn.js、en.js

Main.js:component入口js文件。

如果在运行命令时,使用的是windowss的PowerShell,可能会报错“…… 因为在此系统上禁止运行脚本……”的错误,有两个办法解决:1、用管理员权限打开Windows PowerShell,运行 set-executionpolicy remotesigned 命令,然后先择 Y ,回车即可运行脚本;2、是切换到Command,如下图:

image (19).png

部署组件

前端的打包部署使用了gulp,为了能快速部署组件到开发服务器,需要增加一个配置文件:o2web/gulpconfig.js,用于设置部署到服务器的信息。

内容如下:

module.exports = {
    "dev": {	//"dev"为配置名称
        'upload': 'sftp',	//sftp, ftp, 或 local
        'location': 'E:/o2server/servers/webServer/',	//本地服务器部署路径,仅upload为local时有效
        'host': 'px.o2oa.net',	//sftp或ftp时的服务器地址
        'user': 'root',					//sftp或ftp 的登录用户
        'pass': '********',	//sftp或ftp 登录用户的密码
        "port": 22,					//sftp或ftp 的端口
        "remotePath": "/data/o2server/servers/webServer/",	//sftp或ftp 的服务器部署路径
        "dest": "dest"	//打包后生成的本地路径
    }
};

上面的这个配置表示,如果在打包时传入"dev"作为参数的话,会自动打包,并通过sftp部署到px.o2oa.net服务器的“/data/o2server/servers/webServer/”路径下,这就是正在运行开发服务器的web路径,所以当我们部署上去后,就可以在开发服务器直接运行component了。

配置完成后,就可以运行打包部署脚本了:

gulp x_component_custom_homepage --ev dev

如果不出意外,运行正确后,出现下面的信息:

image (20).png

此时我们新创建的component就部署到开发服务器上了。

运行组件

然后就可以访问开发服务器查看custom.homepage的运行情况,有三种方法:

1、通过浏览器打开:http://hostaname/x_desktop/index.html?app=custom.homepage

2、通过浏览器打开:http://hostaname/x_desktop/app.html?app=custom.homepage

以上两种方法中的“hostname”替换为开发服务器地址。

3、通过浏览器打开:http://hostaname/x_desktop/index.html,然后用管理员身份登录,打开主菜单-系统设置

image (21).png

进入应用后选择“系统部署”,点击最后的“部署组件”:

image (22).png

然后填入合适的信息

image (23).png

组件名称:可随意填写,但不能与已有组件重名

组件标题:可随意填写,此信息其实已经无效,实际的组件标题会自动获取component的语言包的title数据。

组件路径:这个必须和我们创建组件时的名称一致,这个例子中,就是“custom.homepage”

组件图标:会自动获取component组件目录下的appicon.png

是否可见:表示此组件是否会在主菜单中出现。

可访问列表:可以选择个人、群组和角色,设定此组件只有哪些人可访问,为空时表示不限制,

拒绝访问列表:可以选择个人、群组和角色,设定此组件哪些人不可访问,为空时表示不限制,

当“可访问列表”和“拒绝访问列表”都为空时,表示所有人都可以访问。

填写好信息后,点击“部署组件”。

然后就可以在主菜单中看到这个组件了,点击就可以打开它。

image (24).png

打开后组件页面是这个样子的:

image (25).png

这个就是默认的O2OAcomponent组件,它主要实现了列示当前用户最新的5个待办,以及打开日程安排、打开组织管理,启动流程等样例功能。

组件源码介绍

在组件源码目录下的$Main/下存放了静态资源文件,几个主要文件如下:

appicon.png:作为组件在平台主菜单中显示的图标

default/style.css:组件使用的css文件,此文件的css内容仅对当前组件生效

lp/目录存放语言包文件,包含了zh-cn.js和en.js,其中的title就是组件显示的标题。

Main.js文件是组件的入口,它定义了一个类,我们简单介绍一下主要的方法和参数:

//这一行定义了custom.homepage组件是否可以在平台中打开多个窗口
MWF.xApplication.custom.homepage.options.multitask = false;

//此处定义了MWF.xApplication.custom.homepage.Main类,组件被打开时,会实例化这个类
MWF.xApplication.custom.homepage.Main = new Class({
  
  //它继承了MWF.xApplication.Common.Main类,这是系统定义的所有组件的基类
	Extends: MWF.xApplication.Common.Main,
  
	Implements: [Options, Events],

	options: {
		"style1": "default",
    //此处定义了组件使用的默认样式,它对应$Main/default目录,系统会自动加载对应目录的css和资源
		"style": "default",
		"name": "custom.homepage",	//组件的名称
		"mvcStyle": "style.css",	//要加载的css文件名
		"icon": "icon.png",				//图标的文件名
		"title": MWF.xApplication.custom.homepage.LP.title	//组件的标题,从lp/目录下的语言包获取
	},
  //此方法在组件被加载之前运行,此处只是赋值了语言信息
	onQueryLoad: function(){
		this.lp = MWF.xApplication.custom.homepage.LP;
	},
  
  //loadApplication是组件对象加载的入口方法,在此处为组件创建dom对象
  //一个最简单的组件,只需要实现此方法即可。它是组件中唯一一个必须要实现的方法
  //组件的this.conent是一个div容器,它是组件的容器对象,组件的所有dom元素都应该被this.conent包裹
	loadApplication: function(callback){
		var url = this.path+this.options.style+"/view.html";
		this.content.loadHtml(url, {"bind": {"lp": this.lp}, "module": this}, function(){
			this.loadTaskView();
		}.bind(this));
	},
  
  //---------------------------------------------------------------------
  //之后所有的方法都是当前组件特有的方法,这需要根据组件的功能自行添加
  
	loadTaskView: function(){
		o2.Actions.load("x_processplatform_assemble_surface").TaskAction.listMyPaging(1,5, function(json){
			debugger;
			this.taskListView.loadHtml(this.path+this.options.style+"/taskView.html", {"bind": {"lp": this.lp, "data": json.data}, "module": this}, function(){
				this.doSomething();
			}.bind(this));
		}.bind(this));
	},
	doSomething: function(){

	},
  //通过o2.api获取平台api运行环境,然后可以在api文档钟查询具体方法和对象的使用方法
	openTask: function(id, e, data){
		o2.api.page.openWork(id);
	},
	openCalendar: function(){
		o2.api.page.openApplication("Calendar");
	},
	openOrganization: function(){
		o2.api.page.openApplication("Org");
	},
	openInBrowser: function() {
		this.openInNewBrowser(true);
	},
	startProcess: function(){
		o2.api.page.startProcess();
	},
	createDocument: function(){
		o2.api.page.createDocument();
	}
});

接着来看一下 loadApplication 方法做了什么

loadApplication: function(callback){
  //先计算view.html的路径
  var url = this.path+this.options.style+"/view.html";
  
  //然后通过dom对象的loadHtml方法,将view.html的内容,渲染到this.content中。
  //在 view.html 内容被加载完成后,通过回调方法,调用loadTaskView方法。
  //loadHtml是O2OA为dom对象的一个扩展方法,它实现了一个简单的模板引擎。
  //第一个参数是要加载的html模板的url
  //第二个参数是options对象,其中bind是要绑定到模板的json格式数据,此处我们就是绑定了语言信息
  //		                    module是html中的元素要绑定到的组件。
  //第三个参数是加载完成后的回调函数。
  this.content.loadHtml(url, {"bind": {"lp": this.lp}, "module": this}, function(){
    this.loadTaskView();
  }.bind(this));
},

那就需要看一下view.html的内容了:

<div class="hello">
    <img class="logo" alt="O2OA logo" src="../x_component_Empty/$Main/default/icons/o2logo.png">
    <h1>{{ $.lp.welcome }}</h1>
    <p>
        For more O2OA development document,<br>
        check out the
        <a href="https://www.o2oa.net/develop.html" target="_blank" rel="noopener">O2OA develop documentation</a>.
    </p>

    <div class="task" data-o2-element="taskListView"></div>
</div>

其中的{{$.xxx}}的内容引用了绑定过来的bind信息。“$”就是绑定的数据(前面所说的bind的数据)。

其中data-o2-element属性是给这个dom对象一个名称,这样我们就可以在组件脚本中,通过this.[名称]获取到这个dom对象了。这个例子中,就是this.taskListView 了。

在view.html加载完成后,会执行 this.loadTaskView方法,那我们就详细看看这个方法

loadTaskView: function(){
  //o2.Actions对象的load方法可以载入指定上下文的后端服务,并将其转换为前端可调用的方法
  //所有的平台restful api,都可以通过http://develop.o2oa.net/x_program_center来查看
  //这里载入了x_processplatform_assemble_surface服务,此服务定义了与流程相关的一组restful api
  //TaskAction.listMyPaging方法用于获取当前用户的待办列表
  //第一个参数是获取待办的页码;第二个参数是每页获取几条待办;第三个参数的是获取成功的回调函数 
  o2.Actions.load("x_processplatform_assemble_surface").TaskAction.listMyPaging(1,5, function(json){
    //成功回调后,调用 this.taskListView.loadHtml方法,这里的this.taskListView就是上述view.html
    //中data-o2-element属性为“taskListView”的div元素。
    //通过loadHtml方法载入了taskView.html,并绑定json.data,json.data就是获取的待办列表对象数组
    this.taskListView.loadHtml(this.path+this.options.style+"/taskView.html", {"bind": {"lp": this.lp, "data": json.data}, "module": this}, function(){
      //载入taskView.html后,可以做一些其他事情...
      this.doSomething();
    }.bind(this));
  }.bind(this));
}

再来看看 taskView.html

<h3>{{$.lp.taskListTitle}}</h3>
<br>
<table align="center" class="taskListTable" border="1">
    <tr>
        <th>{{$.lp.taskTitle}}</th>
        <th>{{$.lp.taskProcess}}</th>
        <th>{{$.lp.taskTime}}</th>
    </tr>

    {{each $.data}}
    <tr>
        <td><a href="#" data-o2-events="click:openTask:{{$.work}}">{{$.title}}</a></td>
        <td>{{$.processName}}</td>
        <td>{{$.startTime}}</td>
    </tr>
    {{end each}}
</table>
<br>
<button data-o2-events="click:openCalendar">{{$.lp.openCalendar}}</button>
<button data-o2-events="click:openOrganization">{{$.lp.openOrganization}}</button>
<button data-o2-events="click:startProcess">{{$.lp.startProcess}}</button>
<br>
<button data-o2-events="click:openInBrowser">{{$.lp.openInBrowser}}</button>

这里有一个 {{each $.data}} 和 {{end each}},这代表循环$.data数据,并处理内部的html内容。$.data必须是一个可迭代的数据。

data-o2-events自定义属性用于绑定事件,属性值中,如果有多个事件绑定,使用分号“;”分隔,每个事件绑定的格式为:“事件名:方法:[参数1]:[参数2]...”,在loadHtml时,将component组件绑定到了“module”属性,所以这里的“方法”需要在component组件中定义。如: data-o2-events="click:openCalendar",在Main.js中就定义了这一个方法,用于打开日程安排组件。

openCalendar: function(){
  layout.openApplication(null, "Calendar");
}

组件修改

接着来修改组件内容,一般情况首先要修改的是组件标题,所以我们打开语言包,修改title内容:

//zh-cn.js
MWF.xApplication.custom.homepage.LP = {
	"title": "我的主页",
	"welcome": "Welcome to O2OA Component",
	"taskListTitle": "此处列出您的5个最新待办",

	"taskTitle": "标题",
	"taskProcess": "流程",
	"taskTime": "到达时间",

	"openCalendar": "打开日程管理",
	"openOrganization": "打开组织管理",
	"startProcess": "启动流程",
	"openInBrowser": "在新浏览器窗口中打开"
};


//en.js
MWF.xApplication.custom.homepage.LP = {
	"title": "MyHomepage",
	"welcome": "Welcome to O2OA Component",
	"taskListTitle": "Here are your top 5 task",

	"taskTitle": "Title",
	"taskProcess": "Process",
	"taskTime": "Time",

	"openCalendar": "Open Calendar",
	"openOrganization": "Open Organization",
	"startProcess": "Start Process",
	"openInBrowser": "Open In Browser"
};

保存后,再次运行部署命令:

gulp x_component_custom_homepage --ev dev

image (26).png

运行完成后在刷新浏览器就可以看到修改后的效果了。

每次修改后运行部署命令,是令人不愉快的,所以我们可以运行以下命令,来监听文件变化,并自动部署:

gulp watch --src x_component_custom_homepage --ev dev

之后每次修改组件的任何文件时,就会自动部署到开发环境“dev”了。

至此,native类型的component的框架搭建好了。

vue3类型的component

O2OA支持使用vue3创建component

创建组件

我们再次打开终端,到o2web/source目录,运行创建component命令,创建一个名为“custom.workplace”的component。

o2-cmpt create custom.workplace

然后选择“vue3”,会自动创建基于vue3的component。在安装完部分依赖之后,会询问几个问题:

1、需要输入开发服务器的hosts

2、需要输入开发服务器的center服务端口,默认是80

3、需要输入开发服务器的web服务端口,默认是80

4、确认开发服务器是否使用https,默认为 否(N)

其中开发服务器我们使用 px.o2oa.net, 其他选项都保持默认即可。

看到以下界面,说明component创建完成。

image (27).png

然后选择“vue3”,会自动创建基于vue3的component。在安装完部分依赖之后,会询问几个问题:

1、需要输入开发服务器的hosts

2、需要输入开发服务器的center服务端口,默认是80

3、需要输入开发服务器的web服务端口,默认是80

4、确认开发服务器是否使用https,默认为 否(N)

其中开发服务器我们使用 px.o2oa.net, 其他选项都保持默认即可。

看到以下界面,说明component创建完成。

image (28).png

此时就可以在目录列表中看到“x_component_custom_workplace”这个目录了。

image (29).png

展开目录后,就可以看到一个标准的vue应用的文件结构。其中有o2.config.js文件内容如下:

module.exports = {
    "server": {
        "host": "develop.o2oa.net",
        "port": "80",
        "httpPort": "80",
        "https": false
    }
}

这里的内容就是在创建component时询问的四个问题答案,它主要用于在启动本地开发服务器时,确定要连接的后端服务地址。我们可以随时修改这个配置,来连接不同的O2OA开发服务器。

在看到public/$Main/和public/lp/目录,这和原生component的$Main目录和lp目录内容完全一致。

运行组件

vue类型的component,是可以运行在本地开发服务器上的,所以我们只需要在组件目录下运行npm run serve即可

cd x_component_custom_workplace

npm run serve

运行后,会启动本地开发服务器,并自动打开浏览器,访问。

image (30).png

image (31).png

image (31).png

添加路由插件
我们还可以为vue component添加vue router插件,这和所有vue应用一样,可以通过vue ui添加,也可以使用命令:vue add router.

Shell复制代码

1

vue add router

image (32).png

如果有源码有未提交的commit,会提示,建议先提交后再安装插件。这里我们选择y,继续安装。

安装一些依赖包后,会询问是否使用histroy模式,此处我们选择 n ,使用 hash 模式。

image (33).png

接着安装完成,我们可以看到src目录下,增加了router/index.js和view/目录下的两个视图。

重新启动本地开发服务器:npm run serve,可以在浏览器中看到效果:

image (34).png

修改组件

此时再修改组件内容,如修改src/components/O2Task.vue文件,中的create()方法,将获取5个待办,改获取10个待办:

...
<script>
  ...

  created(){
  	//此处将第二个参数从5改为10
    o2.Actions.load("x_processplatform_assemble_surface").TaskAction.V2ListPaging(1, 10, null).then((json)=>{
      this.$data.taskList = json.data;
    });
  }

...
</script>
...

保存文件后,本地服务器会自动编译,浏览器会自动体现修改的内容。

image (35).png

image (35).png

这样我们就可以方便的开发component组件了。

集成自定义应用

部署组件

此时组件都是在本地服务器运行,要部署到服务器的方法和native类型的组件是一样的。在确保存在了gulpconfig.js文件,并正确配置后,在o2web/目录下运行gulp命令:

gulp x_component_custom_workplace --ev dev

就可以将组件部署到服务器了。

可以和native组件一样的方式,访问custom.workplace组件了。

React类型的component

O2OA支持使用React创建component组件,其方法与Vue3的组件非常类似。

创建组件

我们再次打开终端,到o2web/source目录,运行创建component命令,创建一个名为“custom.liveplace”的component。

o2-cmpt create custom.liveplace

image (36).png

然后选择“react”,就会自动创建基于React的component。在安装完部分依赖之后,同样会询问几个问题:

1、需要输入开发服务器的hosts

2、需要输入开发服务器的center服务端口,默认是80

3、需要输入开发服务器的web服务端口,默认是80

4、确认开发服务器是否使用https,默认为 否(N)

其中开发服务器我们使用 px.o2oa.net, 其他选项都保持默认即可。

image (37).png

看到以下界面,说明component创建完成。(React应用创建过程较长,需要耐心等待一下)

image (39).png

此时就可以在目录列表中看到“x_component_custom_liveplace”这个目录了。

image (40).png

展开目录后,就可以看到一个标准的React应用的文件结构。其中有o2.config.js文件内容如下:

module.exports = {
    "server": {
        "host": "develop.o2oa.net",
        "port": "80",
        "httpPort": "80",
        "https": false
    }
}

这里的内容就是在创建component时询问的四个问题答案,它主要用于在启动本地开发服务器时,确定要连接的后端服务地址。我们可以随时修改这个配置,来连接不同的O2OA开发服务器。

再看到public/$Main/和public/lp/目录,这和原生component的$Main目录和lp目录内容完全一致。

运行组件

React类型的component,是可以运行在本地开发服务器上的,所以我们只需要在组件目录下运行npm run start即可

cd x_component_custom_liveplace

npm run start

运行后,会启动本地开发服务器,并自动打开浏览器,访问。

image (41).png

image (42).png

此时可以修改组件源码,这里我们先修改一下欢迎信息。

修改中文语言信息:打开组件源码目录的public/lp/zh-cn.js,修改一下welcome:

MWF.xApplication.custom.liveplace.LP = {
    "title": "custom.liveplace",

    "welcome": "欢迎使用O2OA和React!",
    "taskListTitle": "此处列出您的5个最新待办",

    "taskTitle": "标题",
    "taskProcess": "流程",
    "taskTime": "到达时间",

    "openCalendar": "打开日程管理",
    "openOrganization": "打开组织管理",
    "startProcess": "启动流程",
    "createDocument": "创建信息",
    "openInBrowser": "在新浏览器窗口中打开"
}

刷新浏览器窗口后,就可以看到:

image (43).png

我们可以切换语言信息,来看一下,点击右上角的个人头像,点击“个人设置”,将“语言设置”改为“English”,“保存个人信息”后,刷新页面。

image (44).png

就可以看到,组件的语言信息,已经切换过来了:

image (45).png

接着就需要根据需求的内容,进行组件开发了。

部署组件

部署React类型的组件,也非常容易。和上述两种模式是一样的。

在确保存在了gulpconfig.js文件,并正确配置后,在o2web/目录下运行gulp命令:

gulp x_component_custom_liveplace --ev dev

就可以将组件部署到服务器了。

可以和native组件一样的方式,访问custom.liveplace组件了。

总结

  本文我们讲述了如何对O2OA进行前端的二次开发,介绍了创建O2OA component的方式,包括原生方式、基于Vue3的方式和基于React的方式。各种O2OA component脚手架工具帮助开发者更方便地搭建了O2OA组件的开发框架。无论那种方式,都完整的保留了O2OA平台的所有可用API,认证体系,多语言特性、后端服务方法转换等特性,使开发者可以更好地专注于需要实现的业务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1637324.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Sentinel 控制台学习

引言 上篇文章已经讲过 SpringCloud Sentinel集成到微服务项目中&#xff0c;接下来我们继续学习怎么使用sentinel控制台对微服务进行限流&#xff0c;熔断&#xff0c;降级等一系列操作。 控制台 接下来我们单独讲解每一个菜单按钮 实时监控 实时监控&#xff1a; 可以看到…

Leetcode 145:二叉树的后序遍历(迭代法)

给你一棵二叉树的根节点 root &#xff0c;返回其节点值的 后序遍历 。 思路&#xff1a; 迭代法的思路是&#xff0c;使用栈&#xff0c;一层一层的将树节点遍历入栈。 比如下面这个树&#xff0c;使用迭代法&#xff0c;1&#xff09;第一层&#xff0c;让根节点入栈。2&a…

2024深圳杯数学建模竞赛A题(东三省数学建模竞赛A题):建立火箭残骸音爆多源定位模型

更新完整代码和成品完整论文 《2024深圳杯&东三省数学建模思路代码成品论文》↓↓↓&#xff08;浏览器打开&#xff09; https://www.yuque.com/u42168770/qv6z0d/zx70edxvbv7rheu7?singleDoc# 2024深圳杯数学建模竞赛A题&#xff08;东三省数学建模竞赛A题&#xff0…

2024五一杯数学建模A题思路分析-钢板最优切割路径问题

文章目录 1 赛题选题分析 2 解题思路3 最新思路更新 1 赛题 A题 钢板最优切割路径问题 提高钢板下料切割过程中的工作效率&#xff0c;是模具加工企业降低成本和增加经济效益的重要途径&#xff0c;其中钢板切割的路径规划是钢板切割过程的一个关键环节。 钢板切割就是使用特殊…

附录6-1 黑马优购项目-组件与过滤器

目录 1 过滤器-格式化价格 2 组件-搜索框 3 组件-数量框 4 组件-商品概况 4.1 格式化价格 4.2 选择性使用勾选框和数量框 4.3 源码 1 过滤器-格式化价格 这个项目中仅用到格式化价格这一种过滤器。过滤器文件位置为store/filter.wxs 文件内容是这样的&#xf…

【嵌入式DIY实例】-植物自动浇水机

DIY自动植物浇水机 文章目录 DIY自动植物浇水机1、硬件准备与接线2、代码实现智能灌溉系统是一种先进的、新技术的灌溉技术,可以减少人力、时间等。在本文中,将介绍如何实现一个植物自动浇水机。通过这个项目,可以给我们身边的一些植物,所有花盆都安装这一系统。这个系统由…

【JavaEE初阶系列】——理解tomcat 带你实现最简单的Servlet的hello world程序(七大步骤)

目录 &#x1f6a9;认识Tomcat &#x1f6a9;运用Tomcat &#x1f6a9;Servlet &#x1f393;完成简单的Servlet的hello world程序 &#x1f388;创建项目Maven &#x1f388;引入依赖 &#x1f388;创建目录 &#x1f388;编写代码 &#x1f388;打包程序 &#x1…

关于用户体验和设计思维

介绍 要开发有效的原型并为用户提供出色的体验&#xff0c;了解用户体验 (UX) 和设计思维的原则至关重要。 用户体验是用户与产品、服务或系统交互并获得相应体验的过程。 设计思维是一种解决问题的方法&#xff0c;侧重于创新和创造。 在启动期实现用户体验和设计思维时&#…

头歌:SparkSQL简单使用

第1关&#xff1a;SparkSQL初识 任务描述 本关任务&#xff1a;编写一个sparksql基础程序。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1. 什么是SparkSQL 2. 什么是SparkSession。 什么是SparkSQL Spark SQL是用来操作结构化和半结构化数据的接口。…

Tuxera NTFS使用教程 轻松实现磁盘格式转换的教程分享 ntfsMac软件怎么用

NTFS for Mac是Mac电脑里非常重要的工具之一&#xff0c;因为它太实用了&#xff0c;解决了NTFS移动硬盘在Mac上的写入问题。但是&#xff0c;小伙伴在安装完软件之后&#xff0c;通常再也不会关注它&#xff0c;甚至时间长了&#xff0c;也就忘了Mac里还有这么一个软件。 在Tu…

GB32960解析工具

几年前搞了一个用Qt开发的国标32960报文解析工具。分享给大家&#xff0c;只用1积分便可以下载。 国标32960新能源车协议解析工具资源-CSDN文库

(附源码)超级简单的SSM图书交易系统,包含技术栈、架构图、设计图、教程

先看首页效果&#xff0c;包含买家、卖家、管理员三个端口。启动有问题可以联系我解决&#xff0c;微信&#xff1a;keepgoing4u 架构图&#xff1a; 用到软件 Jdk1.8 Mysql IntelliJ IDEA Maven 项目技术&#xff1a; Spring Boot SSM JSP mybatis Maven B/S模式 配置…

云服务器的主要用途有哪些,使用云服务器具有哪些方面的优势

随着科技的飞速发展&#xff0c;云计算已经成为现代企业和个人用户不可或缺的技术支持&#xff0c;云计算技术已经逐渐渗透到我们生活的方方面面。云服务器作为云计算的核心组成部分&#xff0c;正在逐步改变我们的数据存储和处理方式&#xff0c;成为各类互联网用户实现综合业…

前端vite+rollup前端监控初始化——封装基础fmp消耗时间的npm包并且发布npm beta版本

文章目录 ⭐前言&#x1f496;vue3系列文章 ⭐初始化npm项目&#x1f496;type为module&#x1f496;rollup.config.js ⭐封装fmp耗时计算的class&#x1f496;npm build打包class对象 ⭐发布npm的beta版本&#x1f496; npm发布beta版本 ⭐安装web-performance-tool的beta版本…

2024年第二十一届 五一杯 (B题)大学生数学建模挑战赛 | 最大流问题,深度学习分析 | 数学建模完整代码解析

DeepVisionary 每日深度学习前沿科技推送&顶会论文&数学建模与科技信息前沿资讯分享&#xff0c;与你一起了解前沿科技知识&#xff01; 本次DeepVisionary带来的是五一杯的详细解读&#xff1a; 完整内容可以在文章末尾全文免费领取&阅读&#xff01; 第一个问题…

算法效率的判断及一些典型例题的讲解

一.算法效率 1.用处&#xff1a;判断算法的好坏&#xff0c;好的算法应该是高效的 2算法效率取决于时间复杂度和空间复杂度 <1>时间复杂度 1.1概念&#xff1a;算法中基本操作的执行次数就是算法的时间复杂度 1.2表示&#xff1a;大O的渐进表示法&#xff0c;例如O(N)…

什么是场内期权,场内期权是如何操作的?

今天期权懂带你了解什么是场内期权,场内期权是如何操作的&#xff1f;场内期权是标准化、规范化且在公开市场交易的金融衍生品。相比场外期权&#xff0c;场内期权具有更高的流动性和透明度。 什么是场内期权&#xff1f; 场内期权&#xff0c;也称为交易所期权&#xff0c;是…

【C++航海王:追寻罗杰的编程之路】C++11(四)

目录 1 -> 相关文章 【C航海王&#xff1a;追寻罗杰的编程之路】C11(一) 【C航海王&#xff1a;追寻罗杰的编程之路】C11(二) 【C航海王&#xff1a;追寻罗杰的编程之路】C11(三) 2 -> lambda表达式 2.1 -> C98中的一个例子 2.2 -> lambda表达式 2.3 ->…

HCIA-题目解析1

0x00 前言 遇到这样一道题,这种题目对于我来说还是比较复杂的,所以记录一下。主要还是和熟练度有关系。 0x01 题目 路由器RouterID邻居关系如下,下列说法正确的是 A:本路由器和Router-lD为10.0.3.3的路由器不能直接交换链路状态信息 B:DR路由器的Router-lD为10.0.1.2 C:…

Flutter运行项目一直:running gradle task

大体原因就是访问国外的资源由于网络等原因导致访问失败&#xff0c;解决方法就是换成国内的源 修改项目的android/build.gradle 文件&#xff0c;将里面的 google() mavenCentral()替换为 maven {allowInsecureProtocol trueurl https://maven.aliyun.com/repository/googl…