Bin and Legend

Bin and Legend 查看完整档案

填写现居城市  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 该用户太懒什么也没留下

个人动态

Bin and Legend 赞了文章 · 9月19日

04-SpringBoot工程下如何实现对HikariCP连接池的整合?

池化思想分析

池化思想是我们项目开发过程中的一种非常重要的思想,如整数池,字符串池,对象池、连接池、线程池等都是池化思想的一种应用,都是通过复用对象,以减少因创建和释放对象所带来的资源消耗,进而来提升系统性能。例如Integer对象的内部池应用,代码如下:

package com.cy.java.pool;
public class TestInteger01 {
    public static void main(String[] args) {
        Integer n1=100;//Integer.valueOf(100) 编译时优化
        Integer n2=100;
        Integer n3=200;
        Integer n4=200;//池中没有则new Integer(200)
        System.out.println(n1==n2);//true
        System.out.println(n3==n4);//false 
    }
    
}

数据库连接池简介

背景分析

目开发过程中应用程序与数据库交互时,“获得连接”或“释放连接”是非常消耗系统资源的两个过程,频繁地进行数据库连接的建立和关闭会极大影响系统的性能,若多线程并发量很大,这样耗时的数据库连接就可能让系统变得卡顿。因为TCP连接的创建开支十分昂贵,并且数据库所能承载的TCP并发连接数也有限制,针对这种场景,数据库连接池应运而生。如下图所示:

image.png

思考:假如现在是让你去设计一个连接池,你会从什么角度进行设计?
第一:物理存储结构(基于什么结构去存储数据)
第二:基于什么算法从池中取连接?
第三:基于什么算法从池中移除连接?
第四:当池中没有连接时,基于什么方式处理连接请求?
第五:池是可以共享,我们需要考虑池在访问的时并发安全?

连接池原理分析

在系统初始化的时候,在内存中开辟一片空间,将一定数量的数据库连接作为对象存储在对象池里,并对外提供数据库连接的获取和归还方法。用户访问数据库时,并不是建立一个新的连接,而是从数据库连接池中取出一个已有的空闲连接对象;使用完毕归还后的连接也不会马上关闭,而是由数据库连接池统一管理回收,为下一次借用做好准备。如果由于高并发请求导致数据库连接池中的连接被借用完毕,其他线程就会等待,直到有连接被归还。整个过程中,连接并不会关闭,而是源源不断地循环使用,有借有还。数据库连接池还可以通过设置其参数来控制连接池中的初始连接数、连接的上下限数,以及每个连接的最大使用次数、最大空闲时间等,也可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。

Java中的连接池

Java官方,为了在应用程序中更好的应用连接池技术,定义了一套数据源规范,例如javax.sql.DataSource接口,基于这个接口,很多团队或个人创建了不同的连接池对象。然后我们的应用程序中通过耦合与DataSource接口,便可以方便的切换不同厂商的连接池。Java项目中通过连接池获取连接的一个基本过程,如下图所示:

image.png

在上图中,用户通过DataSource对象的getConnection()方法,获取一个连接。假如池中有连接,则直接将连接返回给用户。假如池中没有连接,则会调用Dirver(驱动,由数据库厂商进行实现)对象的connect方法从数据库获取,拿到连接以后,可以将连接在池中放一份,然后将连接返回给调用方。连接需求方再次需要连接时,可以从池中获取,用完以后再还给池对象。

数据库连接池在Java数据库相关中间件产品群中,应该算是底层最基础的一类产品,作为企业应用开发必不可少的组件,无数天才们为我们贡献了一个又一个的优秀产品,它们有的随时代发展,功成身退,有的则还在不断迭代,老而弥坚,更有新生代产品,或性能无敌,或功能全面。目前市场上常见的连接池有DBCP、C3P0,DRUID,HikariCP等。

SpringBoot工程下HikariCP整合测试

数据初始化

打开mysql控制台,然后按如下步骤执行goods.sql文件。
第一步:登录mysql。

mysql –uroot –proot

第二步:设置控制台编码方式。

set names utf8;

第三步:执行goods.sql文件(切记不要打开文件复制到mysql客户端运行)。

source d:/goods.sql

其中goods.sql文件内容如下:

drop database if exists dbgoods;
create database dbgoods default character set utf8;
use dbgoods;
create table tb_goods(
     id bigint primary key auto_increment,
     name varchar(100) not null,
     remark text,
     createdTime datetime not null
)engine=InnoDB;
insert into tb_goods values (null,'java','very good',now());
insert into tb_goods values (null,'mysql','RDBMS',now());
insert into tb_goods values (null,'Oracle','RDBMS',now());
insert into tb_goods values (null,'java','very good',now());
insert into tb_goods values (null,'mysql','RDBMS',now());
insert into tb_goods values (null,'Oracle','RDBMS',now());
insert into tb_goods values (null,'java','very good',now());

创建项目Module并添加相关依赖

第一步:基于IDEA创建项目Module,如图所示:

image.png

第二步:添加依赖
1) mysql数据库驱动依赖。

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

2) spring对象jdbc支持(此时会默认帮我们下载HiKariCP连接池)。

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

配置HikariCP连接池

打开application.properties配置文件,添加如下内容(必写)。

spring.datasource.url=jdbc:mysql:///dbgoods?serverTimezone=GMT%2B8&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root

hikariCP 其它额外配置(可选),代码如下(具体配置不清晰的可自行百度):

spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.pool-name=DatebookHikariCP
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.connection-test-query=SELECT 1

HikariCP 连接池测试

单元测试API设计及应用分析,如图所示:

image.png

在项目中添加单元测试类及测试方法,代码如下:

package com.cy.pj.common.datasource;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class DataSourceTests {
    @Autowired
    private DataSource dataSource;
    @Test
    public void testConnection() throws Exception{
        System.out.println(dataSource.getConnection());
    }
}

在当前测试类中我们需要:

  • 掌握单元测试类、测试方法编写规范。
  • 理解DataSource的设计规范及规范的实现。
  • 分析在测试类中dataSource属性指向的对象是谁?
  • 分析在测试类中DataSource的实现类对象由谁创建和管理?
  • 思考基于DataSource接口获取连接的基本过程是怎样的?

测试BUG分析

  • 数据库不存在,如图所示:

image.png

  • 类编译错误,DataSource为javax.sql包中的类型,如图所示:

image.png

  • 连接错误:数据库连接不上,如图所示:

image.png

基于HikariCP实现JDBC操作(练习)

业务分析

基于HikariCP,借助JDBC技术访问商品库中的数据。

API架构设计

基于业务,进行API设计,如图所示:

image.png

业务时序图分析

基于业务需求,进行商品查询过程的的时序图设计,如图所示:

image.png

业务代码设计及实现

第一步:定义GoodsDao接口,例如:

package com.cy.pj.goods.dao;
import java.util.List;
import java.util.Map;
/**
 * 商品模块数据访问层接口
 */
public interface GoodsDao {
    /**
 * 查询所有商品信息,将每一行记录存储到一个map对象,然后将多个存储到list集合.
 */ List<Map<String,Object>> findGoods();
}

第二步:创建GoodsDao接口实现类,代码如下:

package com.cy.pj.goods.dao;
/**
 * 此对象为一个商品数据层访问对象,现在要求在此类中定义一个方法,这个方法基于JDBC从从数据库获取商品信息,并将其封装到map集合,要求一个行记录一个map对象(key为表中字段名,值为字段名对应的值),多个map存储到list集合. @Repository此注解通常用于描述数据层实现类对象,本质上就是一个特殊的@Component, 都是要交给spring框架管理的一个Bean对象
 */
@Repository
public class DefaultGoodsDao implements  GoodsDao{
       @Autowired
       private DataSource dataSource;//hikariCP
       /**查询商品信息,一行记录映射为内存中的一个map对象*/
       public List<Map<String,Object>> findGoods(){
           Connection conn=null;//java.sql.*
           Statement stmt=null;
           ResultSet rs=null;
           String sql="select * from tb_goods";
           //1.获取连接(从连接池获取)
           try {
               conn=dataSource.getConnection();
               //2.创建statement对象
               stmt=conn.createStatement();
               //3.发送sql
               rs=stmt.executeQuery(sql);
               //4.处理结果
               List<Map<String,Object>> list=new ArrayList<>();
               while(rs.next()){//循环一次取一行,一行记录映射为一个map对象
                  list.add( rowMap(rs));//将存储了一行记录的map对象再存储到list集合
               }
               return list;
           }catch (SQLException e){
               e.printStackTrace();
               throw new RuntimeException(e);//转换为非检查异常(编译时不检测的异常)
           }finally{
               //5. 释放资源
               close(rs,stmt,conn);
           }
       }

定义行映射方法

       private Map<String,Object> rowMap(ResultSet rs)throws SQLException{
           Map<String,Object> rowMap=new HashMap<>();
           //方法1映射
           //rowMap.put("id",rs.getInt("id"));
           //rowMap.put("name",rs.getString("name"));
           //rowMap.put("remark",rs.getString("remark"));
           //rowMap.put("createdTime",rs.getTimestamp("createdTime"));
           //方法2映射
           ResultSetMetaData rsmd=rs.getMetaData();//获取元数据(包括表中的字段名)
           int columnCount=rsmd.getColumnCount();//获取列的数量
           for(int i=0;i<columnCount;i++){
               rowMap.put(rsmd.getColumnLabel(i+1),rs.getObject(rsmd.getColumnLabel(i+1)));
               //getColumnLabel(i+1);获取表中字段名或字段名对应的别名
           }
           return rowMap;
       }

定义释放资源的方法

       private void close(ResultSet rs,Statement stmt,Connection conn){
           if(rs!=null)try{rs.close();}catch(Exception e){e.printStackTrace();}
           if(stmt!=null)try{stmt.close();}catch(Exception e){e.printStackTrace();}
           //这里的连接是返回到了池中
           if(conn!=null)try{conn.close();}catch(Exception e){e.printStackTrace();}
       }
}

测试代码的编写及运行

定义单元测试类,并对其查询过程进行单元测试,例如:

package com.cy.pj.goods.dao;


@SpringBootTest
public class GoodsDaoTests {

      @Autowired
      private GoodsDao goodsDao;

      @Test
      void testFindGoods(){
          List<Map<String,Object>> list= goodsDao.findGoods();
          for(Map<String,Object> map:list){
              System.out.println(map);
          }
      }

}

测试运行过程中的BUG分析

对测试过程中出现的问题进行记录,分析,总结.

总结(Summary)

总之,数据库连接池的为我们的项目开发及运行带来了很多优点,具体如下:

  • 资源重用更佳。

由于数据库连接得到复用,减少了大量创建和关闭连接带来的开销,也大大减少了内存碎片和数据库临时进程、线程的数量,使得整体系统的运行更加平稳。

  • 系统调优更简便。

使用了数据库连接池以后,由于资源重用,大大减少了频繁关闭连接的开销,大大降低了TIME_WAIT的出现频率。

  • 系统响应更快。

数据库连接池在应用初始化的过程中一般都会提前准备好一些数据库连接,业务请求可以直接使用已经创建的连接,而不需要等待创建连接的开销。初始化数据库连接配合资源重用,使得数据库连接池可以大大缩短系统整体响应时间。

  • 连接管理更灵活。

数据库连接池作为一款中间件,用户可以自行配置连接的最小数量、最大数量、最大空闲时间、获取连接超时间、心跳检测等。另外,用户也可以结合新的技术趋势,增加数据库连接池的动态配置、监控、故障演习等一系列实用的功能。

查看原文

赞 75 收藏 22 评论 4

Bin and Legend 发布了文章 · 9月12日

Spring Boot 整合 Spring MVC的基本步骤

Spring Boot 整合Spring MVC 过程

关系图:
image.png
image.png
image.png
image.png
这种关系图的程序代码的书写代码的顺序是从右边往左边写!
要理解Spring MVC 的操作理解:
做这些用到了mybatis 的整合,这样简化了jdbc连接数据库的操作
下面是书写的代码:
-- Application.properties

close banner

spring.main.banner-mode=off

Spring DateSource

spring.datasource.url=jdbc:mysql:///dbgoods?serverTimezone=GMT%2B8&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root

spring mybatis

mybatis.mapper-locations=classpath:/mapper/goods/GoodsMapper.xml

spring log

logging.level.com.cy=debug

server

server.port=80
server.servlet.context-path=/binbin

spring thymleaf

spring.thymeleaf.prefix=classpath:/templates/pages/
spring.thymeleaf.suffix=.html
spring.thymeleaf.cache=false
--GoodsMapper.xml
<?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.cy.pj.goods.dao.GoodsDao">
<delete id="deleteObjects">

   delete from tb_goods
   where id in <!-- (1,2,3,4,5) -->
   <foreach collection="ids"
            open="("
            close=")"
            separator=","
            item="id">
           #{id}
   </foreach>

</delete>
</mapper>
Goods.java
package com.cy.pj.goods.pojo;

import java.util.Date;

public class Goods {

 private Long id;//id bigint primary key auto_increment
 private String name;//name varchar(100) not null
 private String remark;//remark text
 private Date createdTime;//createdTime datetime
public Long getId() {
    return id;
}
public void setId(Long id) {
    this.id = id;
}
public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
public String getRemark() {
    return remark;
}
public void setRemark(String remark) {
    this.remark = remark;
}
public Date getCreatedTime() {
    return createdTime;
}
public void setCreatedTime(Date createdTime) {
    this.createdTime = createdTime;
}
@Override
public String toString() {
    return "Goods [id=" + id + ", name=" + name + ", remark=" + remark + ", createdTime=" + createdTime + "]";
}
 

}
GoodsDao(interface)
package com.cy.pj.goods.dao;

import java.util.List;

import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
/*

  • @Mapper 用于描述(做标记)数据层访问接口,用于告诉mybatis框架,
    使用此注解描述的接口为底层创建实现类,在实现类中基于mybatis API 实现与数据库的交互
    这个类的对象最后 交给spring来管理
    */

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import com.cy.pj.goods.pojo.Goods;

@Mapper
public interface GoodsDao {

@Select("select * from tb_goods")
List<Goods>findGoods();
/**
 *     基于id执行商品信息的删除, 在mybatis中假如sql映射比较简单
 *     可以直接以注解方法进行定义
 * @param id
 * @return
 */
/**
 * 基于id去查找商品信息
 * @param id
 * @return
 */
@Select("select * from tb_goods where id=#{id}")
Goods findById(Integer id);
@Update("update tb_goods set name=#{name},remark=#{remark} where id=#{id}")
int UpdateGoods(Goods goods);
@Delete("delete from tb_goods where id=#{id}")
int deleteById(Integer id);
/**
 *         基于多个id执行商品删除业务操作
 *         ids可变参数,用于接受传入的商品id值
 */
int deleteObjects(@Param("ids")Integer...ids);
@Insert("insert into tb_goods(name,remark,createdTime) values (#{name},#{remark},now())" )

int insertGoods(Goods goods);

}

GoodsService(interface)
package com.cy.pj.goods.service;

import java.util.List;

import com.cy.pj.goods.pojo.Goods;

/**

  • 商品模块的业务层接口,负责具体业务标准定义
  • @author Bin and Legend

*
*/
public interface GoodsService {

        Goods findById(Integer id);
        List<Goods>findGoods();
        int deleteById(Integer id);
        int saveGoods(Goods goods);    
        int UpdateGoods(Goods goods);

}
GoodsServiceImpl
package com.cy.pj.goods.service.impl;
import java.util.Date;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
/**

  • 业务层对象,后续会在此对象中执行
  • 1)核心业务(例如 : 点击购买商品信息,要生成点单项信息,扣减库存 ...)
  • 2)扩展业务 (例如 :事务控制,权限控制,日志记录)

*/
import org.springframework.stereotype.Service;

import com.cy.pj.goods.dao.GoodsDao;
import com.cy.pj.goods.pojo.Goods;
import com.cy.pj.goods.service.GoodsService;

//@Deprecated

@Service//是一个特殊的@Component 也可以用@Component
public class GoodsServiceImpl implements GoodsService{


private static final Logger log = LoggerFactory.getLogger(GoodsServiceImpl.class);

@Autowired
private GoodsDao goodsdao;
@Override
public List<Goods> findGoods() {
    
    return goodsdao.findGoods();
}

@Override
public int saveGoods(Goods goods) {
    // TODO Auto-generated method stub
    goods.setCreatedTime(new Date());
    return goodsdao.insertGoods(goods);
}
@Override
public int deleteById(Integer id) {
        long t1 = System.currentTimeMillis();
        int rows = goodsdao.deleteById(id);
        long t2 = System.currentTimeMillis();
        log.info("deleteById execute time : {}",(t2-t1));
        System.out.println(log.getClass().getName());
    return rows;
}
@Override
public Goods findById(Integer id) {
    
    return goodsdao.findById(id);
}
    
@Override
public int UpdateGoods(Goods goods) {
    // TODO Auto-generated method stub
    return goodsdao.UpdateGoods(goods);
}

}
GoodsController
/**

*/
package com.cy.pj.goods.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import com.cy.pj.goods.pojo.Goods;
import com.cy.pj.goods.service.GoodsService;

/**

  • @author Bin and Legend

*
*/
@Controller
@RequestMapping("/goods/")
public class GoodsController {

//http://localhost/goods/doDeleteById?id=12
@Autowired
private  GoodsService goodsService;
//执行删除操作
@RequestMapping("doDeleteById/{id}")
public String doDeleteById(@PathVariable Integer id) {
    goodsService.deleteById(id);    
    return "redirect:/goods/doGoodsUI";
}

@RequestMapping("doGoodsAddUI")
public String doGoodsAddUI() {
    return "goods-add";
}
@RequestMapping("doGoodsUI")
public String doGoodsUI(Model model) {
    List<Goods> list = goodsService.findGoods();
    model.addAttribute("goods", list);
    return "goods";//view name
}
@RequestMapping("doSaveGoods")
public String doSaveGoods(Goods goods){
    goodsService.saveGoods(goods);
    return "redirect:/goods/doGoodsUI" ;
}
@RequestMapping("doUpdateGoods")
public String doUpdateGoods(Goods goods){
    goodsService.UpdateGoods(goods);
    return "redirect:/goods/doGoodsUI" ;
}
@RequestMapping("doFindById/{id}")
public String doFindById(@PathVariable Integer id,Model model) {
    Goods goods = goodsService.findById(id);
    model.addAttribute("goods", goods);
    return "goods-update";
}
    //FAQ?
    //返回的viewname会给谁?谁调用doGoodsController就给谁(DispatcherServelt)
    //谁负责解析viewname V
    //解析到的结果会响应到哪里
}

goods.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>The Goods Page</h1>
添加商品

idnameremarkcreatedTimeoperation
1AAAAAAAAA....2020/08/31deleteupdate

</body>
</html>
goods-add.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style type="text/css">

    ul li {list-style-type: none}

</style>
</head>
<body>

<h1>The Goods Add page</h1>
<form th:action="@{/goods/doSaveGoods}" method="p">
    <ul>
        <li>name:
        <li><input type="text" name="name">
        <li>remark:
        <li><textarea rows="3" cols="30" name="remark"></textarea>
        <li><input type="submit" value="Save Goods">
    </ul>
</form>

</body>
</html>
goods-update.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style type="text/css">

    ul li {list-style-type: none}

</style>
</head>
<body>

<h1>The Goods Add page</h1>
<form th:action="@{/goods/doUpdateGoods}" method="p">
    <input type="hidden" name="id" th:value="${goods.id}">
    <ul>
        <li>name:
        <li><input type="text" name="name" th:value="${goods.name}">
        <li>remark:
        <li><textarea rows="3" cols="30" name="remark" th:text="${goods.remark}"></textarea>
        <li><input type="submit" value="Save Goods">
    </ul>
</form>

</body>
</html>
后面的是测试类的结果:
DateSourceTests.java
package com.cy.pj.common.datasource;

import java.sql.Connection;

import javax.sql.DataSource;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class DataSourceTests {

/*
 * FAQ? 
 * 请问dataSource对象在运行时指向的具体对象类型是什么 两种:
 * 一:对象。getclass()。getname();通过反射来找到指向的具体对象 二:通过debug测试来,将鼠标指向该连接就可以看到具体对象
 *  请问dataSource对象是有谁帮你创建的?spring框架(基于底层的基本配置)DataSourceAutoConfiguration
 */
    @Autowired
    private DataSource datasource;
    //测试通过数据源DataSource对象获取一个连接
    @Test
    public void testConnection() throws Exception {

// //输出datasource变量指向的对象的类型
// System.out.println(datasource.getClass().getName());//com.zaxxer.hikari.HikariDataSource

            //请问获取连接的过程你了解吗
        //第一次获取连接时会检测连接池是否存在,假如不存在则创建并初始化池
        //基于Driver对象创建与数据库的连接,并将连接放在池中
        //最后从池中返回用户的需要的连接
        Connection conn = datasource.getConnection();
            System.out.println(conn);
    }

}
GoodsDaoTests.java
package com.cy.pj.goods.dao;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import com.cy.pj.goods.dao.GoodsDao;

@SpringBootTest
public class GoodsDaoTests {

    /**    关联数据层接口,并由spring为其进行值的注入
     *     FAQ?
     * 1)GoodsDao指向的对象是谁,由谁创建?由谁管理
     * 2)GoodsDao指向的内部对象会做什么事情? 基于mybatis API进行会话操作
     */
    @Autowired
    private GoodsDao goodsdao;
    @Test
    void testDeleteId() {
        int rows = goodsdao.deleteById(1);
        System.out.println("rows=" + rows);
    }
    @Test
    void testDeleteObject() {
        int rows = goodsdao.deleteObjects(2,3);
        System.out.println("rows=" + rows);
    }

}
GoodsServiceTests.java
package com.cy.pj.goods.service;
import java.util.List;

/**

  • FAQ?
  • 什么是耦合? 耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。耦合的强弱取决于模块间接口的复杂性、调用模块的方式以及通过界面传送数据的多少。

*/
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import com.cy.pj.goods.pojo.Goods;

@SpringBootTest
public class GoodsServiceTests {

    @Autowired//has a
private GoodsService goodsService;
    @Test
    void testFindGoods() {
        List<Goods> list = goodsService.findGoods();
        for(Goods g:list) {
            System.out.println(g);
        }
    }
    @Test
void testDeleteById() {
    int rows = goodsService.deleteById(10);
    System.out.println("rows=" +rows );
}
    

}
这一次的所需要的依赖注入,来自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>
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.0.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.cy</groupId>
<artifactId>CGB-SBOOT-04</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>CGB-SBOOT-04</name>
<description>Demo project for Spring Boot</description>

<properties>
    <java.version>1.8</java.version>
</properties>

<dependencies>
<!-- 此依赖提供了HikariCP连接池 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
       <!-- 负责数据库的的驱动程序 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
    <!-- 添加mybatis starter 依赖(SpringBoot 在这个依赖下提供mybatis的自动配置 -->
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

</project>

查看原文

赞 0 收藏 0 评论 0

Bin and Legend 关注了用户 · 9月11日

木梓姑娘 @muguniang

关注 1

Bin and Legend 关注了用户 · 8月25日

Jason @jason_5f0dbb9eaae42

以终为始,闭环迭代,持续提高。

关注 1772

认证与成就

  • 获得 0 次点赞
  • 获得 0 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 0 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 8月25日
个人主页被 77 人浏览