- 浏览: 552987 次
- 性别:
- 来自: 北京
-
文章分类
- 全部博客 (740)
- css (4)
- jquery (8)
- javascript (23)
- html (0)
- uml (0)
- 设计模式 (1)
- 开发工具 (14)
- json (4)
- struts 1.x (3)
- spring (3)
- hibernate (6)
- struts 2.x (17)
- JFreechart (0)
- j2se (48)
- jsp (9)
- flex (22)
- 找工作 (1)
- 技术杂谈 (18)
- 网络编程 (5)
- io流 (1)
- ORACLE (15)
- 报表 (3)
- extjs (11)
- jpbm (2)
- swing (5)
- jspereports (3)
- sql (1)
- linux (15)
- ps (1)
- storm (4)
- hbase (8)
- li (0)
- python (1)
- hive (3)
- 机器学习 (1)
- hdfs (1)
- elasticsearch (1)
- hadoop 2.2 (5)
- hadoop (1)
最新评论
-
Tristan_S:
这个有点意思
ASM -
starryskydog:
程序修改detail band部分的样式 如内容字体大小 ...
使用jasperReport实现动态表头 -
samwong:
Good, so usefule
使用YUI Compressor压缩CSS/JS -
gc715409742:
能够告诉我怎么在web项目中使用YUI Compressor? ...
使用YUI Compressor压缩CSS/JS -
JsonTeye:
您好! 我看你的代码,我现在也在做动态报表,实现功能由用户自己 ...
使用jasperreport动态生成pdf,excel,html
摘要:这篇文章描述了在Eclipse RCP中引入依赖注射机制的一个简单方法。为了避免污染Eclipse平台的基础设施并且透明的为RCP添加IoC框架,我们使用了动态字节码操作(使用 ObjectWeb ASM类库),Java类加载agent以及Java标注技术的组合。
Eclipse胖客户端平台(Rich Client Platform,RCP)是一个功能强大的软件基础(software foundation),它基于相互联系并协作的插件,允许开发人员创建通用的应用程序。RCP使得开发人员可以更加关注应用程序的业务逻辑而不是花大量 时间来重新发明轮子去编写大量的应用程序管理逻辑。
控制翻转(IOC)和依赖注射是一种减少程序耦合性的设计模式。它们遵循了一个简单的原则:你不必自己创建对象,你只需要描述如何创建对象。你不必去实例 化或者定位你的组件需要的服务,你只需要去描述哪个组件需要哪个服务,其他组件(通常是容器)来负责将它组装好。这也就是著名的好莱坞原则:不要打电话给 我们,我们会打给你。
这篇文章描述了在Eclipse RCP中引入依赖注射机制的一个简单方法。为了避免污染Eclipse平台的基础设施并且透明的为RCP添加IoC框架,我们使用了动态字节码操作(使用 ObjectWeb ASM类库),Java类加载agent以及Java标注技术的组合。
什么是Eclipse胖客户端平台?
简单来说,Eclipse胖客户端平台是一组类库,软件框架以及运行环境,它可以用来创建独立运行并且经常需要与网络交互的应用程序。
尽管Eclipse是作为一个集成开发环境(IDE)框架设计的,但是,从3.0版本开始,整个项目已经被重构成各种独立的组件,以便于可以使用这些组件 的一个子集来构建任意的应用程序。这个子集构成了RCP,它包含以下几种组件:基本运行环境,用户接口组件(SWT和JFace),插件以及OSGi层。 图1展示了Eclipse平台的主要组件。
整个Eclipse平台是基于插件和扩展点(extensions points)这样一个关键概念的。一个插件是可以独立开发和发布的功能的最小单元。它一般会打包成一个jar文件并且通过增加功能来扩充Eclipse 平台(例如,增加一个编辑器,工具栏按钮或者一个编译器)。整个平台就是一组互相联系并通讯的一组插件的集合。一个扩展点是一个已经存在的互相联系的端 点,可以被其他插件用来添加功能(功能:在Eclipse术语中叫做扩展)。扩展和扩展点通过XML配置文件定义并绑定在插件中。
尽管插件已经使用了关注点分离这样一个重要的模式,但是插件之间的强相互联系和通讯会导致他们之间的强依赖关系。一个典型的例子就是需要定位应用程序需要 的各种单例(Singleton)服务,例如数据库连接池,日志处理器,或者用户偏爱(preference)的设置信息的保存等。控制反转和依赖注射是 消除这些依赖的可行解决方案。
控制反转和依赖注射
+控制反转是一种设计模式,它主要关注如何将服务(或者应用程序组件)的定义和服务如何定位它们依赖的服务进行分离。为了完成这种分离,一般都会依赖一个 容器,或者定位框架(locator framework),维护现存服务的列表+提供一种方法来将组件和它们依赖的服务绑定在一起。
+提供一种方法让应用程序代码可以请求一个已经配置好的对象(例如,一个所有依赖都已经满足的对象),这样就可以保证该对象所有相关的服务都已经可用了。
现存的框架一般都使用下面三种基本技术的组合来绑定服务和组件:
+类型一(基于接口):服务对象需要实现一个专门的接口,这个接口为这些服务对象提供了一个对象,服务可以通过这个对象来查询它们的依赖。这是一些早期的 容器使用的模式,例如Excalibur. +类型二(基于setter):通过JavaBean属性的setter方法将依赖的服务赋值给服务对象。HiveMind和Spring都是通过这种方 式来实现的。
+类型三(基于构造函数):依赖的服务通过构造函数的参数提供(不通过JavaBean属性暴露)。这是PicoContainer使用的唯一方式。HiveMind和Spring也使用了这种方式。
我们将采用第二种方式的变种,通过带标注的方法来提供服务。(示例应用的源代码在资源中可以找到)。声明依赖可以采用以下方式:
@Injected public void aServicingMethod( Service s1, AnotherService s2) { // save s1 and s2 into class variables // to use them when needed}
控制反转容器会查找Injected标注并且使用需要的参数来调用这个方法。在我们为Eclipse平台引入IoC的过程中,在服务和可服务对象间建立绑 定关系的代码被封装在一个Eclipse插件中。这个插件定义了一个扩展点 (com.onjava.servicelocator.servicefactory),用来为应用程序提供服务工厂。当一个可服务对象需要配置时,插 件会向工厂请求服务的实例。正如下面的代码,ServiceLocator类将会完成所有的工作。(我们会跳过那些处理扩展点解析的代码,因为这些代码会 很简单)
/** * Injects the requested dependencies into the * parameter object. It scans the serviceable * object looking for methods tagged with the * {@link Injected} annotation.Parameter types are * extracted from the matching method. An instance * of each type is created from the registered * factories (see {@link IServiceFactory})。 When * instances for all the parameter types have been * created the method is invoked and the next one * is examined. * * @param serviceable the object to be serviced * @throws ServiceException */
public static void service(Object serviceable) throws ServiceException {
ServiceLocator sl = getInstance();
if (sl.isAlreadyServiced(serviceable)) {
// prevent multiple initializations due to
// constructor hierarchies
System.out.println( "Object " + serviceable + " has already been configured ");
return; }
System.out.println("Configuring " + serviceable);
// Parse the class for the requested services
for (Method m : serviceable.getClass()。getMethods()) {
boolean skip=false;
Injected ann=m.getAnnotation(Injected.class)
; if (ann != null) {
Object[] services = new Object[m.getParameterTypes()。length];
int i = 0;
for(Class<?> klass :m.getParameterTypes()){
IServiceFactory factory = sl.getFactory(klass,ann.optional());
if (factory == null) {
skip = true;
break; }
Object service = factory.getServiceInstance();
// sanity check: verify that the returned
// service's class is the expected one
// from the method
assert(service.getClass()。equals(klass) || klass.isAssignableFrom(service.getClass()));
services[i++] = service ; }
try {
if (!skip)
m.invoke(serviceable, services); }
catch(IllegalAccessException iae) {
if (!ann.optional())
throw new ServiceException( "Unable to initialize services on " + serviceable + ": " + iae.getMessage(),iae); }
catch(InvocationTargetException ite) {
if (!ann.optional())
throw new ServiceException( "Unable to initialize services on " + serviceable + ": " + ite.getMessage(),ite); } } }
sl.setAsServiced(serviceable);}
既然这个服务工厂返回的服务同样可以是一个可服务对象,这个策略允许定义一种服务层次(但是,目前并不提供对循环依赖的支持)。
ASM and java.lang.instrument Agents
以上介绍的各种注射策略都依赖于容器的存在,依赖容器提供一个入口点来使得应用程序可以使用该入口点来请求已经得到正确配置的对象。但是,我们想在开发我 们的IoC插件的时候使用一种透明的方式,这主要有两个原因:+RCP采用了复杂的classloader以及初始化策略(考虑一下 createExecutableExtension())来维护插件的隔离性以及可见性的限制。我们不想修改或者替代这种策略来引入我们的基于容器的初 始化规则。
+对这样一个入口点(这个例子中,是service locator插件中定义的service()方法)的显式引用将会强迫应用程序开发人员采用一种显式的模式和逻辑来获取初始化的组件。这样就会有一些应 用-锁定的类库出现在程序代码中。我们想要定义一个合作的插件,这个插件并不需要显示的引用这些代码。
出于以上原因,我们要引入定义在java.lang.instrument包中的Java转换代理,这个包出现在J2SE5.0以及以后的版本中。一个转 换代理是一个实现了java.lang.instrument.ClassFileTransformer接口的对象,这个接口只有唯一一个方法, transform()。当一个转换器的实例注册到JVM中后,当JVM要创建任何类的时候,这个代理的transform()会被调用。转换器可以在 JVM加载类之前访问这个类的字节码并且可以对其进行修改。
转换代理可以采用-javaagent:jarpath[=options]的形式的命令行参数来注册到JVM,其中jarpath是包含了这个代理类的 JAR文件,options是传递给该代理的一个参数字符串。这个代理JAR文件使用一个特殊的MANIFEST属性来指明真正的代理类,这个代理类必须 定义一个public static void premain(String options, Instrumentation inst)方法。这个premain()方法将会在应用程序的main方法被调用之前调用,并且将一个真正的变换器注册到传递进来的 java.lang.instrument.Instrumentation类的实例中。
在我们的示例程序中,我们定义一个代理来透明的进行字节码操作并且动态的调用我们的IoC容器(service vlocator插件)。这个代理会通过检验是否存在Serviceable标注来确定一个可服务对象。然后,修改所有的构造函数来调用IoC容器的方法 在对象初始化时正确地配置和初始化这个对象。
让我们假设我们有一个需要依赖于其他服务的对象(还记得Injected标注吗?):@Serviceablepublic class ServiceableObject { public ServiceableObject() { System.out.println("Initializing……"); } @Injected public void aServicingMethod( Service s1, AnotherService s2) { // …… omissis …… }}
当它被转换代理操作以后,它的字节码会和下面这个进行正常编译的类的字节码一样:@Serviceablepublic class ServiceableObject { public ServiceableObject() { ServiceLocator.service(this); System.out.println("Initializing……"); } @Injected public void aServicingMethod( Service s1, AnotherService s2) { // …… omissis …… }}
通过这种解决方案,我们不必将对容器的依赖进行硬编码就可以配置一个可服务对象并且使他们可用。开发人员仅仅需要在可服务对象类上使用 Serviceable标注就可以了,变换代理的代码如下:public class IOCTransformer implements ClassFileTransformer { public byte[] transform( ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { System.out.println("Loading " + className); ClassReader creader = new ClassReader(classfileBuffer); // Parse the class file ConstructorVisitor cv = new ConstructorVisitor(); ClassAnnotationVisitor cav = new ClassAnnotationVisitor(cv); creader.accept(cav, true); if (cv.getConstructors()。size() > 0) { System.out.println("Enhancing "+className); // Generate the enhanced-constructor class ClassWriter cw = new ClassWriter(false); ClassConstructorWriter writer = new ClassConstructorWriter( cv.getConstructors(), cw); creader.accept(writer, false); return cw.toByteArray(); } else return null; } public static void premain(String agentArgs, Instrumentation inst) { inst.addTransformer(new IOCTransformer()); }}
其中ConstructorVisitor, ClassAnnotationVisitor, ClassWriter以及 ClassConstructorWriter这几个类使用ObjectWeb ASM类库来进行字节码操作。
ASM使用访问者模式来将类数据(包括指令序列)作为事件流处理。当解码一个已经存在的类时,ASM为我们产生事件流,调用我们的方法来处理事件。当生成 一个新类的时候,采用相反的过程:我们产生一个事件流,ASM类库将它转化成一个类。注意我们描述的这个方法并不依赖于特定的字节码类库(我们这里用了 ASM),其他的解决方案,例如BCEL和Javassist同样可以工作。
我们不想深究ASM的内部机制。对于本文的目的来说,知道ConstructorVisitor和ClassAnnotationVisitor对象是用来确定使用了Serviceable标注的类并且收集他们的构造函数就足够了。它们的代码如下:
public class ClassAnnotationVisitor extends ClassAdapter { private boolean matches = false; public ClassAnnotationVisitor(ClassVisitor cv) { super(cv); } @Override public AnnotationVisitor visitAnnotation( String desc, boolean visible) { if (visible && desc.equals("Lcom/onjava/servicelocator/annot/Serviceable;")) { matches = true; } return super.visitAnnotation(desc, visible); } @Override public MethodVisitor visitMethod( int access, String name, String desc, String signature, String[] exceptions) { if (matches) return super.visitMethod( access,name,desc,signature,exceptions); else { return null; } } }public class ConstructorVisitor extends EmptyVisitor { private Set<Method> constructors; public ConstructorVisitor() { constructors = new HashSet<Method>(); } public Set<Method> getConstructors() { return constructors; } @Override public MethodVisitor visitMethod( int access, String name, String desc, String signature, String[] exceptions) { Type t = Type.getReturnType(desc); if (name.indexOf("<init>") != -1 && t.equals(Type.VOID_TYPE)) { constructors.add(new Method(name,desc)); } return super.visitMethod( access,name,desc,signature,exceptions); }}
对于上述类收集到的每一个构造函数,使用一个ClassConstructorWriter类的实例来修改构造函数的字节码,注入对service locator插件的调用:com.onjava.servicelocator.ServiceLocator.service(this);
采用ASM方式完成上述工作需要以下代码:// mv is an ASM method visitor,// a class which allows method manipulationmv.visitVarInsn(ALOAD, 0);mv.visitMethodInsn( INVOKESTATIC, "com/onjava/servicelocator/ServiceLocator", "service", "(Ljava/lang/Object;)V");
第一个指令将第二个指令需要使用的this对象的引用放在堆栈上,第二个指令将调用ServiceLocator的一个静态方法。
一个示例Eclipse RCP应用我们现在已经具有了所有创建应用程序的元素,我们的示例代码用来向用户显示有趣的警句和引用,就像fortune cookies一样。它包含了四个插件:+service locator插件,提供Ioc框架的功能+FortuneService插件,提供了管理fortune cookies的服务。
+FortuneInterface插件,发布访问服务需要的公共接口。
+客户端插件,作为Eclipse应用在一个Eclipse视图中显示格式化的警句。
我们采用的IoC设计使得服务的实现和客户端分离,服务的实现可以改变或者修改,而客户端却不受影响。
就像上面几节描述的那样,为了向用户显示警句,service locator将会将客户和服务绑定在一起。FortuneInterface仅仅定义一个公有的接口,用户可以使用它来访问cookie消息。
public interface IFortuneCookie { public String getMessage();}
Fortune插件提供了一个简单的服务工厂来创建IFortuneCookie的实现类的实例。
public class FortuneServiceFactory implements IServiceFactory { public Object getServiceInstance() throws ServiceException { return new FortuneCookieImpl(); } // …… omissis ……}
工厂作为一个Eclipse扩展注册到service locator,就像它的plugin.xml中描述的一样。
<?xml version="1.0" encoding="UTF-8"?><?eclipse version="3.0"?><plugin><extension point="com.onjava.servicelocator.servicefactory"> <serviceFactory class="com.onjava.fortuneservice.FortuneServiceFactory" id="com.onjava.fortuneservice.FortuneServiceFactory" name="Fortune Service Factory" resourceClass="com.onjava.fortuneservice.IFortuneCookie"/></extension></plugin>
这里,resourceClass属性定义了这个工厂提供的服务类。描述的服务被FortuneClient插件中的Eclipse视图使用。
@Serviceablepublic class View extends ViewPart { public static final String ID = "FortuneClient.view"; private IFortuneCookie cookie; @Injected(optional=false) public void setDate(IFortuneCookie cookie) { this.cookie = cookie; } public void createPartControl(Composite parent){ Label l = new Label(parent,SWT.WRAP); l.setText("Your fortune cookie is:n" + cookie.getMessage()); } public void setFocus() {}}
注意要加上Serviceable和Injected标注来定义对其他服务的依赖,但是不需要引用提供这些服务的代码。最后的结果是createPartControl()可以自由得使用cookie对象而且可以保证cookie是正确初始化过的。
结论
在这篇文章中,我们讨论了如何将一种强大的设计模式(可以简化代码依赖的处理,IoC)与一种可以加速Java客户端应用程序开发的技术合并在一起。虽然 我没有处理更多于这个问题有关的细节,但是我也已经演示了一个示例应用如何将服务和服务客户解耦。我同时也描述了Eclipse插件技术在开发客户端和服 务时如何做到了关注点分离。但是,仍然有很多有趣的元素在等待我们探索,例如清除策略,用来在不需要这个服务的时候清除掉服务,或者在我们的客户插件中使 用mock-up服务来进行单元测试,这些要留给读者去研究了。
Resources +本文的示例代码+Eclipse.org网站上的Eclipse RCP教程+ASM网站上的ASM 2.0介绍+Matrix,与Java共舞+http://www.onjava.com
发表评论
-
使用Java调用谷歌搜索
2013-10-19 12:50 905转自:http://yangshangchuan.iteye ... -
走出类加载器迷宫
2013-10-16 14:22 698这是前几天在看类加载器机制时搜到的一篇旧文,网上搜了搜 ... -
Log4j使用
2012-12-05 11:34 795... -
Java的JDBC数据库连接池实现方法
2012-09-14 10:20 751虽然J2EE程序员一般都有现成的应用服务器所带的JDBC数据库 ... -
什么是线程安全和线程不安全
2012-08-23 14:49 801什么是线程安全和线程 ... -
线程运行栈信息的获取
2012-08-23 14:49 840线程运行栈信息的获取 ... -
log4j 获取行号
2012-08-23 14:50 1167log4jjava 今天看log4j的日志,突然注意到log ... -
javassist【动态改字节码】学习三
2012-08-23 14:50 2678这里举个简单的例子,来记录下如何用CtClass创建一个类,并 ... -
javassist【动态改字节码】学习二
2012-08-22 11:53 845写了个例子。 有一个类: Java代码 package ... -
javassist[动态改字节码]学习一
2012-08-22 11:52 920前段时间为了公司里的 ... -
JVM启动参数
2012-08-22 11:51 956一、标准参数 1.-server -client 虚拟机服务器 ... -
使用javassist动态注入代码
2012-08-22 11:33 792关于java字节码的处理,目前有很多工具,如bcel,asm。 ... -
利用javaassist修改Class文件
2012-08-22 11:22 1510我们在开发中有时候会遇到这样的问题,就是使用的某个第三方包中的 ... -
JavaMail
2012-08-16 20:03 954在Java EE应用程序中,经常需要发送E-mail。Java ... -
让java变成脚本语言
2012-08-15 12:42 0今天在弄游戏的GM模块,大部分gm命令很简单,只是单纯改 ... -
JavaAgent
2012-08-13 23:43 1289-javaagent 这个JVM参数是JDK 5引进的. j ... -
aop的几种实现方式
2012-08-05 21:14 9521 AOP各种的实现 AOP就是面向切面编程,我们可以从 ... -
Java编程中“为了性能”尽量要做到的一些地方
2012-07-28 21:36 600http://www.iteye.com/magazines/ ... -
java基础拾遗
2012-06-17 10:05 885. 电梯直达 楼主 发表于 2012-1-28 13: ... -
使用 HttpClient 和 HtmlParser 实现简易爬
2012-05-01 17:57 1107使用 HttpClient 和 HtmlParse ...
相关推荐
在Eclipse RCP中实现控制反转(IoC)是一种提高应用程序可维护性和可扩展性的重要设计策略。控制反转(Inversion of Control,IoC)和依赖注射(Dependency Injection,DI)是面向对象编程中降低模块间耦合的技术,...
反转控制(InversionofControl,IoC)和依赖注入(DependencyInjection,DI)是两种编程模式,可用于减少程序间的耦合。它们遵循一个简单的原则:你不要创建你的对象;你描述它们应当如何被创建。你不要实例化你的部件所...
学习RCP时搜集的资料 Eclipse RCP上的国际化技术 Eclipse 平台入门 打造您的 Eclipse RCP 产品 富客户机应用程序的性能 设计实现...eJFace 开发嵌入式应用程序 在Eclipse RCP中实现反转控制(IoC)
- **IoC(Inversion of Control,控制反转)**:Spring的核心特性之一,它将对象的创建和管理职责从应用代码中分离出来,使得代码更易于测试和维护。 - **AOP(Aspect Oriented Programming,面向切面编程)**:...
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
ACM动态规划模板-区间修改线段树问题模板
# 踏入C语言的奇妙编程世界 在编程的广阔宇宙中,C语言宛如一颗璀璨恒星,以其独特魅力与强大功能,始终占据着不可替代的地位。无论你是编程小白,还是有一定基础想进一步提升的开发者,C语言都值得深入探索。 C语言的高效性与可移植性令人瞩目。它能直接操控硬件,执行速度快,是系统软件、嵌入式开发的首选。同时,代码可在不同操作系统和硬件平台间轻松移植,极大节省开发成本。 学习C语言,能让你深入理解计算机底层原理,培养逻辑思维和问题解决能力。掌握C语言后,再学习其他编程语言也会事半功倍。 现在,让我们一起开启C语言学习之旅。这里有丰富教程、实用案例、详细代码解析,助你逐步掌握C语言核心知识和编程技巧。别再犹豫,加入我们,在C语言的海洋中尽情遨游,挖掘无限可能,为未来的编程之路打下坚实基础!
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
本项目为Python语言开发的PersonRelationKnowledgeGraph设计源码,总计包含49个文件,涵盖19个.pyc字节码文件、12个.py源代码文件、8个.txt文本文件、3个.xml配置文件、3个.png图片文件、2个.md标记文件、1个.iml项目配置文件、1个.cfg配置文件。该源码库旨在构建一个用于表示和查询人物关系的知识图谱系统。
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
rtsp实时预览接口URL:/evo-apigw/admin/API/MTS/Video/StartVideo HLS、FLV、RTMP实时预览接口方式 :接口URL/evo-apigw/admin/API/video/stream/realtime 参数名 必选 类型 说明 data true string Json串 +channelId true string 视频通道编码 +streamType true string 码流类型:1=主码流, 2=辅码流,3=辅码流2 +type true string 协议类型:hls,hlss,flv,flvs,ws_flv,wss_flv,rtmp hls:http协议,m3u8格式,端口7086; hlss:https协议,m3u8格式,端口是7096; flv:http协议,flv格式,端口7886; flvs:https协议,flv格式,端口是7896; ws_flv:ws协议,flv格式,端口是7886; wss_flv:wss协议,flv格式,端口是7896; rtmp:rtmp协议,端口是1975;
Simulink永磁风机飞轮储能系统二次调频技术研究:频率特性分析与参数优化,Simulink永磁风机飞轮储能二次调频技术:系统频率特性详解及参数优化研究参考详实文献及两区域系统应用,simulink永磁风机飞轮储能二次调频,系统频率特性如下,可改变调频参数改善频率。 参考文献详细,两区域系统二次调频。 ,核心关键词: 1. Simulink 2. 永磁风机 3. 飞轮储能 4. 二次调频 5. 系统频率特性 6. 调频参数 7. 改善频率 8. 参考文献 9. 两区域系统 以上关键词用分号(;)分隔,结果为:Simulink;永磁风机;飞轮储能;二次调频;系统频率特性;调频参数;改善频率;参考文献;两区域系统。,基于Simulink的永磁风机与飞轮储能系统二次调频研究:频率特性及调频参数优化
MATLAB驱动的ASR防滑转模型:PID与对照控制算法对比,冰雪路面条件下滑移率与车速轮速对照展示,MATLAB驱动的ASR防滑转模型:PID与对照控制算法对比,冰雪路面条件下滑移率与车速轮速对照图展示,MATLAB驱动防滑转模型ASR模型 ASR模型驱动防滑转模型 ?牵引力控制系统模型 选择PID控制算法以及对照控制算法,共两种控制算法,可进行选择。 选择冰路面以及雪路面,共两种路面条件,可进行选择。 控制目标为滑移率0.2,出图显示车速以及轮速对照,出图显示车辆轮胎滑移率。 模型简单,仅供参考。 ,MATLAB; ASR模型; 防滑转模型; 牵引力控制系统模型; PID控制算法; 对照控制算法; 冰路面; 雪路面; 控制目标; 滑移率; 车速; 轮速。,MATLAB驱动的ASR模型:PID与对照算法在冰雪路面的滑移率控制研究
芯片失效分析方法介绍 -深入解析芯片故障原因及预防措施.pptx
4131_127989170.html
内容概要:本文提供了一个全面的PostgreSQL自动化部署解决方案,涵盖智能环境适应、多平台支持、内存与性能优化以及安全性加强等重要方面。首先介绍了脚本的功能及其调用方法,随后详细阐述了操作系统和依赖软件包的准备过程、配置项的自动生成机制,还包括对实例的安全性和监控功能的强化措施。部署指南给出了具体的命令操作指导,便于新手理解和执行。最后强调了该工具对于不同硬件条件和服务需求的有效应对能力,特别是针对云计算环境下应用的支持特点。 适合人群:对PostgreSQL集群运维有一定基础并渴望提高效率和安全性的数据库管理员及工程师。 使用场景及目标:本脚本能够帮助企业在大规模部署时减少人工介入时间,确保系统的稳定性与高性能,适用于各类需要稳定可靠的数据库解决方案的企业或机构,特别是在大数据量和高并发事务处理场合。 其他说明:文中还提及了一些高级功能如自动备份、流复制等设置步骤,使得该方案不仅可以快速上线而且能满足后续维护和发展阶段的要求。同时提到的技术性能数据也为用户评估其能否满足业务需求提供了直观参考。
房地产开发合同[示范文本].doc
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!