本文代码部分来自于《spring in action》,本文讲的是使用!!

Spring 是为了解决什么

一个框架的存在是为了解决某个问题的,那么Spring这个框架是为了解决什么问题呢?主要就是解耦,spring主要要把握两方面的知识,

  • DI(依赖注入 dependency injection) : 解耦, 方便测试
  • AOP(面向切面编程 aspect-oriented programming)

关于 DI Ioc 和 AOP 可以先阅读这篇文章,本文讲的主要是使用。

DI (依赖注入 depency injection)

先看一个例子:

  1 //定义一个勇士类
2 public class DamselRescuingKnight implements Knight {
3
4 private RescueDamselQuest quest;
5
6 //营救任务
7 public DamselRescuingKnight() {
8 this.quest = new RescueDamselQuest();
9 }
10
11 public void embarkOnQuest() {
12 quest.embark();
13 }
14 }

可以看到这里,勇士的 embarkOnQuest ( ) 方法执行的传入的特定的任务,那么当勇士需要执行其他任务的时候就无法进行了,于是Queue 应该做成一个接口.这样的好处是解耦合和方便测试

  1 public class BraveKnight implements Knight {
2 private Quest quest;
3
4 public BraveKnight(Quest quest) {
5 this.quest = quest;
6 }
7
8 public void embarkOnQuest() {
9 quest.embark();
10 }
11 }
  1 public class SlayDragonQuest implements Quest {
2 private PrintStream stream;
3
4 public SlayDragonQuest(PrintStream stream) {
5 this.stream = stream;
6 }
7
8 public void embark() {
9 stream.println("Embarking on quest to slay the dragon!");
10 }
11 }

上面使用依赖注入并且在构造器解耦被称为构造器解耦。 在spring中如何组装这些组件呢?(将queue配置给knight)

  1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://www.springframework.org/schema/beans
5 http://www.springframework.org/schema/beans/spring-beans.xsd">
6
7 <bean id="knight" class="com.springinaction.knights.BraveKnight">
8 <constructor-arg ref="quest" />
9 </bean>
10
11 <bean id="quest" class="com.springinaction.knights.SlayDragonQuest">
12 <constructor-arg value="#{T(System).out}" />
13 </bean>
14 </beans>

图一. 依赖注入会将所依赖的关系自动交给目标对象, 而不是让对象自己去获取依赖

AOP(面向切面编程)

加入一个勇士需要一个历史记录着纪录它的英雄事迹,那么

  1 public class Recorder {
2 private PrintStream stream;
3
4 public Recorder(PrintStream stream) {
5 this.stream = stream;
6 }
7
8 public void singBeforeQuest() {
9 stream.println("Fa la la, the knight is so brave!");
10 }
11
12 public void singAfterQuest() {
13 stream.println("Tee hee hee, the brave knight " +
14 "did embark on a quest!");
15 }
16 }
  1 public class BraveKnight implements Knight {
2 private Quest quest;
3 private Recorder recorder;
4
5 public BraveKnight(Quest quest, Recorder recorder) {
6 this.quest = quest;
7 this.recorder= recorder;
8 }
9
10 public void embarkOnQuest() throws QuestException {
11 recorder.singBeforeQuest();
12 quest.embark();
13 recorder.singAfterQuest();
14 }
15 }

但是这样似乎有点不合常理,当我需要一名勇士时是否每次都要匹配以为记录者?假如记录着可以当我需要的时候出现那么就好了。使用spring的AOP 编程,

  1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xmlns:aop="http://www.springframework.org/schema/aop"
5 xsi:schemaLocation="http://www.springframework.org/schema/aop
6 http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
7 http://www.springframework.org/schema/beans
8 http://www.springframework.org/schema/beans/spring-beans.xsd">
9
10 <bean id="knight" class="com.springinaction.knights.BraveKnight">
11 <constructor-arg ref="quest"/>
12 </bean>
13
14 <bean id="quest" class="com.springinaction.knights.SlayDragonQuest">
15 <constructor-arg value="#{T(System).out}"/>
16 </bean>
17
18 <bean id="minstrel" class="com.springinaction.knights.Recorder">
19 <constructor-arg value="#{T(System).out}"/>
20 </bean>
21
22 <aop:config>
23 <aop:aspect ref="recorder">
24 <aop:pointcut id="embark"
25 expression="execution(* *.embarkOnQuest(..))"/>
26 <aop:before pointcut-ref="embark"
27 method="singBeforeQuest"/>
28 <aop:after pointcut-ref="embark"
29 method="singAfterQuest"/>
30 </aop:aspect>
31 </aop:config>
32 </beans>
33

Spring 容器

spring容器是使用DI(依赖注入)去管理组成应用的组件,其中包括两大类,

  • Application Cotext
  • Bean Factories

Bean Factories 主要是低水准的应用, 下面主要介绍application context,它包括

  • AnnotationConfigApplicationContext :从一个或多个java形式的class文件中加载一个spring 应用
  • AnnotationConfigWebApplicationContext  : 从一个或多个java形式的class文件中加载一个spring web应用
  • FileSystemXmlApplication : 加载一个上下文定义(context)从文件路径中的xml文件
  • XmlWebApplicationConte
  • ClassPathXmlApplication

AnnotationConfigWebApplicationContext 和 XmlWebApplicationContext 我们使用比较多的

装配组件

三种方式

  • XML 形式
  • JavaConfig形式
  • 隐式的bean发现机制 和 自动装配

三种方式的选择: 根据《spring in action》的描述,隐式的bean 发现和自动装配方式强与显式装配, 假若不得不显式装配,优先选择类型安全的java编码形式的,最后才是XML形式 。

自动配置

Spring从两个角度来实现自动化装配:(一个是生成独立的bean, 一个是将他们组装起来)

  • 组件扫描(component scanning) : Spring会自动发现应用上下文中所创建的bean。
  • 自动装配(autowiring) : Spring自动满足bean之间的依赖。

@Component 属性表明这个类是个组件,并且告诉spring 因为为它创建一个been

  1 @Component
2 public class SgtPeppers implements CompactDisc {
3 private String title = "Sgt. Pepper's Lonely Hearts Club Band";
4 private String artist = "The Beatles";
5
6 public void play() {
7 System.out.println("Playing " + title + " by " + artist);
8 }
9 }
  1 @Configuration
2 @ComponentScan
3 public class CDPlayerConfig {
4
5 }

@ComponentScan 表示组件扫描,在这个包下的组件都会被扫描出来并且创建为been,而@Configuration 将会在下面讲到,同时上面也可以通过xml的形式创建

  1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xmlns:context="http://www.springframework.org/schema/context"
5 xsi:schemaLocation="http://www.springframework.org/schema/beans
6 http://www.springframework.org/schema/beans/spring-beans.xsd
7 http://www.springframework.org/schema/context
8 http://www.springframework.org/schema/context/spring-context.xsd">
9 <context:component-scan base-package="soundsystem" />
10 </beans>

组件被scan 后会生成一个bean ,然后生成一个id,默认为类名,那么下面展示的如何自定义这个id的名字,和如何指定spring在特定的路径下进行扫描

  1   1 //组件命名
2 2 @Component("lonelyHeartsClub")
3 3 public class SgtPeppers implements CompactDisc {
4 4 ...
5 5 }
6 6
7 7 //扫描基本路径,多个基本路径
8 8 @Configuration
9 9 @ComponentScan(basePackages= {"soundsystem", "video"})
10 10 public class CDPlayerConfig {}

扫描基类下的所有类

  1 @Configuration
2 @ComponentScan(basePackageClasses={CDPlayer.class, DVDPlayer.class})
3 public class CDPlayerConfig {}

扫描完了,下面展示如何自动装配,使用@Autowired 注解,spring会自动将bean 加载进来,但是当bean 不存在时,spring加载时会抛出错误,为了防止spring直接抛出错误,可以设置 required = false

  1 @Component
2 public class CDPlayer implements MediaPlayer {
3 private CompactDisc cd;
4 @Autowired
5 public CDPlayer(CompactDisc cd) {
6 this.cd = cd;
7 }
8 public void play() {
9 cd.play();
10 }
11
12 @Autowired(required=false)
13 public OtherCDPlayer(CompactDisc cd) {
14 this.cd = cd;
15 }
16 }

JAVA 编码装配bean

当我们需要使用到第三方库时,我们就不能使用自动装配机制,可以使用XML形式和JavaConfig的形式来进行显式装配,java编码比xml形式的重构更加友好,类型安全,更加强大。

  1 @Configuration
2 public class CDPlayerConfig {
3 }

使用@Configuration 注解表明这个类通过javaConfig形式告知spring为它创建一个bean。另外加入我们调用一个方法,而方法返回值是个对象,我们希望这个对象被spring生成一个bean,这又怎么写呢?

  1 @Bean(name="lonelyHeartsClubBand")
2 public CompactDisc sgtPeppers() {
3 return new SgtPeppers();
4 }

和上面自动扫描一样,我们创建了bean, 是时候把它们装配起来了,假如CDPlayer 这个对象依赖CompactDisc 这个对象,我们需要对它进行注入。上面的代码可以知道sgtPeppers( ) 方法可以获取一个bean对象。

  1 @Bean
2 public CDPlayer cdPlayer() {
3 return new CDPlayer(sgtPeppers());
4 }

可以看到我们同样调用了sgtPeppers( ) 方法,使用了@Bean注解,这个需要注意的是spring创建的bean都会是单例,什么意思呢?

  1 @Bean
2 public CDPlayer cdPlayer() {
3 return new CDPlayer(sgtPeppers());
4 }
5 @Bean
6 public CDPlayer anotherCDPlayer() {
7 return new CDPlayer(sgtPeppers());
8 }

在sgtPeppers( )方法中即使我们使用new 一个新的对象,调用这两个方法返回的CDPlay( )却是相同的,都是spring 创建的bean对象。我们可以使用一个简单的方式写法。

  1 @Bean
2 public CDPlayer cdPlayer(CompactDisc compactDisc) {
3 return new CDPlayer(compactDisc);
4 }

XML 方式装配bean

使用XML 形式进行装配bean,

  1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://www.springframework.org/schema/beans
5 http://www.springframework.org/schema/beans/spring-beans.xsd
6 http://www.springframework.org/schema/context">
7
8 <bean id="cdPlay" class="soundsystem.SgtPeppers">
9 </beans>

初始化bean构造器注入有两种方式

  • 使用<constructor-arg>
  • 使用c-命名空间在Spring 3.0

下面使用的时第一种,ref是传入的引用,是某个bean 的id

  1 <bean id="cdPlayer" class="soundsystem.CDPlayer">
2 <constructor-arg ref="compactDisc" />
3 </bean>

如果存在下面的类

  1 public class BlankDisc implements CompactDisc {
2 private String title;
3 private String artist;
4 public BlankDisc(String title, String artist) {
5 this.title = title;
6 this.artist = artist;
7 }
8 public void play() {
9 System.out.println("Playing " + title + " by " + artist);
10 }
11 }

那么构造器依赖注入就是

  1 <bean id="compactDisc" class="soundsystem.BlankDisc">
2 <constructor-arg value="Sgt. Pepper's Lonely Hearts Club Band"/>
3 <constructor-arg value="The Beatles"/>
4 </bean>
5
6 <!--下面是c-命名空间,下划线后加参数名字-->
7 <bean id="compactDisc"
8 class="soundsystem.BlankDisc"
9 c:_title="Sgt. Pepper's Lonely Hearts Club Band"
10 c:_artist="The Beatles" />
11
12 <!--也可以这样子写-->
13 <bean id="compactDisc"
14 class="soundsystem.BlankDisc"
15 c:_0="Sgt. Pepper's Lonely Hearts Club Band"
16 c:_1="The Beatles" />
17

如果构造参数中有List,或是set,要是set 的话,只需要改节点为<set>

  1 <bean id="compactDisc" class="soundsystem.BlankDisc">
2 <constructor-arg value="Sgt. Pepper's Lonely Hearts Club Band" />
3 <constructor-arg value="The Beatles" />
4 <constructor-arg>
5 <list>
6 <value>Sgt. Pepper's Lonely Hearts Club Band</value>
7 <value>With a Little Help from My Friends</value>
8 <value>Lucy in the Sky with Diamonds</value>
9 <value>Getting Better</value>
10 <value>Fixing a Hole</value>
11 <!-- ...other tracks omitted for brevity... -->
12 </list>
13 </constructor-arg>
14 </bean>

如果使用c命名空间的构造器注入,必须向在开头声明命令空间

  1
2 <?xml version="1.0" encoding="UTF-8"?>
3 <beans xmlns="http://www.springframework.org/schema/beans"
4 xmlns:c="http://www.springframework.org/schema/c"
5 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
6 xsi:schemaLocation="http://www.springframework.org/schema/beans
7 http://www.springframework.org/schema/beans/spring-beans.xsd">
8 ...
9 </beans>

下面是如何使用

  1 <bean id="cdPlayer" class="soundsystem.CDPlayer"
2 c:cd-ref="compactDisc" />

假如一个类没有构造方法,需要对属性进行注入

  1 public class BlankDisc implements CompactDisc {
2 private String title;
3 private String artist;
4 private List<String> tracks;
5 public void setTitle(String title) {
6 this.title = title;
7 }
8 public void setArtist(String artist) {
9 this.artist = artist;
10 }
11
12 public void setTracks(List<String> tracks) {
13 this.tracks = tracks;
14 }
15 public void play() {
16 System.out.println("Playing " + title + " by " + artist);
17 for (String track : tracks) {
18 System.out.println("-Track: " + track);
19 }
20 }
21 }
  1 <bean id="compactDisc"
2 class="soundsystem.BlankDisc">
3 <property name="title"
4 value="Sgt. Pepper's Lonely Hearts Club Band" />
5 <property name="artist" value="The Beatles" />
6 <property name="tracks">
7 <list>
8 <value>Sgt. Pepper's Lonely Hearts Club Band</value>
9 <value>With a Little Help from My Friends</value>
10 <value>Lucy in the Sky with Diamonds</value>
11 <value>Getting Better</value>
12 <value>Fixing a Hole</value>
13 <!-- ...other tracks omitted for brevity... -->
14 </list>
15 </property>
16 </bean>
17

和c-命名空间相同, p-命名空间用来标识属性注入的,但是需要注意的是p-命名空间不能注入List,只能用spring-util 命名空间对集合进行注入,同样,在使用命令空间时需要在xml开头声明

  1 xmlns:p="http://www.springframework.org/schema/p"
2 xmlns:util="http://www.springframework.org/schema/util"
  1 <bean id="compactDisc"
2 class="soundsystem.BlankDisc"
3 p:title="Sgt. Pepper's Lonely Hearts Club Band"
4 p:artist="The Beatles"
5 p:tracks-ref="trackList" />
  1 <util:list id="trackList">
2 <value>Sgt. Pepper's Lonely Hearts Club Band</value>
3 <value>With a Little Help from My Friends</value>
4 <value>Lucy in the Sky with Diamonds</value>
5 <value>Getting Better</value>
6 <value>Fixing a Hole</value>
7 <!-- ...other tracks omitted for brevity... -->
8 </util:list>

即使当显示声明bean时,我们更趋向javaCofig 形式装配,但是有些时候XML 形式的才是最好的选择,spring允许两者混合使用,如下

在javaCofig形式中引入xml配置

加入存在以下图的依赖关系

  1 @Configuration
2 public class CDConfig {
3 @Bean
4 public CompactDisc compactDisc() {
5 return new SgtPeppers();
6 }
7 }
8
9
10 //我们直接使用 @Import 注解通过引入另外一个类,来装配bean,
11 @Configuration
12 @Import(CDConfig.class)
13 public class CDPlayerConfig {
14 @Bean
15 public CDPlayer cdPlayer(CompactDisc compactDisc) {
16 return new CDPlayer(compactDisc);
17 }
18 }
19
20
21 //或是我们创建多一个类,直接引入两个类,来装配bean
22 @Configuration
23 @Import({CDPlayerConfig.class, CDConfig.class})
24 public class SoundSystemConfig {
25 }
26

假如BlankDisc 是定义在XML 中,如何通过Java形式来进行装配,使用@ImportResource()注解

  1 <bean id="compactDisc"
2 class="soundsystem.BlankDisc"
3 c:_0="Sgt. Pepper's Lonely Hearts Club Band"
4 c:_1="The Beatles">
5 <constructor-arg>
6 <list>
7 <value>Sgt. Pepper's Lonely Hearts Club Band</value>
8 <value>With a Little Help from My Friends</value>Importing and mixing configurations 61
9 <value>Lucy in the Sky with Diamonds</value>
10 <value>Getting Better</value>
11 <value>Fixing a Hole</value>
12 <!-- ...other tracks omitted for brevity... -->
13 </list>
14 </constructor-arg>
15 </bean>
  1 @Configuration
2 @Import(CDPlayerConfig.class)
3 @ImportResource("classpath:cd-config.xml")
4 public class SoundSystemConfig {
5 }

其中,classpath :cd-config.xml 表示xml的位置。假如需要从另外的XML 文件中引入一个bean

  1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xmlns:c="http://www.springframework.org/schema/c"
5 xsi:schemaLocation="http://www.springframework.org/schema/beans
6 http://www.springframework.org/schema/beans/spring-beans.xsd">
7
8 <import resource="cd-config.xml" />
9 <bean id="cdPlayer"
10 class="soundsystem.CDPlayer"
11 c:cd-ref="compactDisc" />
12 </beans>
13

从java形式装配引入到XML 中,直接使用bean

  1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xmlns:c="http://www.springframework.org/schema/c"
5 xsi:schemaLocation="http://www.springframework.org/schema/beans
6 http://www.springframework.org/schema/beans/spring-beans.xsd">
7 <bean class="soundsystem.CDConfig" />
8 <bean id="cdPlayer"
9 class="soundsystem.CDPlayer"
10 c:cd-ref="compactDisc" />
11 </beans>

当需要装配一个bean来自XML ,一个来自javaConfig,那么按照之前的想法就是将多一个更加高层次的类对两个bean进行装配。

  1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xmlns:c="http://www.springframework.org/schema/c"
5 xsi:schemaLocation="http://www.springframework.org/schema/beans
6 http://www.springframework.org/schema/beans/spring-beans.xsd">
7 <bean class="soundsystem.CDConfig" />
8 <import resource="cdplayer-config.xml" />
9 </beans>

好了,这一篇讲了bean 装配的问题,下一篇继续学习!加油

Spring 基础入门(一)的更多相关文章

  1. Spring基础入门

    一.Spring了解 Spring:程序员们的春天 Spring主要技术是IOC.AOP两个大概念 它是轻量级的,每个jar包就1M ~ 3M 左右,所以速度快 面向接口编程:降低了耦合度 面向切面编 ...

  2. Spring基础入门(一)

    一.Spring概念 1.什么是Spring   Spring是一个开源框架,它由Rod Johnson创建.它是为了解决企业应用开发的复杂性而创建的.Spring使用基本的JavaBean来完成以前 ...

  3. Spring基础入门(二)

    一.AOP 1.AOP概念 aop:面向切面编程,扩展功能不修改源代码实现. AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码. 2.AOP原理 (1)第一种情况,有接口情况,使用动态代理创建 ...

  4. Spring基础入门(三)

    一.Spring的jdbcTemplate操作 (1)Spring是一站式框架,对于javaee三层,每一层都有解决技术. web层:springMVC service:spring的ioc dao层 ...

  5. [Spring框架]Spring AOP基础入门总结二:Spring基于AspectJ的AOP的开发.

    前言: 在上一篇中: [Spring框架]Spring AOP基础入门总结一. 中 我们已经知道了一个Spring AOP程序是如何开发的, 在这里呢我们将基于AspectJ来进行AOP 的总结和学习 ...

  6. [Spring框架]Spring AOP基础入门总结一.

    前言:前面已经有两篇文章讲了Spring IOC/DI 以及 使用xml和注解两种方法开发的案例, 下面就来梳理一下Spring的另一核心AOP. 一, 什么是AOP 在软件业,AOP为Aspect ...

  7. Spring Boot 入门之基础篇(一)

    原文地址:Spring Boot 入门之基础篇(一) 博客地址:http://www.extlight.com 一.前言 Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是 ...

  8. Java基础-SSM之Spring MVC入门篇

    Java基础-SSM之Spring MVC入门篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Spring MVC简介 1>.什么是Spring MVC 答:Sprin ...

  9. Java基础-SSM之Spring快速入门篇

    Java基础-SSM之Spring快速入门篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.    Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java ...

随机推荐

  1. 在线绘图网站 UML、思维导图、 流程图、 用例图等等

    https://www.processon.com/ 用我的微信登录即可 帐号是 QQ邮箱

  2. SP16549 QTREE6 - Query on a tree VI(LCT)

    题意翻译 题目描述 给你一棵n个点的树,编号1~n.每个点可以是黑色,可以是白色.初始时所有点都是黑色.下面有两种操作请你操作给我们看: 0 u:询问有多少个节点v满足路径u到v上所有节点(包括)都拥 ...

  3. VMware虚拟机中如何配置静态IP

    我们首先说一下VMware的几个虚拟设备 VMnet0:用于虚拟桥接网络下的虚拟交换机 VMnet1:用于虚拟Host-Only网络下的虚拟交换机 VMnet8:用于虚拟NAT网络下的虚拟交换机 VM ...

  4. Flink学习笔记:Flink API 通用基本概念

    本文为<Flink大数据项目实战>学习笔记,想通过视频系统学习Flink这个最火爆的大数据计算框架的同学,推荐学习课程: Flink大数据项目实战:http://t.cn/EJtKhaz ...

  5. js-查找字符串中出现次数最多的字符

    假设有一个字符串,下面让我们一起来查找出现次数最多的字符 var str = 'asdfssaaasasasasaa'; 首先,我们定义一个Object用来存放拆分的字符串,然后遍历字符串. 判断ob ...

  6. python学习,day3:集合的学习

    集合天生去重,另外集合非常便于两组数字的取交集,并集等计算 # coding=utf-8 # Author: RyAn Bi list_1 =[1,2,3,4,5,6,7] list_1 =set(l ...

  7. CDQZ Day4

    NOIP 模拟题By liu_runda题目名称 数 论 题源程序文件名 number.cpp theory.cpp problem.cpp输入文件名 number.in theory.in prob ...

  8. train loss与test loss结果分析

    train loss 不断下降,test loss不断下降,说明网络仍在学习; train loss 不断下降,test loss趋于不变,说明网络过拟合; train loss 趋于不变,test ...

  9. linux忘记root密码怎么办

    如何找回root密码,如果我们不小心,忘记root密码,怎么找回? 思路:进入到单用户模式,然后修改root密码.因为进入单用户模式,root不需要密码就可以登录. 详细过程: 1.打开虚拟机 2.开 ...

  10. CDH集群安装配置(七)--CDH组件的安装和配置

    1. Clouder Manger页面的配置 访问主节点IP:(cdh1)192.168.80.81:7180 默认用户名和密码:admin,admin 选择一个版本 选择集群的服务器(agent), ...