当前位置: 首页 > news >正文

网站建设主要课程企业网站系统源码

网站建设主要课程,企业网站系统源码,城乡建设和住房建设部八大员,芜湖建设工程质量监督站网站目录 一、MyBatis 简介 1、MyBatis 简介 2、工作流程 二、入门案例 1、准备工作 2、示例 三、Mapper 代理开发 1、问题简介 2、工作流程 3、注意事项 4、测试 四、核心配置文件 mybatis-config.xml 1、environment 2、typeAilases 五、基于 xml 的查询操作 1、…目录 一、MyBatis 简介 1、MyBatis 简介 2、工作流程  二、入门案例 1、准备工作 2、示例 三、Mapper 代理开发 1、问题简介 2、工作流程 3、注意事项 4、测试 四、核心配置文件 mybatis-config.xml 1、environment 2、typeAilases 五、基于 xml 的查询操作 1、准备环境 2、 映射列名 3、根据 id 查询 #{ id } 4、参数传递的 6 种方式 6、动态查询 六、基于 xml 的添加操作 1、添加数据 2、事务提交 3、主键返回 七、基于 xml 的修改操作 1、修改全部字段 2、修改动态字段 八、基于 xml 的删除操作 1、根据 id 删除 2、批量删除 九、注解开发 1、简单的增删改查 一、MyBatis 简介 1、MyBatis 简介 MyBatis 是一款优秀的持久层框架它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJOPlain Old Java Objects普通老式 Java 对象为数据库中的记录。 2、工作流程  1每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的 SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例即 xml 方式、注解方式 2SqlSessionFactory 顾名思义我们可以从中获得 SqlSession 的实例 SqlSession 提供了在数据库执行 SQL 命令所需的所有方法如selectList、selectOne通过 SqlSession 实例来执行已映射的 SQL 语句根据对应 namespace id 执行自定义的 SQL 语句 3释放资源 SqlSession.close() 整个流程大致为 二、入门案例 显然重点在于 MyBatis 的配置文件以及执行相应方法所需要的 mapper 映射文件。下面通过 1 个示例来说明。 1、准备工作 1引入相关依赖 这里使用的数据库是 PostgreSQL可以根据自己的数据库更改。 dependenciesdependencygroupIdorg.mybatis/groupIdartifactIdmybatis/artifactIdversion3.5.10/version/dependencydependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.12/versionscopetest/scope/dependencydependencygroupIdorg.postgresql/groupIdartifactIdpostgresql/artifactIdversion42.6.0/version/dependency /dependencies 2创建一个 Pojo 实体类 构造函数、toString 等等方法自行添加。 package com.demo.pojo;public class User {private Integer id;private String username;private String password;private Integer gender;private String address; }3创建对应的 user 表格 2、示例 我们按照前面的大致流程完成示例。 1mybatis-config.xml 文件命名任意在 resource 目录下创建/mybatis-config.xml首先需要配置数据库信息其次需要链接 mapper 映射文件 ?xml version1.0 encodingUTF-8 ? !DOCTYPE configurationPUBLIC -//mybatis.org//DTD Config 3.0//ENhttp://mybatis.org/dtd/mybatis-3-config.dtdconfiguration!--设置连接数据库的环境--environments defaultdevelopmentenvironment iddevelopmenttransactionManager typeJDBC/dataSource typePOOLEDproperty namedriver valueorg.postgresql.Driver/property nameurl valuejdbc:postgresql://localhost:5432/MyDatabase/property nameusername valuepostgres/property namepassword value123456//dataSource/environment/environments!--引入sql映射文件--mappers!-- 单独引入一个 mapper --mapper resourcemapper/UserMapper.xml//mappers /configuration2UserMapper.xml 在 resource 目录下创建/mapper/mybatis-config.xmlnamespace命名空间一般可以随便写示例一和示例二有所不同id作为当前编写语句的标识符通常与 namespace 连用resultType顾名思义返回类型 ?xml version1.0 encodingUTF-8 ? !DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttps://mybatis.org/dtd/mybatis-3-mapper.dtdmapper namespaceMyUserselect idselectAll resultTypecom.demo.pojo.Userselect * from MyUser; !-- PostgreSQL 写法 --/select /mapper 3Java 代码 Test public void test1() throws IOException {// 1.加载核心配置文件获取 sqlSessionFactory 对象String resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);// 2.获取 sqlSession 对象用来执行sql语句SqlSession sqlSession sqlSessionFactory.openSession();// 3.执行 sqlListUser userList sqlSession.selectList(MyUser.selectAll);System.out.println(userList);// 4.释放资源sqlSession.close(); } 三、Mapper 代理开发 1、问题简介 我们会发现上面的示例有一个大问题当我们使用 sqlSession 对象调用指定的 SQL 语句时传入了一个字符串常量 MyUser.selectAll。 这种硬编码的问题显然不利于后期的维护并且在编写的时候也需要来回查找对应的 SQL 语句的 id。 而我们的 Mapper 代理开发的目的 解决原生方式中的硬编码问题简化后期执行的 SQL 2、工作流程 处理哪个 Pojo 实体类我们就可以创建对应的 mapper 代理对象mapper 代理对象就是一个接口 使用 sqlSession 获取指定的 mapper 代理对象通过 class然后使用 mapper 执行目标 SQL 语句的方法 目标方法的方法名与我们在 xml 文件中设置的 id 值一致 3、注意事项 使用 mapper 代理对象需要 mapper 接口和相同文件名的 xml 在同一个目录下因此在 resources 目录下创建软件包若 resource 没有软件包选项则用 com/demo/mapper 来创建目录或者将 resources 标记为源代码根目录 mapper 配置文件的 namespace 需要改成 mapper 代理对象的类路径 由于以后很肯能会有大量的 Pojo 实体类需要用到 Mapper因此可以在 mybatis-config.xml 中使用包扫描  4、测试 1Java 代码 Test public void test2() throws IOException {String resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession sqlSessionFactory.openSession();// mapper 代理对象需要 mapper 接口 和 xml 在同一个目录下因此在 resources 目录下创建软件包// 没有软件包选项则用 com/demo/mapper 来创建目录或者将 resources 标记为源代码目录UserMapper userMapper sqlSession.getMapper(UserMapper.class);ListUser userList userMapper.selectAll();System.out.println(userList);sqlSession.close(); } 2Mapper 接口类 package com.demo.mapper;import com.demo.pojo.User;import java.util.List;public interface UserMapper {ListUser selectAll(); } 3mybatis-config.xml ?xml version1.0 encodingUTF-8 ? !DOCTYPE configurationPUBLIC -//mybatis.org//DTD Config 3.0//ENhttp://mybatis.org/dtd/mybatis-3-config.dtdconfiguration!--设置连接数据库的环境--environments defaultdevelopmentenvironment iddevelopmenttransactionManager typeJDBC/dataSource typePOOLEDproperty namedriver valueorg.postgresql.Driver/property nameurl valuejdbc:postgresql://localhost:5432/MyDatabase/property nameusername valuepostgres/property namepassword value123456//dataSource/environment/environments!--引入sql映射文件--mappersmapper resourcecom/demo/mapper/UserMapper.xml//mappers /configuration4UserMapper.xml ?xml version1.0 encodingUTF-8 ? !DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttps://mybatis.org/dtd/mybatis-3-mapper.dtdmapper namespacecom.demo.mapper.UserMapperselect idselectAll resultTypecom.demo.pojo.Userselect * from MyUser;/select /mapper 四、核心配置文件 mybatis-config.xml 详情可以参考https://mybatis.org/mybatis-3/zh/configuration.html 下面举两个例子。  1、environment environment 用来配置数据源因此可以在 environments 中配置多个数据源。通过 default 属性值可以动态地切换数据源。 1transactionManager 事务管理方式。这个默认写 JDBC 即可后期开发使用的是 Spring 的事务管理方式。 2dataSource 数据源信息。后期开发也是使用 Spring 来配置数据源默认写上 POOLED 即可。 2、typeAilases 我们在 UserMapper.xml 中需要为返回类型写上类的全路径有一点麻烦。 使用 typeAilases 可以为 POJO 类配置一个别名设置好包的路径后它们的别名默认就是不区分大小写的类名。 五、基于 xml 的查询操作 1、准备环境 1创建表 brand 2创建实体类 Brand package com.demo.pojo;public class Brand {private Integer id;private String brandName;private String companyName;private Integer order;private String description;private Integer status; }3安装 MyBatisX 插件 当我们在 mapper 接口中写上相应的 SQL 语句的方法名时如果已经有很多方法了那么对比起来就很麻烦使用 MyBatisX 可以帮助我们快速定位。 蓝色头顶代表 mapper 的接口红色头顶代表 SQL 的映射文件点击红鸟或者蓝鸟可以在 mapper 接口和 SQL 映射文件之间进行切换 并且 MyBatisX 还能自动生成方法所对应的 SQL 的 id 2、resultMap 映射列名 有的人习惯在创建数据库表的时候列名使用 _ 下划线这样就会导致 MyBatis 无法将数据注入到 POJO 实例中。 而如果给每个带有 _ 下划线的列名都取别名写起来又非常麻烦所以 MyBatis 提供了一个 resultMap 标签用来将表的列名与 POJO 实体类的属性名做一一对应 resultMap idbrandResultMap typecom.demo.pojo.Brandresult columnbrand_name propertybrandName/result columncompany_name propertycompanyName/ /resultMapselect idselectAll resultMapbrandResultMapselect * from MyBrand; /select 需要注意的是select 中不是写 resultType而是写 resultMap。 3、根据 id 查询 #{ id } 显然根据 id 查询时我们需要传入一个 Integer 类型的参数 接口添加参数 映射文件添加 #{id} MyBatis 会根据参数名与 #{ } 内的名做比较来进行注入。 select 有一个属性是 parameterType用于表示参数类型但一般都不写。 1${} 与 #{}  除了 #{ } 这种写法还可以用 ${ } 这种写法它们的区别在于 #{ }会先将 #{ } 替换成 ?然后再将传入的参数赋值给 ?${ }直接将传入的参数替换掉 ${ } 一般情况下我们都推荐使用 #{ }因为 #{ } 将 #{ } 替换成 ?是为了防止 SQL 注入而 ${ } 就不能防止 SQL 注入。 2特殊字符 假如我们写出如下 SQL 语句 显然 会被识别为一个标签的开始所以我们可以做如下措施 转义字符 CDATA 区 4、参数传递的 6 种方式 当我们希望接收如下两个参数来做查询。 1Param(value) Param 的 value 属性用来将其标注的参数按照 value 的属性值找到相同的 #{ value } 来进行注入。比如 value brandName就可以注入到 #{ brandName} 中。 2POJO 实体类 如果传递的参数都属于同一个 POJO 实体类那么就可以用一个实体类的参数来接收他们。这就要求 #{ } 占位符内的名称跟 POJO 实体类的属性名一致。 3Map Map 的要求就很明显了要求 key 的值与 #{ } 内的名称一致。 4Collection 封装为 Map 集合通过 #{ arg0 } 或 #{ collection } 获取可以使用 Param 注解替换 Map 中默认的 arg 键名。 5List 封装为 Map 集合通过 #{ arg0 } 或 #{ collection } 或 #{ list } 获取可以使用 Param 注解替换 Map 中默认的 arg 键名。 6Array 封装为 Map 集合通过 #{ arg0 } 或 #{ array } 获取可以使用 Param 注解替换 Map 中默认的 arg 键名。 7Java 测试代码 Test public void testSelectByCondition() throws IOException {// 模拟从 web 接收参数Integer status 0;String companyName 华为;// 处理参数模糊查询companyName % companyName %;// 封装 Brand 对象Brand brand new Brand();brand.setStatus(status);brand.setCompanyName(companyName);// 设置 map 对象MapString, Object map new HashMap();map.put(status, status);map.put(companyName, companyName);String resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession sqlSessionFactory.openSession();BrandMapper brandMapper sqlSession.getMapper(BrandMapper.class);ListBrand brandList1 brandMapper.selectByConditions1(status, companyName);ListBrand brandList2 brandMapper.selectByConditions2(brand);ListBrand brandList3 brandMapper.selectByConditions3(map);System.out.println(第一种 brandList1);System.out.println(第二种 brandList2);System.out.println(第三种 brandList3);sqlSession.close(); } 5Mapper 配置文件 select idselectByConditions1 resultTypecom.demo.pojo.Brandselect * from MyBrand wherestatus #{ status } andcompanyName like #{ companyName } !-- PostgreSQL 需要 “” 保证大写 -- /select select idselectByConditions2 resultTypecom.demo.pojo.Brandselect * from MyBrand wherestatus #{ status } andcompanyName like #{ companyName } /select select idselectByConditions3 resultTypecom.demo.pojo.Brandselect * from MyBrand wherestatus #{ status } andcompanyName like #{ companyName } /select 6输出结果 6、动态查询 上面的例子其实有 Bug因为用户在操作的时候有可能只希望用一个 companyName 来查询目标数据。也就是说我们需要对原有 SQL 语句做动态修改没有传递过来的参数就不用。 动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架你应该能理解根据不同条件拼接 SQL 语句有多痛苦例如拼接时要确保不能忘记添加必要的空格还要注意去掉列表最后一个列名的逗号。利用动态 SQL可以彻底摆脱这种痛苦。 下面通过几个标签完成动态查询 ifchoose and when 1if test 的多条件动态查询 test 属性值就是我们要做的逻辑判断。 使用 if 时由于 and 关键字不好控制所以一般都加上一个恒等式1 1。 select idselectByDynamic resultTypecom.demo.pojo.Brandselect *from MyBrandwhere 1 1if teststatus ! nulland status #{ status }/ifif testcompanyName ! null and companyName ! and companyName like #{ companyName }/if /select 或者使用 where 标签会根据判断结果来连接也就是 and对应的语句。 select idselectByDynamic resultTypecom.demo.pojo.Brandselect *from MyBrandwhereif teststatus ! nullstatus #{ status }/ifif testcompanyName ! null and companyName ! companyName like #{ companyName }/if/where /select 2choose 的单条件动态查询 有些情况下只允许根据一个的条件进行查询但是条件可以更改。 如果用户只输入一个参数所以可以不用 where。otherwise 可以用来防止用户一个都不输入。如果用户真的一个都不输入可以用 where这样可以省略 otherwise。 select idselectByDynamic resultTypecom.demo.pojo.Brandselect *from MyBrandwhere !-- 因为保证了用户只会输入一个参数所以可以不用 where --choosewhen teststatus ! nullstatus #{ status }/whenwhen testcompanyName ! null and companyName ! companyName like #{ companyName }/whenotherwise1 1/otherwise/choose /select 六、基于 xml 的添加操作 1、添加数据 1接口 2Mapper 映射 insert idaddBrandinsert into MyBrand(brandName, companyName, order, description, status)values(#{brandName}, #{companyName}, #{order}, #{description}, #{status}); /insert 3Java 测试代码 Test public void testAddBrand() throws IOException {String resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession sqlSessionFactory.openSession();BrandMapper brandMapper sqlSession.getMapper(BrandMapper.class);Brand brand new Brand(null, iphone, Apple, 99, iphone 8, 1);brandMapper.addBrand(brand);ListBrand brandList brandMapper.selectAll();System.out.println(brandList);// 提交事务sqlSession.commit();sqlSession.close(); } 2、事务提交 在刚才添加数据的例子中我们发现多写了一句 sqlSession.commit()用于将 SQL 语句的操作提交。如果不写就会发现我们插入的数据没有添加到数据库。 1事务提交的设置方法 sqlSession.commit()手动提交事务sqlSessionFactory.openSession(true)在获取 sqlSession 的时候可以设置是否自动提交默认false即开启事务 3、主键返回 有时在数据添加成功后需要获取插入数据库的主键的值比如 id。 因为数据刚刚添加完成我们并不知道它的 id 值但是此时我们马上要用到 id 作为另一个表的外键那么就需要返回主键值。 1解决方法 在相应的 insert 标签中添加 useGeneratedKeys 和 KeyProperty 属性即可 useGeneratedKeys设置为 trueKeyProperty设置为需要返回的列 2示例 插入一个新的 brand然后获取其 id再次做查询验证 id。 2-1Mapper 映射 insert idaddBrandBackId useGeneratedKeystrue keyPropertyidinsert into MyBrand(brandName, companyName, order, description, status)values(#{brandName}, #{companyName}, #{order}, #{description}, #{status}); /insert 2-2Java 测试代码 Test public void testAddBrand() throws IOException {String resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession sqlSessionFactory.openSession();BrandMapper brandMapper sqlSession.getMapper(BrandMapper.class);Brand brand new Brand(null, iphone, Apple, 99, iphone 8, 1);brandMapper.addBrandBackId(brand);Integer id brand.getId();System.out.println(id);Brand tmp brandMapper.selectById(id);System.out.println(tmp);// 提交事务sqlSession.commit();sqlSession.close(); } 3输出结果 七、基于 xml 的修改操作 1、修改全部字段 传入一个 POJO 实体类做对应的 update 操作即可。 1接口 2Mapper 映射 update idupdateupdate MyBrandsetbrandName #{ brandName },companyName #{ companyName },order #{ order},description #{ description },status #{ status }where id #{ id }; /update 3Java 测试代码 Test public void testUpdate() throws IOException {String resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession sqlSessionFactory.openSession();BrandMapper brandMapper sqlSession.getMapper(BrandMapper.class);int count brandMapper.update(new Brand(9, Iphone, Apple, 66, iphone 18, 1));System.out.println(count);sqlSession.commit();sqlSession.close();} 2、修改动态字段 比如 User 对象密码的修改和其他的内容的修改一般是不会放在一起的修改密码时只需要修改 password其他内容不用修改。 使用 set 标签就可以实现动态 当 update 语句中没有使用 if 标签时如果有一个参数为 null都会导致错误。当在 update 语句中使用 if 标签时如果前面的 if 没有执行则会导致逗号多余错误。使用 set 标签将动态的配置 SET 关键字并剔除追加到条件末尾的任何不相关的逗号。使用 ifset 标签修改后如果某项为 null 则不进行更新而是保持数据库原值。 update idupdateupdate MyBrandsetif testbrandName ! nullbrandName #{ brandName },/ifif testcompanyName ! nullcompanyName #{ companyName },/ifif testorder ! nullorder #{ order },/ifif testdescription ! nulldescription #{ description },/ifif teststatus ! nullstatus #{ status },/if/setwhere id #{ id }; /update 八、基于 xml 的删除操作 1、根据 id 删除 1Mapper 映射文件 delete iddeleteByIddelete from MyBrand where id #{ id }; /delete 2Java 测试代码 Test public void testDeleteById() throws IOException {String resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession sqlSessionFactory.openSession();BrandMapper brandMapper sqlSession.getMapper(BrandMapper.class);int count brandMapper.deleteById(9);sqlSession.commit();sqlSession.close();} 2、批量删除 批量多选删除是我们经常遇到的需求。 实现方法就是将多个 id 封装成 id 数组SQL 语句中用 占位符来接收所有的 id 值。 但是现在问题就在于我们不能确定有多少个 id也就是不能确定有多少个 占位符。 1foreach 为了解决 in 语句的问题MyBatis 提供了一个 foreach 标签可以对一个集合进行遍历 collection表示传入的集合item遍历的每一个元素seperator元素之间的分隔符open/close指定开闭匹配的字符串 其中 collection 需要特别注意MyBatis 会将集合对象封装到一个 Map 对象通过 key 来获取我们传入的集合。 key 的值数组则写 arrayList 实例则写 list也可以用 Param 起别名。 2示例 2-1Mapper 映射文件 delete iddeleteByIdsdelete from MyBrand where id inforeach collectionarray itemid separator, open( close)#{ id }/foreach /delete 九、注解开发 MyBatis 中并不一定使用完全注解开发通常 注解完成简单功能配置文件完成复杂功能 1、简单的增删改查 1Mapper 映射接口 Select(select * from \MyBrand\) ListBrand selectAll();Insert(insert into \MyBrand\(\brandName\, \companyName\, \order\, description, status)\n values(#{brandName}, #{companyName}, #{order}, #{description}, #{status});) void addBrand(Brand brand);Update(update \MyBrand\ set status #{ status }) int update(Brand brand);Delete(delete from \MyBrand\ where id #{ id };) int deleteById(Integer id); 2Java 测试代码 Test public void testAnnotation() throws IOException {String resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession sqlSessionFactory.openSession();BrandMapper brandMapper sqlSession.getMapper(BrandMapper.class);// 增brandMapper.addBrand(new Brand(null, iphone, Apple, 55, Iphone x, 0));// 删brandMapper.deleteById(2);// 改brandMapper.update(new Brand(1, No.1, 华为No.1, 66, 遥遥领先2.0,0));// 查ListBrand brandList brandMapper.selectAll();System.out.println(brandList);sqlSession.commit();sqlSession.close(); } 3输出结果 运行前  运行后
http://www.pierceye.com/news/60453/

相关文章:

  • 做淘宝站外推广网站福鼎市城市建设监察大队网站
  • 常见网站建设网络推广培训一对一
  • 使用html做网站的网页网站开发有前途
  • 建设网站公司挖掘挖掘工具做网站太累
  • 创意包装设计网站郑州微信小程序开发公司排名
  • 36氪网站是用什么做的手机编程软件app下载
  • 洛阳网站建设兼职软件开发培训机构电话
  • 烟台网站建设费用宽屏网站尺寸
  • 伊宁市做网站重庆app推广公司
  • 公司微信网站开发平台网上服装商城网站建设方案策划书
  • 东莞做网站怎么样网页和网站区别
  • 龙岗免费的网站制作企业的网站建设
  • 网站 百度 关键字优化网络服务提供者是谁
  • 徐州开发的网站wordpress目录导航主题
  • 有专门做背景音乐的网站吗菊子曰 wordpress
  • 建立网站tkwordpress仿百度首页
  • 自己做网站,为什么出现403网站订单系统模板
  • 网站设计英语seo免费资源大全
  • 卢松松的网站企业主页是什么
  • 锦州网站建设东莞公司网站制作公司
  • 网站开发是否用html5app推广公司
  • 反钓鱼网站联盟外贸网站建设公司案例
  • 网站视频下载脚本陕西西乡网站建设
  • 个人网页优秀作品邢台优化网站排名
  • asp网站有哪些在58同城做网站有生意吗
  • 做策划需要进的网站家居行业网站建设
  • 大理石在哪些网站做宣传新加坡服务器网站需要备案么
  • 营销型网站方案ppt长鳖春遇网站开发
  • 甘肃省住房和城乡建设厅安置局网站网站正能量免费下载
  • 中国十大小说网站排名最好永久免费素材网