赞
踩
**写在前面,认真看本文,你可以获得的技能:1.springboot项目的搭建 2.springboot+Oracle实现增删改查 3. 多数据源的配置 4.前后台交互并实现真分页(网上乱七八糟的绝大部分都是假的分页)**
操作 File—>new–>project 选择spring initializr
项目存储位置,以及名称(demo)
直接下一步,其中的dependencies暂时什么都不选,后面自己添加
现在的项目样子:
建立好的模型是这个样子的:
配置maven仓库:
至此一个spring 项目就建立好了
先在Oracle中创建一个测试表 表名为user_test(随意起)
下面展示一下 代码
。
<!--Oracle-->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.1.0</version>
</dependency>
<!--引入Spring封装的jdbc-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
爆红解决方案:orale驱动手动导入
package com.example.demo.test; import java.sql.*; public class OracleConnection { public static Connection getConnection(){ String url="jdbc:oracle:thin:@自己的:orcl"; String username="账号"; String password="密码"; String driver="oracle.jdbc.driver.OracleDriver"; try { Class.forName(driver); Connection con= DriverManager.getConnection(url, username, password); Statement state=con.createStatement(); //容器 String sql="select * from user_test"; //SQL语句 ResultSet resultSet= state.executeQuery(sql); //将sql语句上传至数据库执行 while (resultSet.next()){ System.out.println(resultSet.getString(1)+"--"+resultSet.getString(2)); } con.close();//关闭通道 return con; } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } return null; } public static void main(String[] args) { Connection conn=OracleConnection.getConnection(); } }
到目前为止,就可以实现Oracle和后台交互,但是太粗糙了,下面进行第三部spring-MVC实现简单的操作
properties文件,也可以是yml文件,我习惯写properties文件
添加相关的dependency4个,加上先前的两个一共6个
<!--web 对应的是RequestMapping等jar包--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- alibaba的druid数据库连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency> <!--mybatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency> <!-- 分页插件 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.2</version> </dependency>
类1:OracleDataSourceProperties类
package com.example.demo.druid; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix = "spring.datasource.oracle")//这里就是properties中配置的数据源前缀 public class OracleDataSourceProperties { private String url; private String username; private String password; private String driverClassName; public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getDriverClassName() { return driverClassName; } public void setDriverClassName(String driverClassName) { this.driverClassName = driverClassName; } }
类2:OracleDataSourceConfig 注意/****/中的问题。
package com.example.demo.druid; import com.alibaba.druid.pool.DruidDataSourceFactory; import com.github.pagehelper.PageInterceptor; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import javax.sql.DataSource; import java.util.Properties; @Configuration @MapperScan(basePackages = OracleDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "oracleSqlSessionFactory") public class OracleDataSourceConfig { //你的mapper位置,会自动扫描,这也就是自动装配的好处了 /** 这里我在mapper层下又建立了一个包oracle,专门用来存储这个数据源的mapper, 为后面的多数据源配置做准备。一定要注意不要写错。 **/ static final String PACKAGE = "com.example.demo.mapper.oracle"; //你的mapper.xml位置 static final String MAPPER_LOCATION = "classpath:oracleMapper/*.xml"; @Autowired private OracleDataSourceProperties config; /** @primary 这个是用来区分数据源的,如果你是多数据源配置,那么一定要在你的主数据源上 添加@primary注释,否则多数据源容易出错。如果你只有一个数据源,那么可以不要这个注解。 **/ @Bean(name = "oracleDataSource") @Primary public DataSource oracleDataSource() throws Exception{ Properties properties = new Properties(); properties.put("driverClassName", config.getDriverClassName()); properties.put("url", config.getUrl()); properties.put("username", config.getUsername()); properties.put("password", config.getPassword()); //#申请连接时,空闲时间大于(timeBetweenEvictionRunsMillis),则检测连接的有效性 true properties.put("testWhileIdle", "true"); //#申请连接时,检测连接的有效性(性能损耗) false properties.put("testOnBorrow", "false"); //#归还连接时,检测连接的有效性(性能损耗) false properties.put("testOnReturn", "false"); return DruidDataSourceFactory.createDataSource(properties); } @Bean(name = "oracleTransactionManager") @Primary public DataSourceTransactionManager oracleTransactionManager()throws Exception{ return new DataSourceTransactionManager(oracleDataSource()); } @Bean(name = "oracleSqlSessionFactory") @Primary public SqlSessionFactory oracleSqlSessionFactory(@Qualifier("oracleDataSource") DataSource oracleDataSource) throws Exception{ final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(oracleDataSource); Properties p = new Properties(); p.setProperty("offsetAsPageNum", "true"); p.setProperty("rowBoundsWithCount", "true"); p.setProperty("reasonable", "true"); //5.1.2版本的pagehelper Interceptor interceptor = new PageInterceptor(); interceptor.setProperties(p); Interceptor[] plugins = new Interceptor[]{interceptor}; sessionFactory.setPlugins(plugins); sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(OracleDataSourceConfig.MAPPER_LOCATION)); return sessionFactory.getObject(); } }
domain(实体类),mapper(dao层),service(服务层),mapper.xml,controller(控制层)
这里需要注意一下,我在mapper层下又建立了一个oracle包,UserMapper是在oracle层下的。
package com.example.demo.domain; public class User { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
@Repository
public interface UserMapper {
List<User> getAll();
}
<?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.demo.mapper.UserMapper"> <resultMap id="BaseResultMap" type="com.example.demo.domain.User"> <result column="USERNAME" property="username" jdbcType="VARCHAR"/> <!--username--> <result column="PASSWORD" property="password" jdbcType="VARCHAR" /> <!--password--> </resultMap> <!--获取上传信息--> <select id="getAll" resultMap="BaseResultMap"> select * from user_test t </select> </mapper>
UserService: public interface UserService { List<User> getAll(); } UserServiecImpl: @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public List<User> getAll() { //这里暂时简单的这样写,后面如果要实现真分页的话 return userMapper.getAll(); //还需要封装才能实现真分页,后面再说。 } }
@RequestMapping("/test") @RestController public class UserController { @Autowired private UserService userService; @RequestMapping("/getAll") private List<User> getAll(){ List<User> users=userService.getAll(); //将查询到的集合遍历一下 for (User u:users){ System.out.println("username:"+u.getUsername()+"_______password:"+u.getPassword()); } return users; } }
至此,简单的Oracle库配合spring实现简单的操作,就可以了,如果你需要增删改,自己可以在mapper中添加即可,这里我就不一一写了,只是一个model而已。
就是你一个项目,可能连接的数据库不止一个,比如一个Oracle数据库,一个MySql数据库,这时就需要用到多数据源配置了。
package com.example.demo.druid; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix = "cluster1.spring.datasource.oracle")/**注意配置的前缀**/ public class Cluster1OracleDataSourceProperties { private String url; private String username; private String password; private String driverClassName; public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getDriverClassName() { return driverClassName; } public void setDriverClassName(String driverClassName) { this.driverClassName = driverClassName; } }
//特别注意必须有一个数据源的config需要添加@primary注解
package com.example.demo.druid; import com.alibaba.druid.pool.DruidDataSourceFactory; import com.github.pagehelper.PageInterceptor; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import javax.sql.DataSource; import java.util.Properties; @Configuration @MapperScan(basePackages = Cluster1OracleDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "cluster1oracleCdSqlSessionFactory") public class Cluster1OracleDataSourceConfig { static final String PACKAGE = "com.example.mapper.oracleclu"; static final String MAPPER_LOCATION = "classpath*:oraclecluMapper/*.xml"; @Autowired private Cluster1OracleDataSourceProperties config; @Bean(name = "cluster1oracleCdDataSource") public DataSource cluster1oracleCdDataSource() throws Exception{ Properties properties = new Properties(); properties.put("driverClassName", config.getDriverClassName()); properties.put("url", config.getUrl()); properties.put("username", config.getUsername()); properties.put("password", config.getPassword()); properties.put("testWhileIdle", "true"); //#申请连接时,检测连接的有效性(性能损耗) false properties.put("testOnBorrow", "false"); //#归还连接时,检测连接的有效性(性能损耗) false properties.put("testOnReturn", "false"); return DruidDataSourceFactory.createDataSource(properties); } @Bean(name = "cluster1oracleCdTransactionManager") public DataSourceTransactionManager cluster1oracleCdTransactionManager()throws Exception{ return new DataSourceTransactionManager(cluster1oracleCdDataSource()); } @Bean(name = "cluster1oracleCdSqlSessionFactory") public SqlSessionFactory cluster1oracleCdSqlSessionFactory(@Qualifier("cluster1oracleCdDataSource") DataSource cluster1oracleCdDataSource) throws Exception{ final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(cluster1oracleCdDataSource); Properties p = new Properties(); p.setProperty("offsetAsPageNum", "true"); p.setProperty("rowBoundsWithCount", "true"); p.setProperty("reasonable", "true"); //5.1.2版本的pagehelper Interceptor interceptor = new PageInterceptor(); interceptor.setProperties(p); Interceptor[] plugins = new Interceptor[]{interceptor}; sessionFactory.setPlugins(plugins); sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(Cluster1OracleDataSourceConfig.MAPPER_LOCATION)); return sessionFactory.getObject(); } }
如果还想添加新的数据源,只需要重复操作就可以实现。但是一定要注意,不同的数据源,存储mapper和mapper.xml的位置是不同的。也就是说新的数据源,需要重新建包。这时在对应的mapper层下写对应的mapper,就可以实现多数据源了。
本人是后台开发人员,前台页面,只能简单的分享一下啊,实现简单的页面展示,以及真分页。
//Params 类是前台传给后台的参数类,可以有多个参数,由于分页,所以必须有几个基本参数
public class Params {
/** 必须的三个参数 **/
private Integer pageNum;
private Integer pageSize;
private PageInfo pageInfo; //是这个包: import com.github.pagehelper.PageInfo;
/*自己的查询条件,可以是多个*/
private String moHu;//模糊查询条件
/**
getter(),setter() 这里自己写了,都贴下来有点多,后面的都这样写了。
**/
// ResultInfo 是将查询的数据封装,以便传给后台。
public class ResultInfo {
private Integer code;
private String msg;
private Object data;
private boolean isSuccess;
/**
getter(),setter(),toString(),无参有参方法。
**/
}
/**进查询到的list进行封装 全贴了吧,不敢省**/ package com.example.demo.util; import com.github.pagehelper.PageInfo; import com.example.demo.selfEntity.ResultInfo; import java.util.List; public class ResultUtil { /** * 请求成功时返回结果 * @param data * @param code * @param msg * @param flag * @return */ public static ResultInfo getResultInfoOk(Object data, Integer code, String msg, boolean flag){ ResultInfo resultInfo = new ResultInfo(code, msg, data, flag); return resultInfo; } public static ResultInfo getResultInfoOk(Object data, Integer code, String msg){ ResultInfo resultInfo = new ResultInfo(code, msg, data, true); return resultInfo; } public static ResultInfo getResultInfoOk(Object data, boolean flag){ ResultInfo resultInfo = new ResultInfo(200, "", data, flag); return resultInfo; } public static ResultInfo getResultInfoOk(Object data, Integer type){ ResultInfo resultInfo = null; switch (type){ case 1:PageInfo pageInfo = new PageInfo((List)data); resultInfo = new ResultInfo(200, "", pageInfo, true); break; case 2:resultInfo = new ResultInfo(200, "", data, true); break; default: } return resultInfo; } public static ResultInfo getResultInfoOk(Object data){ ResultInfo resultInfo = null; if(data instanceof List){ PageInfo pageInfo = new PageInfo((List)data); resultInfo = new ResultInfo(200, "", pageInfo, true); }else { resultInfo = new ResultInfo(200, "", data, true); } return resultInfo; } /** * 请求失败时返回结果 * @param data * @param code * @param msg * @return */ public static ResultInfo getResultInfoFailed(Object data, Integer code, String msg){ ResultInfo resultInfo = new ResultInfo(code, msg, data, false); return resultInfo; } public static ResultInfo getResultInfoFailed(Object data, String msg){ ResultInfo resultInfo = new ResultInfo(200, msg, data, false); return resultInfo; } }
@Repository
public interface UserMapper {
/*分页mapper*/
List<User> getAllUser(Params params);
List<User> getAll();
}
<?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.demo.mapper.oracle.UserMapper"> <resultMap id="BaseResultMap" type="com.example.demo.domain.User"> <result column="USERNAME" property="username" jdbcType="VARCHAR"/> <!--username--> <result column="PASSWORD" property="password" jdbcType="VARCHAR" /> <!--password--> </resultMap> <select id="getAll" resultMap="BaseResultMap"> select t.username,t.password from user_test t </select> <!--分页查询--> <select id="getAllUser" parameterType="com.example.demo.util.Params" resultMap="BaseResultMap"> select t.username,t.password from user_test t where instr(username,#{moHu})>0 </select> </mapper>
public interface UserService {
/*分页专用*/
ResultInfo getAll(Params params); //注意参数
List<User> getAll();
}
/**serviceImpl是真正分页的地方,需要注意**/ package com.example.demo.service.ServiceImpl; import com.example.demo.domain.User; import com.example.demo.mapper.oracle.UserMapper; import com.example.demo.service.UserService; import com.example.demo.util.Params; import com.example.demo.selfEntity.ResultInfo; import com.example.demo.util.ResultUtil; import com.github.pagehelper.PageHelper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public ResultInfo getAll(Params params) { /*开启分页*/ if(params.getPageNum()!=null&¶ms.getPageSize()!=null){ PageHelper.startPage(params.getPageNum(),params.getPageSize(),true); } List<User> users=userMapper.getAllUser(params); /*封装查询的list*/ ResultInfo resultInfo= ResultUtil.getResultInfoOk(users); return resultInfo; } @Override public List<User> getAll() { return userMapper.getAll(); } }
import com.example.demo.service.UserService; import com.example.demo.util.Params; import com.example.demo.selfEntity.ResultInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RequestMapping("/user") @RestController public class UserController { @Autowired private UserService userService; @RequestMapping("/getAll") public ResultInfo getAll(@RequestBody Params params){ ResultInfo resultInfo=userService.getAll(params); return resultInfo; } }
其中导入的一些css,以及js,除了自己写的(我提供代码),其他的都是可以在网上找到的
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>User</title> <link rel="stylesheet" href="../css/bootstrap-3.3.4/css/bootstrap.min.css"> <link rel="stylesheet" href="../ui/layui-v2.5.5/css/layui.css"> </head> <body> <div class="wrap"> <div class="main" id="main"> <div id="sjzx" class="sjzx"> <!--右边的模板是不固定的,先占一个位子放在这--> <router-view ref="mychild"></router-view> </div> </div> </div> </body> <script src="../ui/jquery-3.3.1.min.js"></script> <script type="text/javascript" src="../css/bootstrap-3.3.4/js/bootstrap.min.js"></script> <script type="text/javascript" src="../ui/layui-v2.5.5/layui.js"></script> <script type="text/javascript" src="../ui/vue.js"></script> <script type="text/javascript" src="../js/axios.js"></script> <script type="text/javascript" src="../js/vue-router.js"></script> <!--就这一个js是自己写的--> <script type="module" src="../js/index.js"></script> </html>
这是一个template路由,对Vue不熟的小伙伴,可以跳过,直接复制就可以了
var theOneTemplate; var laypage; var layer; var element; const url='../'; layui.use(['laypage','layer'],function () { laypage=layui.laypage; layer=layui.layer; }) layui.use(['element'],function () { element=layui.element; }) var theOneTemplate={ data(){ return { mjAll:[], pageSize:'15', moHu:'' } }, template:` <div class="sjzxMain" id="oox"> <div class="sjzx-main-top"> <div class="sjzx-main-top-jjbh"> <div class=" input-group" style="width: 300px;margin-top: 8px;"> <span class="input-group-addon">一键查询</span> <input class="form-control" type="text" v-model="moHu" placeholder="请输条件..."> </div> </div> <div class="sjzx-main-top-btn"><button @click="cx">查 询</button></div> </div> <div class="sjzx-main-center"> <table> <thead> <tr> <th style="width: 55px">姓名</th> <th style="width: 165px">密码</th> </tr> </thead> <tbody> <tr v-for="(item,index) in mjAll" > <td>{{item.username}}</td> <td>{{item.password}}</td> </tr> </tbody> </table> </div> <div class="sjzx-main-bottom"> <div id="sjzx-page" class="sjzx-page"></div> </div> </div>`, methods:{ cx:function () { let _this=this; querymj(_this,1,_this.pageSize, _this.moHu); } }, created:function () {}, mounted:function () {}, watch:{ } } function querymj(obj,pageNum,pageSize,moHu) { axios.post(url+'user/getAll',{pageNum:pageNum,pageSize:pageSize,moHu: moHu ,pageInfo:{"pageNum":pageNum, "pageSize":pageSize} }) .then(function (infoResp) { let count=infoResp.data.data.total; obj.mjAll=infoResp.data.data.list; if(count>0){ let _this=obj; laypage.render({ elem:'sjzx-page', count:count, limit:pageSize, curr:pageNum , layout:['count','prev','page','next','refresh','skip'], theme: '#5EB660', jump:function (obj,first) { if(!first){ querymj(_this,obj.curr,_this.pageSize, _this.moHu) } } }); }else { alert("没有数据") } count=0 }); } export {theOneTemplate};
页面js
var theOneTemplate; var laypage; var layer; var element; const url='../'; layui.use(['laypage','layer'],function () { laypage=layui.laypage; layer=layui.layer; }) layui.use(['element'],function () { element=layui.element; }) var theOneTemplate={ data(){ return { mjAll:[], pageSize:'15', moHu:'' } }, template:` <div class="sjzxMain" id="oox"> <div class="sjzx-main-top"> <div class="sjzx-main-top-jjbh"> <div class=" input-group" style="width: 300px;margin-top: 8px;"> <span class="input-group-addon">一键查询</span> <input class="form-control" type="text" v-model="moHu" placeholder="请输条件..."> </div> </div> <div class="sjzx-main-top-btn"><button @click="cx">查 询</button></div> </div> <div class="sjzx-main-center"> <table> <thead> <tr> <th style="width: 55px">姓名</th> <th style="width: 165px">密码</th> </tr> </thead> <tbody> <tr v-for="(item,index) in mjAll" > <td>{{item.username}}</td> <td>{{item.password}}</td> </tr> </tbody> </table> </div> <div class="sjzx-main-bottom"> <div id="sjzx-page" class="sjzx-page"></div> </div> </div>`, methods:{ cx:function () { let _this=this; querymj(_this,1,_this.pageSize, _this.moHu); } }, created:function () {}, mounted:function () {}, watch:{ } } function querymj(obj,pageNum,pageSize,moHu) { axios.post(url+'test/getAll',{pageNum:pageNum,pageSize:pageSize,moHu: moHu ,pageInfo:{"pageNum":pageNum, "pageSize":pageSize} }) .then(function (infoResp) { let count=infoResp.data.data.total; obj.mjAll=infoResp.data.data.list; if(count>0){ let _this=obj; laypage.render({ elem:'sjzx-page', count:count, limit:pageSize, curr:pageNum , layout:['count','prev','page','next','refresh','skip'], theme: '#5EB660', jump:function (obj,first) { if(!first){ querymj(_this,obj.curr,_this.pageSize, _this.moHu) } } }); }else { alert("没有数据") } count=0 }); } export {theOneTemplate};
在后台,我就写了这三个,一个html,两个js,其中的Css一个都没写(css太多了,太烦,调的很麻烦),
这样就可以实现分页了,其中的index.js,调用的是axious,没有使用ajax,个人习惯而已,其实ajax更简单
debug测试看看是如何分页的。
debug,后,直接在浏览器中输入localhost:9090/page/index.html
模糊查询,直接输入了一个y,然后点击查询
注意pageNum,是第一页,当你点击第二页是,pageNum就变成2了
点击下一页
controller serviceImpl 和页面 三张图就一起展示了。
serviceImpl:
页面显示:
其实,还有很多东西可以写,比如说在密码后面再添加一个操作编辑,可以点击增删改查,配合layui还可以在修改的时候,弹出一个修改框等等,这里就不一一介绍了,本来计划还有 6:多线程 7:非controller调用service服务以及 8:slf4j 日志打印的,实在是今天周五了,下班放假出去浪了。
如果有什么问题,可以留言,只要看到就会恢复的,另附上一个md文档,里面的代码比较详细,需要的可以自行下载。
上述功能都是本人测试过的,按照着肯定可以实现。
本文链接:springboot+pagehelper实现真分页以及多数据源的应用
https://blog.csdn.net/y_yanghao/article/details/106288987
写文不宜,转发请注明转载地址,有什么问题,请留言一起相互学习
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。