SpringCloud-4-基础工程-创建服务提供者

发布于:2022-12-20 ⋅ 阅读:(429) ⋅ 点赞:(0)

4.5 创建服务提供者

  • 服务提供者是提供服务的节点,提供者整体结构
    在这里插入图片描述
  • 在父工程下创建一个名为 microservice-cloud-provider-dept-8001 的 Spring Boot Module,并在其 pom.xml 中引入以下依赖。
<?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/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!--引入父工程pom-->
    <parent>
        <artifactId>spring-cloud-microservice</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>microservice-cloud-provider-dept-8001</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>microservice-cloud-provider-dept-8001</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!--引入公共子模块-->
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>microservice-cloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jdbc</artifactId>
        </dependency>
        <!--Spring Boot Web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--devtools 开发工具-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <!--mysql 驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--数据源-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--整合 mybatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <!--spring-boot test 测试只能在test包中测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--junit 测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 修改后立即生效,热部署 这个热部署重启得更快 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>springloaded</artifactId>
            <version>1.2.8.RELEASE</version>
        </dependency>
        <!--日志-->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
        </dependency>
        <!--jetty-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
  • 在 microservice-cloud-provider-dept-8001 类路径(/resources 目录)下,添加配置文件 application.yml,配置内容如下。
server:
  port: 8001
spring:
  application:
    name: microservice-cloud-provider-dept-8001 #微服务名称,对外暴漏的微服务名称,十分重要
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/springcloud_db_core?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimeZone=UTC
    type: com.alibaba.druid.pool.DruidDataSource
    #SpringBoot默认是不注入这些的,需要自己绑定
    #druid数据源专有配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true

    #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
    #如果允许报错,java.lang.ClassNotFoundException: org.apache.Log4j.Priority

    #则导入log4j 依赖就行
    filters: stat,wall,log4j2
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
#整合mybatis
mybatis:
  type-aliases-package: com.zk.springcloud.entity
  mapper-locations: classpath:mybatis/mapper/*.xml
  #config-location: classpath:mybatis/mybatis-config.xml
  configuration:
    map-underscore-to-camel-case: true #默认开启驼峰命名法,可以不用设置该属性

注意:数据源中的url不需要对:进行转义

  • 在 com.example.mapper包下创建一个名为 DeptMapper 的接口,代码如下。
package com.example.mapper;

import com.zk.springcloud.entity.Dept;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

import java.util.List;

@Mapper
@Repository
public interface DeptMapper {

    boolean addDept(Dept dept);

    //根据主键获取数据
     Dept queryDeptByID(Integer deptNo);

    //获取表中的全部数据
    List<Dept> queryAll();
}
  • 在 resources/mybatis/mapper/ 目录下,创建一个名为 DeptMapper.xml 的 MyBatis 映射文件,配置内容如下。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.DeptMapper">
    <resultMap id="BaseResultMap" type="Dept">
        <id column="dept_no" property="deptNo" jdbcType="Integer"/>
        <result column="dept_name" property="deptName" jdbcType="VARCHAR"/>
        <result column="db_source" property="dbSource" jdbcType="VARCHAR"/>
    </resultMap>
    <sql id="Base_Column_List">
        dept_no,dept_name,db_source
    </sql>
    <insert id="addDept" parameterType="Dept">
        INSERT INTO springcloud_db_core.dept(dept_name,db_source)
            VALUES(#{deptName},DATABASE())
    </insert>

    <select id="queryDeptByID" parameterType="java.lang.Integer" resultMap="BaseResultMap">
        select <include refid="Base_Column_List"></include> from springcloud_db_core.dept
        where dept_no =#{deptNo,jdbcType=INTEGER}
    </select>

    <select id="queryAll" resultMap="BaseResultMap">
        select * from springcloud_db_core.dept
    </select>


</mapper>

问题:将jdbcType="Integer"类型写为小写的类型

在这里插入图片描述

即是Mapper.xml文件出错,因为在mybatis的JdbcType枚举类中找不到一个叫Integer的枚举常量

  • 解决方式:

连续按两次Shift键,开启IDEA的全局搜索,并搜索JdbcType,查找给定的常量。

结果发现给定的枚举常量为INTEGER,而不是Integer

将Mapper.xml中所有的jdbcType=“Integer”,改为jdbcType="INTEGER"大写的类型即可成功解决

<resultMap id="BaseResultMap" type="Dept">
        <id column="dept_no" property="deptNo" jdbcType="INTEGER"/>
        <result column="dept_name" property="deptName" jdbcType="VARCHAR"/>
        <result column="db_source" property="dbSource" jdbcType="VARCHAR"/>
    </resultMap>
<select id="queryDeptByID" parameterType="java.lang.Integer" resultMap="BaseResultMap">
        select <include refid="Base_Column_List"></include> from springcloud_db_core.dept
        where dept_no =#{deptNo,jdbcType=INTEGER}
    </select>
package org.apache.ibatis.type;

import java.sql.Types;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Clinton Begin
 */
public enum JdbcType {
  /*
   * This is added to enable basic support for the
   * ARRAY data type - but a custom type handler is still required
   */
  ARRAY(Types.ARRAY),
  BIT(Types.BIT),
  TINYINT(Types.TINYINT),
  SMALLINT(Types.SMALLINT),
  INTEGER(Types.INTEGER),
  BIGINT(Types.BIGINT),
  FLOAT(Types.FLOAT),
  REAL(Types.REAL),
  DOUBLE(Types.DOUBLE),
  NUMERIC(Types.NUMERIC),
  DECIMAL(Types.DECIMAL),
  CHAR(Types.CHAR),
  VARCHAR(Types.VARCHAR),
  LONGVARCHAR(Types.LONGVARCHAR),
  DATE(Types.DATE),
  TIME(Types.TIME),
  TIMESTAMP(Types.TIMESTAMP),
  BINARY(Types.BINARY),
  VARBINARY(Types.VARBINARY),
  LONGVARBINARY(Types.LONGVARBINARY),
  NULL(Types.NULL),
  OTHER(Types.OTHER),
  BLOB(Types.BLOB),
  CLOB(Types.CLOB),
  BOOLEAN(Types.BOOLEAN),
  CURSOR(-10), // Oracle
  UNDEFINED(Integer.MIN_VALUE + 1000),
  NVARCHAR(Types.NVARCHAR), // JDK6
  NCHAR(Types.NCHAR), // JDK6
  NCLOB(Types.NCLOB), // JDK6
  STRUCT(Types.STRUCT),
  JAVA_OBJECT(Types.JAVA_OBJECT),
  DISTINCT(Types.DISTINCT),
  REF(Types.REF),
  DATALINK(Types.DATALINK),
  ROWID(Types.ROWID), // JDK6
  LONGNVARCHAR(Types.LONGNVARCHAR), // JDK6
  SQLXML(Types.SQLXML), // JDK6
  DATETIMEOFFSET(-155), // SQL Server 2008
  TIME_WITH_TIMEZONE(Types.TIME_WITH_TIMEZONE), // JDBC 4.2 JDK8
  TIMESTAMP_WITH_TIMEZONE(Types.TIMESTAMP_WITH_TIMEZONE); // JDBC 4.2 JDK8

  public final int TYPE_CODE;
  private static Map<Integer,JdbcType> codeLookup = new HashMap<>();

  static {
    for (JdbcType type : JdbcType.values()) {
      codeLookup.put(type.TYPE_CODE, type);
    }
  }

  JdbcType(int code) {
    this.TYPE_CODE = code;
  }

  public static JdbcType forCode(int code)  {
    return codeLookup.get(code);
  }

}

  • 在 resources/mybatis/目录下,创建一个名为mybatis-config.xml 的 MyBatis 配置文件,配置内容如下。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--只保留两项,setting,typeAliases-->
    <settings>
        <!--全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。默认开启true-->
        <!--显示的定义出来是为了代码可读性-->
        <setting name="cacheEnabled" value="true"/>
    </settings>
</configuration>
  • 在 com.example.service包下创建一个名为 DeptService 的接口,代码如下。接口中默认是public abstract
package com.example.service;

import com.zk.springcloud.entity.Dept;

import java.util.List;

public interface DeptService {
    boolean addDept(Dept dept);

    //根据主键获取数据
    Dept queryDeptByID(Integer deptNo);

    //获取表中的全部数据
    List<Dept> queryAll();
}
  • 在 com.example.service包下创建 DeptService 接口的实现类 DeptServiceImpl,代码如下。
package com.example.service;

import com.example.mapper.DeptMapper;
import com.zk.springcloud.entity.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author CNCLUKZK
 * @create 2022/9/7-1:42
 */
@Service
public class DeptServiceImpl implements DeptService{

    @Autowired
    private DeptMapper deptMapper;

    @Override
    public boolean addDept(Dept dept) {
        return deptMapper.addDept(dept);
    }

    @Override
    public Dept queryDeptByID(Integer deptNo) {
        return deptMapper.queryDeptByID(deptNo);
    }

    @Override
    public List<Dept> queryAll() {
        return deptMapper.queryAll();
    }
}
  • 在 com.example.controller 包下创建一个名为 DeptController 的 Controller 类,代码如下。
package com.example.controller;

import com.example.service.DeptService;
import com.zk.springcloud.entity.Dept;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @author CNCLUKZK
 * @create 2022/9/7-1:43
 */
@RestController     //提供restful服务,@RestController需要spring-boot-starter-web
//@Slf4j
@RequestMapping("/dept")
public class DeptController {
    @Autowired
    private DeptService deptService;

    @PostMapping("/add")  //GET跟安不安全没关系的,RESTful规范问题
    public boolean addDept(@RequestBody Dept dept) {
        return deptService.addDept(dept);
    }
    @GetMapping("/get/{deptNo}")
    public Dept getDeptByID(@PathVariable("deptNo") Integer deptNo) {
        return deptService.queryDeptByID(deptNo);
    }
    @GetMapping("/list")
    public List<Dept> queryAll() {
        return deptService.queryAll();
    }
}
  • 然后,启动microservice-cloud-provider-dept-8001项目的启动类,测试运行

在这里插入图片描述

  • 访问http://127.0.0.1:8001/dept/get/1结果:

在这里插入图片描述

  • 访问http://127.0.0.1:8001/dept/list

在这里插入图片描述

  • 说明microservice-cloud-provider-dept-8001项目运行正常

开发期间存在的问题1:Spring Boot项目中含有Mybatis,打Jar包运行之后,报如下错误.

Failed to configure a DataSource: ‘url’ attribute is not specified and no embedded datasource could be configured.

Reason: Failed to determine a suitable driver class

在这里插入图片描述

  • 解决方式:

问题原因:Mybatis没有找到合适的驱动,即spring :datasource:url没有加载成功

  • DataSourceAutoConfiguration会自动加载.
  • spring :datasource:url 属性配置有误,如地址格式有问题
  • spring :datasource:url属性配置所在的yml,properties文件没有被加载
  • 解决方式1:排除此类的autoconfig。启动以后就可以正常运行
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
  • 解决方式2:在application.properties/或者application.yml文件中配置正确的数据库信息,在spring.xml配置文件中引用了数据库地址 所以需要对:等进行转义处理.但是在application.properties/或者application.yml文件并不需要转义
spring:
  application:
    name: microservice-cloud-provider-dept-8001
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/springcloud_db_core?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimeZone=UTC
    type: com.alibaba.druid.pool.DruidDataSource
    //错误示例
	spring.datasource.url = jdbc:mysql\://localhost\:3306/springcloud_db_core?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimeZone=UTC
  • 解决方式3:yml或者properties文件没有被扫描到,需要在pom文件中build添加资源过滤设置。来保证文件都能正常被扫描到并且加载成功.
<resources>
    <resource>
        <directory>src/main/resources</directory>
        <includes>
            <include>**/*.yml</include>
            <include>**/*.properties</include>
            <include>**/*.xml</include>
        </includes>
        <filtering>true</filtering>
    </resource>
    <resource>
        <directory>src/main/java</directory>
        <includes>
            <include>**/*.yml</include>
            <include>**/*.properties</include>
            <include>**/*.xml</include>
        </includes>
        <filtering>true</filtering>
    </resource>
</resources>
  • 问题2:新导入项目,提示报 Cannot access org.springframework.context.ConfigurableApplicationContext的错

    • 解决办法1:需删除导入项目自动生成的xxx.iml ,然后刷新下右侧maven tab即可

在这里插入图片描述

  • 若找不到Maven这个tab,可以通过help下的Find Action,在搜索框中搜索Maven

在这里插入图片描述

  • 解决办法2:若删除删除xxx.iml 后模块 pom变成了灰色并有删除线,需要添加模块的pom.xml,具体是先看Module是否报错,没错时点击“+”add maven project

在这里插入图片描述

  • 在弹框中选择模块自己的pom.xml文件,然后刷新一下即可解决问题,额外注意下子模块的变动引起的父工程的变化。

在这里插入图片描述

下一篇:SpringCloud-5-基础工程-创建服务服务消费者


网站公告

今日签到

点亮在社区的每一天
去签到