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

衡水网站建设格公司软件外包公司排行

衡水网站建设格公司,软件外包公司排行,常熟网站建设书生商友,建设学校网站的报告在第一篇博客中#xff0c;我们掌握了 MyBatis 的基础概念与环境搭建#xff0c;成功通过简单查询实现了数据持久化。但要真正用好 MyBatis#xff0c;还需深入理解其 “内部工作原理” 与 “企业级开发规范”。本篇将聚焦三大核心#xff1a;MyBatis 架构与核心类、全局配…        在第一篇博客中我们掌握了 MyBatis 的基础概念与环境搭建成功通过简单查询实现了数据持久化。但要真正用好 MyBatis还需深入理解其 “内部工作原理” 与 “企业级开发规范”。本篇将聚焦三大核心MyBatis 架构与核心类、全局配置文件详解、Mapper 代理开发企业主流方案帮你从 “会用” 升级到 “懂原理、能规范开发”。 目录 一、深入 MyBatis 架构三层架构 核心类解析 1.1 三层架构从 “调用入口” 到 “基础支撑” 1API 接口层上层应用的 “交互入口” 2数据处理层核心层MyBatis 的 “业务大脑” 3基础支撑层MyBatis 的 “后勤保障” 1.2 5 个核心类MyBatis 的 “关键零件” 核心类工作流程示例以 “查询部门” 为例 二、MyBatis 全局配置文件SqlMapConfig.xml 详解 2.1 properties标签灵活管理数据源参数 方式 1内部直接定义属性简单但不推荐 方式 2加载外部jdbc.properties文件推荐 方式 3动态传入属性了解特殊场景用 2.2 settings标签MyBatis 的 “运行开关” 配置示例 2.3 typeAliases标签简化全限定类名的 “别名神器” 方式 1为单个类定义别名简单场景用 方式 2为包下所有类定义别名推荐企业常用 2.4 environments标签多环境配置开发 / 测试 / 生产 配置示例 关键子标签说明 切换环境 2.5 mappers标签告诉 MyBatis “SQL 在哪里” 方式 1加载类路径下的 Mapper.xml入门用 方式 2加载本地文件系统的 Mapper.xml了解 方式 3加载单个 Mapper 接口Mapper 代理用 方式 4扫描包下所有 Mapper 接口推荐企业常用 三、Mapper 代理开发企业级 Dao 层开发规范 3.1 为什么要放弃 “原始 Dao 开发” 3.2 Mapper 代理开发的 4 个核心规范 3.3 Mapper 代理开发实战步骤 步骤 1创建 Mapper 接口DeptMapper.java 步骤 2创建对应的 Mapper.xmlDeptMapper.xml 步骤 3配置SqlMapConfig.xml的mappers标签 步骤 4编写测试类通过代理对象调用方法 代理开发的优势总结 四、总结与下一步预告 一、深入 MyBatis 架构三层架构 核心类解析 就像开车需要了解方向盘、油门的作用使用 MyBatis 前搞懂其架构与核心类能让你在遇到问题时快速定位原因。MyBatis 的功能架构自上而下分为三层核心类则是每层的 “关键执行器”。 1.1 三层架构从 “调用入口” 到 “基础支撑” MyBatis 的架构设计清晰每层职责明确协同完成数据库操作具体如下 1API 接口层上层应用的 “交互入口” 这是我们最常接触的一层核心对象是SqlSession—— 它是上层应用如 Service 层与 MyBatis 的 “桥梁”提供了 CRUD 操作的所有方法如selectList()查询列表、insert()插入数据、update()更新数据。 我们无需关心底层如何执行 SQL只需通过SqlSession调用对应的方法即可。例如 // 通过SqlSession调用查询方法定位SQL的“namespaceid” ListDept depts session.selectList(com.jr.mapper.DeptMapper.selectDept);当SqlSession接收到调用请求后会将任务交给下一层数据处理层执行。 2数据处理层核心层MyBatis 的 “业务大脑” 这是 MyBatis 的核心负责完成数据库操作的全流程主要做四件事 参数映射将 Java 代码传入的参数如Integer deptno解析并转换为 JDBC 支持的类型如SQL INTEGERSQL 解析读取 Mapper.xml 中的 SQL 语句处理动态 SQL如if、where标签生成最终可执行的 SQLSQL 执行通过执行器Executor调用 JDBC API 执行 SQL与数据库交互结果映射将数据库返回的 ResultSet 结果集自动映射为 Java 实体类如Dept对象无需手动遍历赋值。 这一层的核心组件是Executor执行器它是 SQL 执行的 “实际操作者”MyBatis 提供了三种常用执行器 SimpleExecutor默认执行器每次执行 SQL 都会创建新的PreparedStatementReuseExecutor重用PreparedStatement避免重复创建提升性能BatchExecutor支持批量更新适用于大量插入 / 更新场景。 3基础支撑层MyBatis 的 “后勤保障” 这一层提供通用功能支撑为上层数据处理层服务核心能力包括 连接管理通过数据源DataSource管理数据库连接支持连接池如POOLED类型避免频繁创建 / 关闭连接事务管理支持 JDBC 事务手动提交 / 回滚和 MANAGED 事务交给容器管理如 Spring缓存处理实现一级缓存SqlSession级别和二级缓存Mapper级别减少数据库访问次数工具类提供 XML 解析、反射、日志打印等基础工具简化框架内部逻辑。 1.2 5 个核心类MyBatis 的 “关键零件” 理解核心类的作用与生命周期是排查问题、优化性能的关键下表整理了必须掌握的 5 个核心类 核心类核心作用生命周期关键特点SqlSessionFactory创建SqlSession的 “工厂”应用启动时创建全局唯一一旦创建需一直存在不可重复创建浪费资源SqlSession与数据库的 “一次会话”提供 CRUD 方法每次操作数据库时创建用完关闭非线程安全必须手动关闭推荐try-finallyExecutor执行器负责 SQL 的实际执行查询 / 更新每个SqlSession对应一个Executor可通过配置切换执行器类型如批量执行器MappedStatement存储 Mapper.xml 中的 SQL 信息id、参数、结果映射应用启动时加载全局唯一每个 SQL 节点如select对应一个实例Configuration存储 MyBatis 的所有配置信息数据源、映射、settings应用启动时解析配置文件生成是 MyBatis 的 “配置中心”所有核心类都依赖它 核心类工作流程示例以 “查询部门” 为例 应用启动时解析SqlMapConfig.xml和DeptMapper.xml生成Configuration对象通过SqlSessionFactoryBuilder读取Configuration创建SqlSessionFactory调用SqlSessionFactory.openSession()创建SqlSession并为其分配Executor调用SqlSession.selectList(com.jr.mapper.DeptMapper.selectDept)SqlSession通过 “namespaceid” 找到对应的MappedStatementExecutor根据MappedStatement中的 SQL 信息执行 SQL 并处理结果最终返回Dept列表关闭SqlSession释放Executor与数据库连接。 二、MyBatis 全局配置文件SqlMapConfig.xml 详解 SqlMapConfig.xml是 MyBatis 的 “全局控制中心”所有影响 MyBatis 行为的配置都集中在这里。上篇我们只写了基础配置本篇将详细解析 5 个核心配置标签覆盖企业开发中的常用场景。 2.1 properties标签灵活管理数据源参数 properties标签用于加载数据库连接参数如驱动、URL、用户名、密码避免硬编码在配置文件中支持三种使用方式推荐第二种加载外部属性文件。 方式 1内部直接定义属性简单但不推荐 直接在properties标签内写死参数修改时需改配置文件灵活性差 configuration!-- 内部定义数据源参数 --propertiesproperty namedriver valuecom.mysql.cj.jdbc.Driver/property nameurl valuejdbc:mysql://localhost:3306/mytestdb?serverTimezoneGMTamp;useSSLfalse/property nameusername valueroot/property namepassword valueroot//properties!-- 使用参数${属性名} --environments defaultdevelopmentenvironment iddevelopmenttransactionManager typeJDBC/dataSource typePOOLEDproperty namedriver value${driver}/property nameurl value${url}/property nameusername value${username}/property namepassword value${password}//dataSource/environment/environments /configuration方式 2加载外部jdbc.properties文件推荐 将参数放在独立的属性文件中实现 “参数与配置分离”修改参数无需动SqlMapConfig.xml 在src/main/resources下新建jdbc.properties文件 # jdbc.properties单独存储数据源参数 drivercom.mysql.cj.jdbc.Driver urljdbc:mysql://localhost:3306/mytestdb?serverTimezoneGMTuseSSLfalse usernameroot passwordroot在SqlMapConfig.xml中加载该文件 configuration!-- 加载外部属性文件resource指定文件路径类路径下 --properties resourcejdbc.properties/!-- 直接使用${属性名}引用参数 --environments defaultdevelopmentenvironment iddevelopmenttransactionManager typeJDBC/dataSource typePOOLEDproperty namedriver value${driver}/property nameurl value${url}/property nameusername value${username}/property namepassword value${password}//dataSource/environment/environments /configuration方式 3动态传入属性了解特殊场景用 通过SqlSessionFactoryBuilder.build()方法动态传入参数覆盖配置文件中的值适用于 “临时切换数据源” 场景 // 1. 加载配置文件 InputStream is Resources.getResourceAsStream(SqlMapConfig.xml); // 2. 动态创建属性覆盖url Properties props new Properties(); props.setProperty(url, jdbc:mysql://localhost:3306/testdb2?serverTimezoneGMTuseSSLfalse); // 3. 传入属性创建SqlSessionFactory SqlSessionFactory factory new SqlSessionFactoryBuilder().build(is, props);重要优先级规则动态传入的属性 外部属性文件 内部定义的属性即后加载的属性会覆盖先加载的同名属性。 2.2 settings标签MyBatis 的 “运行开关” settings标签用于配置 MyBatis 的全局运行参数这些参数直接影响框架的性能与行为。企业开发中常用的配置如下 设置项作用描述默认值推荐配置cacheEnabled开启全局二级缓存后续博客详解true保持默认 truelazyLoadingEnabled开启延迟加载按需加载关联数据如查员工时不默认查部门false复杂项目设为 trueaggressiveLazyLoading开启 “积极懒加载”访问实体类任一属性加载所有关联数据false3.4.1设为 false按需加载更灵活mapUnderscoreToCamelCase开启 “下划线转驼峰”数据库字段dept_name自动映射为实体类属性deptNamefalse必须设为 true避免手动映射字段logImpl指定日志实现如 SLF4J、LOG4J未设置开发环境设为 LOG4J方便看 SQL 日志 配置示例 configurationproperties resourcejdbc.properties/!-- settings标签必须在properties之后、typeAliases之前 --settings!-- 开启下划线转驼峰避免手动映射字段 --setting namemapUnderscoreToCamelCase valuetrue/!-- 开启延迟加载优化关联查询性能 --setting namelazyLoadingEnabled valuetrue/!-- 关闭积极懒加载按需加载关联数据 --setting nameaggressiveLazyLoading valuefalse//settings!-- 其他配置... -- /configuration2.3 typeAliases标签简化全限定类名的 “别名神器” 在 Mapper.xml 中resultType/parameterType需要写实体类的全限定类名如com.jr.pojo.Dept重复书写繁琐且易出错。typeAliases标签可给实体类定义 “别名”简化书写。 方式 1为单个类定义别名简单场景用 configurationproperties resourcejdbc.properties/settings.../settings!-- 为单个实体类定义别名 --typeAliases!-- alias别名type实体类全限定类名 --typeAlias aliasdept typecom.jr.pojo.Dept/typeAlias aliasemp typecom.jr.pojo.Emp//typeAliases!-- 其他配置... -- /configuration使用时直接写别名无需全限定类名 !-- Mapper.xml中使用别名 -- select idselectDept resultTypedept !-- 直接用“dept”代替“com.jr.pojo.Dept” --select * from dept /select方式 2为包下所有类定义别名推荐企业常用 若实体类较多逐个定义别名太麻烦可直接扫描整个包MyBatis 会自动将 “类名首字母小写” 作为别名如Dept→dept、Emp→emp configurationproperties resourcejdbc.properties/settings.../settings!-- 扫描com.jr.pojo包下所有实体类自动生成别名 --typeAliasespackage namecom.jr.pojo//typeAliases!-- 其他配置... -- /configuration特殊需求若想自定义别名不使用首字母小写可在实体类上添加Alias注解 import org.apache.ibatis.type.Alias;Alias(myDept) // 自定义别名“myDept” public class Dept {// 实体类属性、getter/setter... }使用时直接写自定义别名 select idselectDept resultTypemyDeptselect * from dept /select2.4 environments标签多环境配置开发 / 测试 / 生产 实际项目中开发、测试、生产环境的数据库配置不同如开发用本地库生产用服务器库environments标签支持配置多个环境默认激活一个。 配置示例 configurationproperties resourcejdbc.properties/settings.../settingstypeAliases.../typeAliases!-- default默认激活的环境ID此处为开发环境 --environments defaultdevelopment!-- 开发环境 --environment iddevelopment!-- 事务管理器JDBC手动控制事务 --transactionManager typeJDBC/!-- 数据源POOLED连接池开发/测试用 --dataSource typePOOLEDproperty namedriver value${dev.driver}/property nameurl value${dev.url}/property nameusername value${dev.username}/property namepassword value${dev.password}//dataSource/environment!-- 生产环境 --environment idproduction!-- 事务管理器MANAGED交给Spring容器管理 --transactionManager typeMANAGED/!-- 数据源POOLED生产环境也用连接池提升性能 --dataSource typePOOLEDproperty namedriver value${prod.driver}/property nameurl value${prod.url}/property nameusername value${prod.username}/property namepassword value${prod.password}//dataSource/environment/environments!-- 其他配置... -- /configuration对应的jdbc.properties需包含多环境参数 # 开发环境参数 dev.drivercom.mysql.cj.jdbc.Driver dev.urljdbc:mysql://localhost:3306/dev_db?serverTimezoneGMTuseSSLfalse dev.usernameroot dev.passwordroot# 生产环境参数 prod.drivercom.mysql.cj.jdbc.Driver prod.urljdbc:mysql://192.168.1.100:3306/prod_db?serverTimezoneGMTuseSSLfalse prod.usernameprod_user prod.passwordprod_pwd关键子标签说明 transactionManager事务管理器 支持两种类型JDBC依赖数据源连接手动调用session.commit()提交事务和MANAGED不管理事务交给容器如 Spring 处理MyBatis 只负责 SQL 执行。dataSource数据源 支持三种类型 POOLED连接池创建连接池管理连接避免频繁创建 / 关闭开发 / 测试 / 生产都推荐UNPOOLED无连接池每次执行 SQL 都新建连接性能差仅适用于小规模项目JNDI从应用服务器如 Tomcat的 JNDI 数据源获取连接适用于 JavaEE 企业级项目。 切换环境 默认使用default指定的环境若需切换如测试时用生产环境配置可在创建SqlSessionFactory时指定环境 ID InputStream is Resources.getResourceAsStream(SqlMapConfig.xml); // 指定激活“production”环境 SqlSessionFactory factory new SqlSessionFactoryBuilder().build(is, production);2.5 mappers标签告诉 MyBatis “SQL 在哪里” mappers标签用于配置 “Mapper 映射文件” 或 “Mapper 接口” 的位置 ——MyBatis 需要通过它找到我们写的 SQL 语句常用四种配置方式企业开发推荐后两种Mapper 代理用。 方式 1加载类路径下的 Mapper.xml入门用 通过resource指定 Mapper.xml 的类路径适用于 “普通项目” 或 “非代理开发” 场景 mappersmapper resourcecom/jr/mapper/DeptMapper.xml/mapper resourcecom/jr/mapper/EmpMapper.xml/ /mappers方式 2加载本地文件系统的 Mapper.xml了解 通过url指定本地文件的绝对路径适用于 Mapper.xml 不在类路径下的场景很少用 mappersmapper urlfile:///D:/mybatis-project/mappers/DeptMapper.xml/ /mappers方式 3加载单个 Mapper 接口Mapper 代理用 通过class指定 Mapper 接口的全限定类名适用于 “Mapper 代理开发”后续详解要求Mapper 接口与 Mapper.xml 在同一包下且文件名相同 mappersmapper classcom.jr.mapper.DeptMapper/mapper classcom.jr.mapper.EmpMapper/ /mappers方式 4扫描包下所有 Mapper 接口推荐企业常用 通过package扫描整个包下的所有 Mapper 接口自动关联对应的 Mapper.xml要求与方式 3 一致接口与 XML 同包同名简化大量配置 mappers!-- 扫描com.jr.mapper包下所有Mapper接口 --package namecom.jr.mapper/ /mappers三、Mapper 代理开发企业级 Dao 层开发规范 在第一篇的环境搭建中我们通过SqlSession.selectList(namespaceid)调用 SQL这种方式属于 “原始 Dao 开发”。但在企业项目中更推荐Mapper 代理开发—— 无需编写 Dao 接口的实现类MyBatis 会自动生成代理对象大幅减少重复代码。 3.1 为什么要放弃 “原始 Dao 开发” 原始 Dao 开发需要手动编写 Dao 接口的实现类如DeptDaoImpl存在三个明显缺点 模板代码冗余实现类中大量重复代码如创建SqlSession、调用方法、关闭SqlSession开发者沦为 “代码搬运工”SQL ID 硬编码调用SqlSession方法时需写死 SQL 的 “namespaceid”如session.selectList(com.jr.mapper.DeptMapper.selectDept)写错不会在编译期报错只能在运行时发现类型不安全SqlSession的方法参数与返回值大量使用泛型如selectList()返回ListObject若参数类型或返回值类型错误编译期无法察觉。 而 Mapper 代理开发能完美解决这些问题 —— 只需写 “Mapper 接口” 和 “Mapper.xml”MyBatis 自动生成实现类代理对象既简洁又安全。 3.2 Mapper 代理开发的 4 个核心规范 要让 MyBatis 自动生成代理对象必须遵守以下 4 个规范缺一不可否则框架无法关联接口与 SQL 接口与 XML 同包同名Mapper 接口如DeptMapper.java与 Mapper.xml如DeptMapper.xml必须在同一包下且文件名完全相同XML 的 namespace 与接口全路径一致Mapper.xml 的namespace属性必须等于 Mapper 接口的全限定类名如com.jr.mapper.DeptMapper接口方法名与 XML 的 SQL ID 一致Mapper 接口中的方法名如selectDept()必须等于 Mapper.xml 中 SQL 标签的id如select idselectDept接口方法参数 / 返回值与 XML 匹配 接口方法的参数类型 ≡ XML 中 SQL 的parameterType接口方法的返回值类型 ≡ XML 中 SQL 的resultType/resultMap若返回列表返回值类型为List实体类XML 中resultType为单个实体类。 3.3 Mapper 代理开发实战步骤 以 “查询部门列表” 为例完整演示 Mapper 代理开发的流程基于 Maven 项目 步骤 1创建 Mapper 接口DeptMapper.java 在src/main/java/com/jr/mapper下创建接口定义查询方法无需写实现类 package com.jr.mapper;import com.jr.pojo.Dept; import java.util.List;// 规范1接口名与后续XML文件名相同DeptMapper public interface DeptMapper {// 规范3方法名与XML中SQL的id一致selectDept// 规范4返回值类型为ListDept对应XML中resultTypedept单个实体类ListDept selectDept();// 新增根据部门编号查询单个部门演示参数匹配// 规范4参数类型为int对应XML中parameterTypeint返回值为Dept对应resultTypedeptDept selectDeptByNo(int deptno); }步骤 2创建对应的 Mapper.xmlDeptMapper.xml 在src/main/resources/com/jr/mapper下创建 XML 文件与接口同包同名配置 SQL 并遵守规范 ?xml version1.0 encodingUTF-8 ? !DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttps://mybatis.org/dtd/mybatis-3-mapper.dtd!-- 规范2namespace等于Mapper接口全路径com.jr.mapper.DeptMapper -- mapper namespacecom.jr.mapper.DeptMapper!-- 规范3id等于接口方法名selectDept --!-- 规范4resultTypedept单个实体类对应接口返回值ListDept --select idselectDept resultTypedeptselect * from dept/select!-- 规范3id等于接口方法名selectDeptByNo --!-- 规范4parameterTypeint接口方法参数类型resultTypedept返回值类型 --select idselectDeptByNo parameterTypeint resultTypedeptselect * from dept where deptno #{deptno}/select /mapper步骤 3配置SqlMapConfig.xml的mappers标签 使用 “扫描包” 方式加载 Mapper 接口企业推荐 configurationproperties resourcejdbc.properties/settingssetting namemapUnderscoreToCamelCase valuetrue//settingstypeAliasespackage namecom.jr.pojo/ !-- 扫描实体类生成别名 --/typeAliasesenvironments defaultdevelopment!-- 数据源配置... --/environments!-- 规范扫描Mapper接口所在包自动关联XML --mapperspackage namecom.jr.mapper//mappers /configuration步骤 4编写测试类通过代理对象调用方法 通过SqlSession.getMapper(接口.class)获取 MyBatis 自动生成的代理对象直接调用接口方法 import com.jr.mapper.DeptMapper; import com.jr.pojo.Dept; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Before; import org.junit.Test; import java.io.InputStream; import java.util.List;public class DeptMapperTest {private SqlSessionFactory factory;// 测试前初始化SqlSessionFactory只执行一次Beforepublic void setUp() throws Exception {InputStream is Resources.getResourceAsStream(SqlMapConfig.xml);factory new SqlSessionFactoryBuilder().build(is);}// 测试查询所有部门Testpublic void testSelectDept() {SqlSession session null;try {session factory.openSession();// 获取Mapper代理对象MyBatis自动生成无需手动new实现类DeptMapper deptMapper session.getMapper(DeptMapper.class);// 直接调用接口方法底层自动执行SQLListDept depts deptMapper.selectDept();for (Dept dept : depts) {System.out.println(dept);}} finally {// 确保关闭会话if (session ! null) {session.close();}}}// 测试根据部门编号查询Testpublic void testSelectDeptByNo() {SqlSession session null;try {session factory.openSession();DeptMapper deptMapper session.getMapper(DeptMapper.class);// 传入参数调用方法Dept dept deptMapper.selectDeptByNo(10);System.out.println(dept); // 输出Dept{deptno10, dnameACCOUNTING, locNEW YORK}} finally {if (session ! null) {session.close();}}} }代理开发的优势总结 无模板代码无需写 Dao 实现类MyBatis 自动生成代理对象SQL ID 无硬编码通过接口方法名关联 SQL编译期可检查错误类型安全接口方法的参数与返回值类型明确编译期可发现类型错误符合面向接口编程符合企业级开发规范便于团队协作与后期维护。 四、总结与下一步预告 本篇博客我们深入 MyBatis 的核心 理解了 MyBatis 的三层架构与核心类知道 SQL 是如何从 “调用” 到 “执行” 的掌握了全局配置文件SqlMapConfig.xml的 5 个核心标签能应对企业级项目的配置需求学会了 Mapper 代理开发规范摆脱了原始 Dao 开发的冗余与不安全实现了 “接口 XML” 的简洁开发。 第三篇预告MyBatis 的 “高级特性”—— 动态 SQL灵活处理多条件查询、关联查询一对一 / 一对多、查询缓存一级 / 二级缓存优化性能这些是解决复杂业务场景的关键也是面试高频考点。跟着系列博客一步步深入你会发现 MyBatis 的强大与灵活真正做到 “知其然更知其所以然”。
http://www.zqtcl.cn/news/281126/

相关文章:

  • 诸暨网站制作设计公众号文章怎么导入到wordpress
  • 网站死链怎么办青岛网站制作企业
  • 已经有域名 怎么修改网站网站推广找客户
  • 网站的制作建站人增加网站流量
  • 向国旗致敬做时代新人网站广州网站建设公司排名
  • 阿里云域名怎么做网站对网站进行seo优化
  • 响应式网站建设合同11月将现新冠感染高峰
  • 做网站客户一般会问什么问题百度云网盘资源分享网站
  • 网站设计中超链接怎么做艺术设计
  • 卡盟网站建设wordpress优化代码
  • 做网站需要什么技术员商城型网站开发网站建设
  • discuz做地方门户网站网站大全免费完整版
  • 莆田人做的网站一天赚2000加微信
  • 阿里云网站访问不了怎么办做网站二维码
  • 手机商城网站建设可采用的基本方式有
  • 网站备案管理做广告公司网站建设价格
  • 绵阳专业网站建设公司上海外贸公司排名榜
  • 如何做英文系统下载网站快速排名工具免费
  • 苏州建网站必去苏州聚尚网络网页视频提取在线工具
  • 网站建设服务市场分析百度集团
  • 网站怎么企业备案信息做网站业务员如何跟客户沟通
  • 如何网站推广知名的集团门户网站建设费用
  • 网站入口设计规范专门做喷涂设备的网站
  • 最简单网站开发软件有哪些企业管理培训课程培训机构
  • 桂城网站制作公司wordpress 导航网站
  • 一个公司做网站需要注意什么条件网站备案 登陆
  • 百度网站介绍显示图片装修公司一般多少钱一平方
  • 网站销售如何做业绩我找伟宏篷布我做的事ko家的网站
  • 建立网站有哪些步骤?jsp网站开发详细教程
  • 网站怎么做直播功能旅游做攻略用什么网站