SpringBoot | 第三十三章:Spring web Servcies集成和使用

前言

最近有个单位内网系统需要对接统一门户,进行单点登录和待办事项对接功能。一般上政府系统都会要求做统一登录功能,这个没啥问题,反正业务系统都是做单点登录的,改下shiro相关类就好了。看了接入方案,做坑爹的是需要业务系统提供一个webService服务,供统一平台调用。对于ws服务,是真的除了大学期间要去写个调用天气预报的作业后,就再也没有接触过了。查阅了SpringBoot文档后,发现确实有一章节是将webService的,所以,今天就来简单介绍下Spring Web Service的集成和使用吧。

  • 一点知识

    • 何为WebService
    • WebServcie技术支持
      • XML和XSD
      • SOAP
      • WSDL
      • UDDI
    • 何为Spring-Web-Services
  • Spring-WS服务端发布
  • Spirng-WS客户端调用
  • 简单使用CXF调用webService
  • 有待补充
  • 参考资料
  • 总结
  • 最后
  • 老生常谈

一点知识

何为WebService

Web Service技术,能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件, 就可相互交换数据或集成。依据Web Service规范实施的应用之间,无论它们所使用的语言、平台或内部协议是什么,都可以相互交换数据。

简单的说,WebService就是一种跨编程语言和跨操作系统平台的远程调用技术。

WebServcie技术支持

以下内容摘自百度百科:Web Service

Web Service平台需要一套协议来实现分布式应用程序的创建。任何平台都有它的数据表示方法和类型系统。要实现互操作性,Web Service平台必须提供一套标准的类型系统,用于沟通不同平台、编程语言和组件模型中的不同类型系统。这些协议有:

XML和XSD

可扩展的标记语言Web Service平台中表示数据的基本格式。除了易于建立和易于分析外,XML主要的优点在于它既与平台无关,又与厂商无关。XML是由万维网协会(W3C)创建,W3C制定的XML SchemaXSD定义了一套标准的数据类型,并给出了一种语言来扩展这套数据类型。

Web Service平台是用XSD来作为数据类型系统的。当你用某种语言如VB. NETC#来构造一个Web Service时,为了符合Web Service标准,所有你使用的数据类型都必须被转换为XSD类型。如想让它使用在不同平台和不同软件的不同组织间传递,还需要用某种东西将它包装起来。这种东西就是一种协议,如 SOAP

XSD全称为XML Schemas Definition,即:XML结构定义。是描述xml的,同时遵循xml规范。

SOAP

SOAP即简单对象访问协议(Simple Object Access Protocol),它是用于交换XML(标准通用标记语言下的一个子集)编码信息的轻量级协议。它有三个主要方面:XML-envelope为描述信息内容和如何处理内容定义了框架,将程序对象编码成为XML对象的规则,执行远程过程调用(RPC)的约定。SOAP可以运行在任何其他传输协议上。例如,你可以使用 SMTP,即因特网电子邮件协议来传递SOAP消息,这可是很有诱惑力的。在传输层之间的头是不同的,但XML有效负载保持相同。

Web Service 希望实现不同的系统之间能够用“软件-软件对话”的方式相互调用,打破了软件应用、网站和各种设备之间的格格不入的状态,实现“基于Web无缝集成”的目标。

WSDL

Web Service描述语言WSDL就是用机器能阅读的方式提供的一个正式描述文档而基于XML的语言,用于描述Web Service及其函数、参数和返回值。因为是基于XML的,所以WSDL既是机器可阅读的,又是人可阅读的。

UDDI

UDDI的目的是为电子商务建立标准;UDDI是一套基于Web的、分布式的、为Web Service提供的、信息注册中心的实现标准规范,同时也包含一组使企业能将自身提供的Web Service注册,以使别的企业能够发现的访问协议的实现标准。

何为Spring-Web-Services

Spring Web servicesSpring推出的一款构建webservice服务的框架。其主要侧重点是创建文档驱动的Web服务。Spring Web Services项目促进了契约优先的SOAP服务开发,提供了多种方式来创建灵活的Web服务,这些服务可以通过多种方式处理XML负载。可无缝地使用Spring依赖注入和配置等概念。

Spring-WS项目由由以下几个项目组成:

  • Spring-WS Core(spring-ws-core.jar) - 它是主要模块,提供WebServiceMessage和SoapMessage等中央接口,服务器端框架,强大的消息分发功能和支持类来实现Web服务端点。 它还提供Web Service消费者客户端作为:WebServiceTemplate。
  • Spring-WS Support(spring-ws-support.jar) ? 该模块为JMS,电子邮件等提供支持。
  • Spring-WS Security(spring-ws-security.jar) - 该模块负责提供与核心Web服务模块集成的WS-Security实现。 使用这个模块,可以添加主体令牌,签名,加密和解密SOAP消息。该模块允许使用现有的Spring Security实现进行认证和授权。
  • Spring XML(spring-xml.jar) ? 该模块为Spring Web Services提供XML支持类。 该模块由Spring-WS框架内部使用。
  • Spring OXM - 该模块提供了XML与对象映射的支持类。

之间的依赖关系,如下图所示:

简单来说,看了官网文档后,一切遵循契约优先原则,请求和响应的参数都应遵循约定,不然wsdl文件生成是错误的,这里踩了坑。。

Spring-WS服务端发布

spring-wsspring-mvc一样,在集成到web项目时,前端有个servlet分发请求消息的概念。

这个servlet接受soap消息,通过映射转发到后端的服务实现类方法中(Endpiont)

在请求进来处理过程中,可以添加,拦截器(Interceptor),异常处理器(ExceptionResolver)。

通过拦截器可以做一些额外的定制功能,比如安全。通过异常处理器定制异常信息显示,处理等。

这个servlet就是MessageDispatcher,来看看官网给出的处理流程图:

所以在需要对请求参数或者响应参数做处理时,可以编写对应的拦截器进行处理的。

现在,以一个简单示例来发布一个webService服务。创建工程:spring-boot-webservice-server

0.引入POM依赖。

        <!-- spirng ws 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web-services</artifactId>
        </dependency>
        <!-- 生成wsdl文件 -->
        <dependency>
            <groupId>wsdl4j</groupId>
            <artifactId>wsdl4j</artifactId>
        </dependency>

1.创建一个xsd文件,用来描述请求和响应的各实体信息。这里简单以一个获取作者信息为例子。

author.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.lqdev.cn/webservice"
           targetNamespace="http://www.lqdev.cn/webservice" elementFormDefault="qualified">

    <!-- 定义请求实体 -->
    <xs:element name="authorRequest">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="name" type="xs:string"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

     <!-- 定义响应实体 -->
    <xs:element name="authorResponse">
               <xs:complexType>
            <xs:sequence>
                <xs:element name="author" type="tns:author"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <!-- 定义请求实体 -->
    <xs:element name="authorListRequest">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="nonce" type="xs:string" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <!-- 定义响应实体 -->
    <xs:element name="authorListResponse">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="author" type="tns:author" minOccurs="1" maxOccurs="unbounded" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <!-- 定义作者 信息 -->
    <xs:complexType name="author">
        <xs:sequence>
                <xs:element name="name" type="xs:string" />
                <!-- 爱好 列表形式 nillable=true 可为空 ,maxOccurs=unbouned 无限 -->
                <xs:element name="hobby" type="xs:string" nillable="true" maxOccurs="unbounded" />
                <!-- 性别 枚举类型 限定 -->
                <xs:element name="sex" type="tns:sex" />
                <!-- 生日 -->
                <xs:element name="birthday" type="xs:string" />
                <!-- 描述 -->
                <xs:element name="description" type="xs:string" />
        </xs:sequence>
    </xs:complexType>

    <!-- 枚举类型 性别:男 女 -->
    <xs:simpleType name="sex">
        <xs:restriction base="xs:string">
            <xs:enumeration value="male"/>
            <xs:enumeration value="female"/>
        </xs:restriction>
    </xs:simpleType>
</xs:schema>

这里需要注意,请求和返回的名字是有要求的,两个名字前面要一样,后缀分别是固定的配置,默认为Request和Response; 当然可以通过requestSuffixresponseSuffix属性来修改默认值的,在配置小节会说到。

关于xsd规则,可以查看:http://www.w3school.com.cn/schema/index.asp

2.根据XSD文件创建实体对象。这里直接使用maven创建自动生成。pom中加入插件:jaxb2-maven-plugin

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>jaxb2-maven-plugin</artifactId>
                <version>1.6</version>
                <executions>
                    <execution>
                        <id>xjc</id>
                        <goals>
                            <goal>xjc</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <schemaDirectory>${project.basedir}/src/main/resources/</schemaDirectory>
                    <outputDirectory>${project.basedir}/src/main/java</outputDirectory>
                    <clearOutputDir>false</clearOutputDir>
     <!-- 包名路径 -->               <packageName>cn.lqdev.learning.springboot.ws.webservice</packageName>
                </configuration>
            </plugin>

然后运行下命令:mvn install就会自动创建了。正常情况下,添加后,xsd文件有变动,都会实时创建对应实体对象的。此时,生成的对象如下:

3.创建Endpoint服务,有点类似Controller,请求服务的入口。

/**
 * 创建endpoint 类似于创建controller了。
 * @author oKong
 *
 */
@Endpoint
public class AuthorEndpoint {

    @PayloadRoot(namespace = WsConst.NAMESPACE_URI, localPart = "authorRequest")
    @ResponsePayload
    public AuthorResponse getAuthor(@RequestPayload AuthorRequest authorReq){
        AuthorResponse resp = new AuthorResponse();
        Author author = new Author();
        author.setBirthday("1990-01-23");
        author.setName("姓名:" + authorReq.getName());
        author.setSex(Sex.FEMALE);
        author.getHobby().addAll(Arrays.asList("电影","旅游"));
        author.setDescription("描述:一枚趔趄的猿。现在时间:" + new Date().getTime());
        resp.setAuthor(author);
        return resp;
    }

    @PayloadRoot(namespace = WsConst.NAMESPACE_URI, localPart = "authorListRequest")
    @ResponsePayload
    public AuthorListResponse getAuthorList(@RequestPayload AuthorListRequest request){
        AuthorListResponse resp = new AuthorListResponse();
        Author author = new Author();
        author.setBirthday("1990-01-23");
        author.setName("姓名:oKong");
        author.setSex(Sex.FEMALE);
        author.getHobby().addAll(Arrays.asList("电影","旅游"));
        author.setDescription("描述:一枚趔趄的猿。现在时间:" + new Date().getTime());
        resp.getAuthor().add(author);
        resp.getAuthor().add(author);
        return resp;
    }
}

示例代码,只是为了演示,大部分信息都固定写死了。实际开发中,可以加入各自的业务逻辑,引入相应的service类的。

而且,这里需要注意:

  1. 方法声明上的 @PayloadRoot标注中的namespacelocalPart分别就是wsdl中的targetNamespacesoap方法名称。
  2. @ResponsePayload@RequestPayload 这两个标注的用法,以及它们对应的数据类型就是此前通过maven插件对wsdl定义生成的java类。

关于请求参数的类型,是否需要加@RequestPayload说明:

一般上,都是使用JAXB2对象了,也就是先前生成的实体对象。当然,有兴趣的同学可以试试,其他的对象参数,可以获取到不同的参数值的。

比如:

public void handle(@RequestPayload Element element)

一个org.w3c.dom.Element对象。

public void handle(@RequestPayload DOMSource domSource, SoapHeader header)

这样,能获取到SOAP的头部信息。

其他相关用法,可以查看此地址:https://docs.spring.io/spring-ws/docs/2.4.2.RELEASE/reference/#server-atEndpoint-methods

关于响应的参数,是否需要加@ResponsePayload,一下是官网给出的说明信息:

这个有个坑:尝试无参数请求时,使用postman发送xml数据可以正常请求,但使用spirng-ws调用就调用不到了,嗯,我想应该是我调用方法不多。。⊙﹏⊙‖∣

4.创建配置类,生效webservice服务。

/**
 * ws-配置
 * @author oKong
 *
 */
@EnableWs //开启webService
@Configuration
public class WebServiceConfig extends WsConfigurerAdapter{

    @Bean
    public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
        MessageDispatcherServlet servlet = new MessageDispatcherServlet();
        servlet.setApplicationContext(applicationContext);
        servlet.setTransformWsdlLocations(true);//true 地址会进行转换,不然都是本地地址
      //这里可以设置 请求的工厂类,实现有两个:SaajSoapMessageFactory 和 AxiomSoapMessageFactory
        //默认是 SaajSoapMessageFactory
//        servlet.setMessageFactoryBeanName(messageFactoryBeanName);
        return new ServletRegistrationBean(servlet, "/ws/*");
    }

    //name 就是对应 wsdl名如 :/ws/author.wsdl
    @Bean(name = "author")
    public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema authorSchema) {
        DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
        wsdl11Definition.setPortTypeName("AuthorPort");
        wsdl11Definition.setLocationUri("/ws");
        wsdl11Definition.setSchema(authorSchema);
        wsdl11Definition.setTargetNamespace(WsConst.NAMESPACE_URI);
        return wsdl11Definition;
    }

    //可自定义SaajSoapMessageFactory 然后指定其SOAP版本
    @Bean
    public SaajSoapMessageFactory messageFactory() {
        SaajSoapMessageFactory messageFactory = new SaajSoapMessageFactory();
        //指定版本
        messageFactory.setSoapVersion(SoapVersion.SOAP_11);//SoapVersion.SOAP_12
        return messageFactory;
    }

    @Bean
    public XsdSchema authorSchema() {
        return new SimpleXsdSchema(new ClassPathResource("author.xsd"));
    }

    @Override
    public void addInterceptors(List<EndpointInterceptor> interceptors) {
        //可以自定义拦截器
    }
}

常量类:WsConst.java

/**
 * 常量类
 * @author oKong
 *
 */
public class WsConst {
    public static final String NAMESPACE_URI = "http://www.lqdev.cn/webservice";
}

5.编写启动类。

/**
 * web-service 简单示例
 *
 * @author oKong
 *
 */
@SpringBootApplication
@Slf4j
public class WebServiceApplication {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(WebServiceApplication.class, args);
        log.info("spring-boot-webservice-server-chapter33启动!");
    }
}

6.启动应用,访问下:http://127.0.0.1:8090/ws/author.wsdl ,可以看见wsdl文件内容了。

接着,我们使用postman调用下:POST http://127.0.0.1:8090/ws

说明已经正常发布了。接下来,我们使用spring-ws直接调用。

Spirng-WS客户端调用

创建一个新工程:spring-boot-webservice-client

0.引入POM依赖。

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web-services</artifactId>
        </dependency>
        <dependency>
            <groupId>wsdl4j</groupId>
            <artifactId>wsdl4j</artifactId>
        </dependency>

1.获取wsdl文件,放入src\main\resources\schemas\文件夹中,同时加入maven插件:maven-jaxb2-plugin使其生成对应实体列。

           <plugin>
                <groupId>org.jvnet.jaxb2.maven2</groupId>
                <artifactId>maven-jaxb2-plugin</artifactId>
                <version>0.13.3</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <schemaLanguage>WSDL</schemaLanguage>
                    <generatePackage>cn.lqdev.webservice</generatePackage>
                    <generateDirectory>${basedir}/src/main/java</generateDirectory>
                    <schemas>
                        <schema>
                            <fileset>
                                <!-- Defaults to schemaDirectory. -->
                                <directory>${basedir}/src/main/resources/schemas</directory>
                                <!-- Defaults to schemaIncludes. -->
                                <includes>
                                    <include>*.wsdl</include>
                                </includes>
                            </fileset>
                        </schema>
                    </schemas>
                </configuration>
            </plugin>

wsdl文件就不贴了。目录为:

生成后对应实体类为:

注意:写此文章前,尝试过使用cxf进行调用,而调用过程中,发现请求的实体需要在包cn.lqdev.webservice路径下,不然校验不通过。所以为了兼容,我直接写成此路径了。对于spring ws而言,包名可以自定义的。不知道cxf是不是可以修改,跟踪了下源码也没有找到具体这个规则是怎么来的,不知道是不是和targetNamespace的值http://www.lqdev.cn/webservice有关,有待测试。

2.创建客户端调用类。

/**
 * 编写客户端 继承WebServiceGatewaySupport 类 方便调用
 * @author oKong
 *
 */
public class WsAuthorClient extends WebServiceGatewaySupport{

    /**
     *  获取作者信息
     *  @author oKong
     */
    public AuthorResponse getAuthor(String name) {
        AuthorRequest req = new AuthorRequest();
        req.setName(name);
        //使用 marshalSendAndReceive 进行调用
        return (AuthorResponse) getWebServiceTemplate().marshalSendAndReceive(req);
    }

    /**
     *  获取作者列表信息
     *  @author oKong
     */
    public AuthorListResponse getAuthorList(){
        AuthorListRequest request = new AuthorListRequest();
        request.setNonce(UUID.randomUUID().toString());
        return (AuthorListResponse) getWebServiceTemplate().marshalSendAndReceive(request);
    }
}

此类,就是调用webservice服务的。

4.创建配置类.

/**
 * 客户端调用配置
 * @author oKong
 *
 */
@Configuration
public class WsClientConfig {

    @Bean
    public Jaxb2Marshaller marshaller() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        //会扫描此类下面的对应的 jaxb2实体类 因为是使用 Marshaller和 unmarshaller来进行xml和bean直接转换的
        //具体是判断此路径下是否包含 ObjectFactory.class 文件
        //设置 JAXBContext 对象
        marshaller.setContextPath("cn.lqdev.webservice");
        //或者使用 以下方式设置
//        marshaller.setPackagesToScan(packagesToScan);
//        marshaller.setClassesToBeBound(classesToBeBound);
        return marshaller;
    }

    /*
     * 创建bean
     */
    @Bean
    public WsAuthorClient wsClient(Jaxb2Marshaller marshaller) {
        WsAuthorClient client = new WsAuthorClient();
        //默认对应的ws服务地址 client请求中还能动态修改的
        client.setDefaultUri("http://127.0.0.1:8090/ws");
        client.setMarshaller(marshaller);//指定转换类
        client.setUnmarshaller(marshaller);
        return client;
    }
}

关于marshallerunmarshaller解析xml和读取xml相关知识,没有过多了解,感兴趣的可以自行搜索相关资料下。

5.创建示例控制层,调用各服务接口。

/**
 * 简单调用示例
 * @author oKong
 *
 */
@RestController
@RequestMapping("/author")
public class DemoController {

    @Autowired
    WsAuthorClient authorClient;

    @GetMapping("/get")
    public AuthorResponse getAuthor(String name) {
        return authorClient.getAuthor(name);
    }

    @GetMapping("/list")
    public AuthorListResponse getAuthorList() {
        return authorClient.getAuthorList();
    }
}

6.修改端口号为:8096,同时启动应用。

server.port=8096

使用Postman,访问:http://127.0.0.1:8096/author/get?name=程序员

正常情况下可以看见以下返回内容:

说明调用成功了。

访问下列表:http://127.0.0.1:8096/author/list

简单使用CXF调用webService

接下类,尝试下使用cxf来访问下服务。

0.引入cxf相关依赖。

    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
        <version>3.1.11</version>
    </dependency>

1.controller类新增一个方法,使用cxf方式调用服务。

    @GetMapping("/cxf/{method}")
    public Object cxf(@PathVariable String method,String name) throws Exception{
        //获取客户端工厂类
        JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
        //创建client对象
        Client client = dcf.createClient("http://127.0.0.1:8090/ws/author.wsdl");

        AuthorListRequest listReq = new AuthorListRequest();
        listReq.setNonce(UUID.randomUUID().toString());

        AuthorRequest req = new AuthorRequest();
        req.setName(name);
        //调用 第一个方法是operation 值,即调用方法,
        //其后是调用参数。
        Object[] objects = new Object[0];
        //相关 operation值 可以根据 client.getEndpoint().getBinding().getBindingInfo().getOperations(); 获取
        //有兴趣可以看下 client.getEndpoint().getBinding().getBindingInfo()提供的一些方法。

        //这里就简单的判断了
        if("authorList".equalsIgnoreCase(method)) {
          objects = client.invoke("authorList", listReq);
        } else {
             objects = client.invoke("author", req);
        }
        //返回的对象objects[0]即为返回的值
        return objects[0];
    }

这里需要注意:对应的实体类,需要符合wsdl文件中解析出来的type Classes 对应上,本例子为:cn.lqdev.webservice.AuthorListRequest,猜猜应该和targetNamespace值有关,不然会出现以下类似提示:

Part {http://www.lqdev.cn/webservice}authorListRequest should be of type cn.lqdev.webservice.AuthorListRequest, not cn.lqdev.learning.webservice.AuthorListRequest

最后发现使用cxf也很简单呀,下次试试。是利用JAX-WS规范的。

2.重启应用,访问下:http://127.0.0.1:8096/author/cxf/author?name=趔趄的猿 最后效果是一样的。

访问:http://127.0.0.1:8096/author/cxf/authorList

有待补充

以上只是基于官方文档,简单的示例了一遍,具体一些高级用法以及相关安全校验、过滤器等等,没有过多涉及的。之后有时间再填坑吧,毕竟这个用的真的不多呀。

参考资料

  1. https://docs.spring.io/spring-ws/docs/2.4.2.RELEASE/reference/
  2. https://spring.io/guides/gs/producing-web-service/
  3. https://spring.io/guides/gs/consuming-web-service/

总结

本章节主要简单介绍了spring-ws的使用。原本是没有打算写关于WebService相关的。只是机缘巧合下刚好有个对接系统需要用上,就临时尝试一下了。还有很多深入的功能,就没有过多涉及了。等到时候真正开始对接时,有碰到一些问题或者有些知识点补充的,再来补充吧。毕竟,我想现在除了旧系统和政府部门的系统,应该很少再去开发webservice服务了吧。官网文档大致看了下,也确实觉得有点复杂呀,不知道是不是理解能力问题,⊙﹏⊙‖∣。理论上,按着规则走,问题应该也不是很大。就是一些比如无参数如何调用,或者返回参数节点自定义问题,这些理论上都可以使用提供的拦截器来完成的。有问题,还是建议查看官网吧,真的比较详细。最后看了cxf,也比较简单。下一篇就来写写使用cxf来发布webservice,多尝试几种方式~

最后

目前互联网上很多大佬都有SpringBoot系列教程,如有雷同,请多多包涵了。原创不易,码字不易,还希望大家多多支持。若文中有所错误之处,还望提出,谢谢。

老生常谈

  • 个人QQ:499452441
  • 微信公众号:lqdevOps

个人博客:http://blog.lqdev.cn

完整示例:https://github.com/xie19900123/spring-boot-learning/tree/master/chapter-33

原文地址:http://blog.lqdev.cn/2018/11/09/springboot/chapter-thirty-three/

原文地址:https://www.cnblogs.com/okong/p/springboot-thirty-three.html

时间: 2024-10-09 21:00:15

SpringBoot | 第三十三章:Spring web Servcies集成和使用的相关文章

Gradle 1.12用户指南翻译——第三十三章. PMD 插件

本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Github上的地址: https://github.com/msdx/gradledoc/tree/1.12. 直接浏览双语版的文档请访问: http://gradledoc.qiniudn.com/1.12/userguide/userguide.html. 另外,Android 手机用户可通过我写的一个

第三十三章

知人者智也,自知者明也.胜人者有力也,自胜者强也.知足者富也,强行者有志也.不失其所者久也,死而不妄者寿也. 第三十三章1 感应天象,罗博士有神化自己吗? 各位朋友大家好,今天我们接着来聊<道德经>,看看老子又给我们什么样的人生启发了. 今天讲的是第三十三章.讲的也很快,讲到第三十三章,我们一起来看看.这一章内容很有趣,首先我们来看第一句,老子说“知人者智也,自知者明也”,这话又耐人寻味了.老子讲了两个境界,很多人讲<道德经>讲这一章的时候,我都讲我跟别人讲有什么不同,一般人都认为

C#高级编程第11版 - 第三十三章

导航 C# 全版本特性一览 全书目录 第三十三章 Windows Apps 33.1 Windows 应用程序简介 855 33.1.1 Windows 运行库 856 33.1.2 Hello, Windows 856 33.1.3 应用程序清单文件 857 33.1.4 应用程序启动 859 33.1.5 主页 859 33.2 XAML 861 33.2.1 XAML 标准 861 33.2.2 将元素映射到类 861 33.2.3 通过XAML 使用定制的.NET 类 862 33.2.

SpringBoot实战(三)之使用RestFul Web服务

一.导入maven依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/P

ABP源码分析三十三:ABP.Web

ABP.Web模块并不复杂,主要完成ABP系统的初始化和一些基础功能的实现. AbpWebApplication : 继承自ASP.Net的HttpApplication类,主要完成下面三件事一,在Application_Start完成AbpBootstrapper的初始化.整个ABP系统的初始化就是通过AbpBootstrapper完成初始化的.二,在Application_BeginRequest设置根据request或cookie中的Culture信息,完成当前工作线程的CurrentCu

【WPF学习】第三十三章 高级命令

前面两章介绍了命令的基本内容,可考虑一些更复杂的实现了.接下来介绍如何使用自己的命令,根据目标以不同方式处理相同的命令以及使用命令参数,还将讨论如何支持基本的撤销特性. 一.自定义命令 在5个命令类(ApplicationCommands.NavigationCommands.EditingCommands.ComponentCommands以及MediaCommands)中存储的命令,显然不会为应用程序提供所有可能需要的命令.幸运的是,可以很方便地自定义命令,需要做的全部工作就是实例化一个新的

企业分布式微服务云SpringCloud SpringBoot mybatis (十三)Spring Boot整合MyBatis

Spring中整合MyBatis就不多说了,最近大量使用Spring Boot,因此整理一下Spring Boot中整合MyBatis的步骤.搜了一下Spring Boot整合MyBatis的文章,方法都比较老,比较繁琐.查了一下文档,实际已经支持较为简单的整合与使用.下面就来详细介绍如何在Spring Boot中整合MyBatis,并通过注解方式实现映射. 整合MyBatis 新建Spring Boot项目,或以Chapter1为基础来操作 pom.xml中引入依赖 这里用到spring-bo

老子《道德经》第三十三章

上德不德,是以有德:下德不失德,是以无德. 上德无为而无不为,下德为之而有以为,上仁为之而无以为,上义为之而有以为. 上礼为之而莫之应,则攘臂而扔之. 故失道而后德,失德而后仁,仁而后义,义而后礼. 夫礼者,忠信之薄而乱之首也:前识者,道之华而愚之始也. 是以大丈夫处其厚,不处其薄:居其实,不居其华. 故去彼取此.

第三十三章清风飞雪

http://v.qq.com/page/1/3/q/x0414bf0cp6.html http://v.qq.com/page/1/3/q/x0414bhrgez.html http://v.qq.com/page/1/3/q/x0414bv92pr.html http://v.qq.com/page/1/3/q/x0414c7ach0.html http://v.qq.com/page/1/3/q/x0414ce2caf.html http://v.qq.com/page/1/3/q/x04