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

企业网站建设问卷网站注册域名 免费

企业网站建设问卷,网站注册域名 免费,app个人主页设计,中天建设集团有限公司招聘文章目录SpringBoot依赖管理特性依赖管理开发导入starter场景启动器SpringBoot自动配置特性自动配好Tomcat自动配好SpringMVC默认的包结构各种配置拥有默认值按需加载所有自动配置项SpringBoot注解底层注解ConfigurationImport导入组件Conditional条件装配ImportResource导入Sp… 文章目录SpringBoot依赖管理特性依赖管理开发导入starter场景启动器SpringBoot自动配置特性自动配好Tomcat自动配好SpringMVC默认的包结构各种配置拥有默认值按需加载所有自动配置项SpringBoot注解底层注解ConfigurationImport导入组件Conditional条件装配ImportResource导入Spring配置文件ConfigurationProperties配置绑定自动配置SpringBootApplication的源码SpringBootConfigurationComponentScanEnableAutoConfiguration自动包规则原理AutoConfigurationPackage初始加载自动配置类Import(AutoConfigurationImportSelector.class)Import(AutoConfigurationImportSelector.class)按需配置的例子自动配置流程SpringBoot依赖管理特性 依赖管理 我们在HelloWorld中导入的父项目依赖 parentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.3.4.RELEASE/version /parentspring-boot-starter-parent的父项目中的一个依赖如下 parentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-dependencies/artifactIdversion2.3.4.RELEASE/version /parentspring-boot-dependencies几乎声明了所有开发中常用的依赖的版本号自动版本仲裁机制 导入spring-boot-starter-parent父项目是用来做依赖管理的这样我们导入依赖无需关注版本号自动版本仲裁 引入依赖默认都可以不写版本引入非版本仲裁的jar要写版本号。 dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId /dependency可以修改默认版本号 查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。 在当前项目里面重写配置如下面的代码。 propertiesmysql.version5.1.43/mysql.version /properties开发导入starter场景启动器 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId /dependency见到很多 spring-boot-starter-* *就某种场景 web就是我们开发web应用的场景 只要引入starter这个场景的所有常规需要的依赖我们都自动引入更多SpringBoot所有支持的场景当我们觉得不够用还可以自己创建starter启动器 见到的 *-spring-boot-starter 第三方为我们提供的简化开发的场景启动器。 所有场景启动器最底层的依赖 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter/artifactIdversion2.3.4.RELEASE/versionscopecompile/scope /dependencySpringBoot自动配置特性 这里我们以我们导入的web场景下的starter为例子 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId /dependency自动配好Tomcat 引入Tomcat依赖。配置Tomcat dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-tomcat/artifactIdversion2.3.4.RELEASE/versionscopecompile/scope /dependency自动配好SpringMVC 引入SpringMVC全套组件自动配好SpringMVC常用组件功能 dependencygroupIdorg.springframework/groupIdartifactIdspring-webmvc/artifactIdversion5.2.9.RELEASE/versionscopecompile/scope /dependency自动配好Web常见功能如字符编码问题 SpringBoot帮我们配置好了所有web开发的常见场景 public static void main(String[] args) {//1、返回我们IOC容器ConfigurableApplicationContext run SpringApplication.run(MainApplication.class, args);//2、查看容器里面的组件String[] names run.getBeanDefinitionNames();for (String name : names) {System.out.println(name);} } //部分输出结果 tomcatWebServerFactoryCustomizer org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration characterEncodingFilter--------设置字符编码的过滤器 localeCharsetMappingsCustomizer org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration multipartConfigElement multipartResolver spring.servlet.multipart-org.springframework.boot.autoconfigure.web.servlet.MultipartProperties org.springframework.aop.config.internalAutoProxyCreator我们之前想解决中文乱码问题需要我们自己配置字符编码过滤器有了SpringBoot我们都不需要设置 默认的包结构 主程序(也就是被我们SpringBootApplication修饰的类)所在包及其下面的所有子包里面的组件都会被默认扫描进来 自动代替我们之前Ioc容器xml文件中配置的自动扫描组件 无需以前的包扫描配置想要改变扫描路径 SpringBootApplication(scanBasePackages“com.lun”)为什么不能直接通过ComponentScan 指定扫描路径 因为我们的SpringBootApplication()是一个合成注解 SpringBootApplication(scanBasePackagescom.lsc) 等同于 SpringBootConfiguration EnableAutoConfiguration ComponentScan(com.lun)各种配置拥有默认值 默认配置最终都是映射到某个类上如MultipartProperties #设置服务器的端口号 server.port8080 #设置文件上传的最大大小 spring.servlet.multipart.max-file-size10MB配置文件的值最终会绑定每个类上因为这个类会在容器中创建对象 按需加载所有自动配置项 我们的SpringBoot非常多的starter引入了哪些场景这个场景的自动配置才会开启SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面 但是不是所有的配置都会生效至于原理需要了解相关注解的原理 我们的spring-boot-starter-web中存在spring-boot-starter依赖 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter/artifactIdversion2.3.4.RELEASE/versionscopecompile/scope /dependency我们的spring-boot-starter中存在spring-boot-autoconfigure dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-autoconfigure/artifactIdversion2.3.4.RELEASE/versionscopecompile/scope /dependencySpringBoot注解底层注解 Configuration 表示当前这个类是配置类类似我们xml配置文件的作用 /*** author lsc* #Description MyConfig* #Date: 2023/2/11 11:11*/ Configuration(proxyBeanMethods true) public class MyConfig {Bean//给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值就是组件在容器中的实例public User user01(){User user new User(1, 刘颂成);user.setCat(tomcat());return user ;}Bean(tomcat)//如果不想以方法名为名称可以自己自定义public Cat tomcat(){return new Cat(tomcat);} }配置类里面使用Bean标注在方法上给容器注册组件默认也是单实例的配置类本身也是组件proxyBeanMethods代理bean的方法 Full(proxyBeanMethods true)保证每个Bean方法被调用多少次返回的组件都是单实例的默认Lite(proxyBeanMethods false)每个Bean方法被调用多少次返回的组件都是新创建的测试 SpringBootApplication(scanBasePackages com.lsc) public class MainApplication {public static void main(String[] args) {//1、返回我们IOC容器ConfigurableApplicationContext run SpringApplication.run(MainApplication.class, args);//2、查看容器里面的组件String[] names run.getBeanDefinitionNames();for (String name : names) {System.out.println(name);}//3、从容器中获取组件Pet tom01 run.getBean(tom, Pet.class);Pet tom02 run.getBean(tom, Pet.class);System.out.println(组件(tom01 tom02));//4、com.atguigu.boot.config.MyConfig$$EnhancerBySpringCGLIB$$51f1e1ca1654a892MyConfig bean run.getBean(MyConfig.class);System.out.println(bean);//如果Configuration(proxyBeanMethods true) 代理对象调用方法。SpringBoot总会检查这个组件是否在容器中有。//保持组件单实例User user bean.user01();User user1 bean.user01();System.out.println(user user1);//trueUser user01 run.getBean(user01, User.class);Cat tom run.getBean(tomcat, Cat.class);System.out.println(用户的宠物(user01.getPet() tom));//true} }最佳实战 配置 类组件之间无依赖关系用Lite模式加速容器启动过程减少判断配置 类组件之间有依赖关系方法会被调用得到之前单实例组件用Full模式默认 Import导入组件 Bean、Component、Controller、Service、Repository它们是Spring的基本标签在Spring Boot中并未改变它们原来的功能。 ComponentScan表示扫描组件来指定要扫描的包 Import({User.class, DBHelper.class}) Configuration(proxyBeanMethods false) public class MyConfig {Bean//给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值就是组件在容器中的实例public User user01(){User user new User(1, 刘颂成);user.setCat(tomcat());return user ;}Bean(tomcat)//如果不想以方法名为名称可以自己自定义public Cat tomcat(){return new Cat(tomcat);} }Import自动导入对应的类利用其无参构造方法创建一个Bean给容器进行管理Import({User.class, DBHelper.class})给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名 测试类 SpringBootApplication(scanBasePackages com.lsc) public class MainApplication {public static void main(String[] args) {//返回的是IOC容器ConfigurableApplicationContext run SpringApplication.run(MainApplication.class,args);String[] beanNamesForType run.getBeanNamesForType(User.class);for (String s : beanNamesForType) {System.out.println(s);}DBHelper bean1 run.getBean(DBHelper.class);System.out.println(bean1);} } // com.lsc.springboot.pojo.User user01 ch.qos.logback.core.db.DBHelper73d6d0cConditional条件装配 条件装配满足Conditional指定的条件则进行组件注入 ConditionalOnBean当容器存在某个Bean,才会进行注入以下的对象ConditionalOnMissingBean当容器不存在某个Bean才会进行注入以下的对象 用ConditionalOnBean举例说明 /*** author lsc* #Description MyConfig* #Date: 2023/2/11 11:11*/ Configuration(proxyBeanMethods true) ConditionalOnBean(name tomcat)//只有当有tom名字的Bean时MyConfig类的Bean才能生效。 public class MyConfig {Bean//给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值就是组件在容器中的实例public User user01(){User user new User(1, 刘颂成);user.setCat(tomcat());return user ;} // Bean(tomcat)//如果不想以方法名为名称可以自己自定义public Cat tomcat(){return new Cat(tomcat);} } 现在我们的容器中是不存在user01这个bean对应的条件装配注解可以放在方法上也可以放在类上 SpringBootApplication(scanBasePackages com.lsc) public class MainApplication {public static void main(String[] args) {//返回的是IOC容器ConfigurableApplicationContext run SpringApplication.run(MainApplication.class,args);//查看我们IOC容器中Bean的组件名称boolean tomcat run.containsBean(tomcat);System.out.println(名称为tomcat的存在tomcat);boolean user01 run.containsBean(user01);System.out.println(名称为user01的bean存在user01);} } //输出结果 名称为tomcat的存在false 名称为user01的bean存在false我们看到我们的tomcat这个bean不存在所以连user01这个bean也没有注入容器 ImportResource导入Spring配置文件 比如公司使用bean.xml文件生成配置bean然而你为了省事想继续复用bean.xmlImportResource登场。 ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdbean classcom.lsc.springboot.pojo.User idhahaproperty nameid value2/propertyproperty namename valuesss/property/beanbean classcom.lsc.springboot.pojo.Cat idheheproperty namename value小猫/property/bean /beans测试 public static void main(String[] args) {//1、返回我们IOC容器ConfigurableApplicationContext run SpringApplication.run(MainApplication.class, args);boolean haha run.containsBean(haha);boolean hehe run.containsBean(hehe);System.out.println(hahahaha);//trueSystem.out.println(hehehehe);//true }ConfigurationProperties配置绑定 如何使用Java读取到properties文件中的内容并且把它封装到JavaBean中以供随时使用 传统方式 public class getProperties {public static void main(String[] args) throws FileNotFoundException, IOException {Properties pps new Properties();pps.load(new FileInputStream(a.properties));Enumeration enum1 pps.propertyNames();//得到配置文件的名字while(enum1.hasMoreElements()) {String strKey (String) enum1.nextElement();String strValue pps.getProperty(strKey);System.out.println(strKey strValue);//封装到JavaBean。}}}我们需要自己读取文件的内容然后进行判断存入 Spring Boot一种配置配置绑定 ConfigurationProperties Component 假设有配置文件application.properties mycar.brandBYD mycar.price10000Component ConfigurationProperties(prefix mycar) public class Car {private String brand;private Integer price;....... }因为只有被spring管理才能拥有SpringBoot强大的功能 RestController public class HelloWorldController {AutowiredCar car;RequestMapping(/car)public Car car(){return car;}SpringBoot另一种配置配置绑定 EnableConfigurationProperties ConfigurationProperties 开启Car配置绑定功能把这个Car这个组件自动注册到容器中 ConfigurationProperties(prefix mycar) public class Car { ... }EnableConfigurationProperties(Car.class) public class MyConfig { ... }自动配置 被SpringBootApplication表示为主类 SpringBootApplication(scanBasePackages com.lsc) public class MainApplication {public static void main(String[] args) {SpringApplication.run(MainApplication.class,args);} SpringBootApplication的源码 Target(ElementType.TYPE) Retention(RetentionPolicy.RUNTIME) Documented Inherited SpringBootConfiguration EnableAutoConfiguration ComponentScan(excludeFilters {Filter(type FilterType.CUSTOM,classes {TypeExcludeFilter.class} ), Filter(type FilterType.CUSTOM,classes {AutoConfigurationExcludeFilter.class} )} ) public interface SpringBootApplication {... }重点分析SpringBootConfigurationEnableAutoConfigurationComponentScan SpringBootConfiguration Target(ElementType.TYPE) Retention(RetentionPolicy.RUNTIME) Documented Configuration public interface SpringBootConfiguration {AliasFor(annotation Configuration.class)boolean proxyBeanMethods() default true; }Configuration代表当前是一个配置类。 ComponentScan 指定扫描哪些Spring注解。 EnableAutoConfiguration 这个注解需要重点分析 Target(ElementType.TYPE) Retention(RetentionPolicy.RUNTIME) Documented Inherited AutoConfigurationPackage Import(AutoConfigurationImportSelector.class) public interface EnableAutoConfiguration {String ENABLED_OVERRIDE_PROPERTY spring.boot.enableautoconfiguration;Class?[] exclude() default {};String[] excludeName() default {}; }重点分析AutoConfigurationPackageImport(AutoConfigurationImportSelector.class)。 自动包规则原理 AutoConfigurationPackage 标签名直译为自动配置包指定了默认的包规则。 Target({ElementType.TYPE}) Retention(RetentionPolicy.RUNTIME) Documented Inherited Import({Registrar.class}) public interface AutoConfigurationPackage {String[] basePackages() default {};Class?[] basePackageClasses() default {}; }Import({Registrar.class})利用Registrar给容器中导入一系列组件 static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {Registrar() {}public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]));}public SetObject determineImports(AnnotationMetadata metadata) {return Collections.singleton(new AutoConfigurationPackages.PackageImports(metadata));}}Registrar.class 作用将主启动类的所在包及包下面所有子包里面的所有组件扫描到Spring容器 初始加载自动配置类 Import(AutoConfigurationImportSelector.class) AutoConfigurationImportSelector 自动配置导入选择器那么它会导入哪些组件的选择器呢我们点击去这个类看源码 1、这个类中有一个这样的方法 protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {if (!this.isEnabled(annotationMetadata)) {return EMPTY_ENTRY;} else {AnnotationAttributes attributes this.getAttributes(annotationMetadata);ListString configurations this.getCandidateConfigurations(annotationMetadata, attributes);configurations this.removeDuplicates(configurations);SetString exclusions this.getExclusions(annotationMetadata, attributes);this.checkExcludedClasses(configurations, exclusions);configurations.removeAll(exclusions);configurations this.getConfigurationClassFilter().filter(configurations);this.fireAutoConfigurationImportEvents(configurations, exclusions);return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);}} 2getAutoConfigurationEntry中调用了getCandidateConfigurations protected ListString getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {ListString configurations SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());Assert.notEmpty(configurations, No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file correct.);return configurations;}3 这个方法又调用了SpringFactoriesLoader 类的静态方法我们进入SpringFactoriesLoader类loadFactoryNames() 方法 public static ListString loadFactoryNames(Class? factoryType, Nullable ClassLoader classLoader) {String factoryTypeName factoryType.getName();return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());}private static MapString, ListString loadSpringFactories(Nullable ClassLoader classLoader) {MultiValueMapString, String result (MultiValueMap)cache.get(classLoader);if (result ! null) {return result;} else {try {EnumerationURL urls classLoader ! null ? classLoader.getResources(META-INF/spring.factories) : ClassLoader.getSystemResources(META-INF/spring.factories);LinkedMultiValueMap result new LinkedMultiValueMap();while(urls.hasMoreElements()) {URL url (URL)urls.nextElement();UrlResource resource new UrlResource(url);Properties properties PropertiesLoaderUtils.loadProperties(resource);Iterator var6 properties.entrySet().iterator();while(var6.hasNext()) {Entry?, ? entry (Entry)var6.next();String factoryTypeName ((String)entry.getKey()).trim();String[] var9 StringUtils.commaDelimitedListToStringArray((String)entry.getValue());int var10 var9.length;for(int var11 0; var11 var10; var11) {String factoryImplementationName var9[var11];result.add(factoryTypeName, factoryImplementationName.trim());}}}cache.put(classLoader, result);return result;} catch (IOException var13) {throw new IllegalArgumentException(Unable to load factories from location [META-INF/spring.factories], var13);}}}发现一个多次出现的文件spring.factories全局搜索它 spring.factories 文件里面写死了spring-boot一启动就要给容器中加载的所有配置类 我们根据源头打开spring.factories 看到了很多自动配置的文件这就是自动配置根源所在 这个spring.factories文件也是一组一组的keyvalue的形式其中一个key是EnableAutoConfiguration类的全类名而它的value是一个xxxxAutoConfiguration的类名的列表这些类名以逗号分隔如下图所示 Import(AutoConfigurationImportSelector.class) AutoConfigurationImportSelector类中利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件 getAutoConfigurationEntry方法中通过调用 ListString configurations this.getCandidateConfigurations(annotationMetadata, attributes);获取到所有需要导入到容器中的配置类 SpringFactoriesLoader利用工厂加载 MapString, ListString loadSpringFactories(Nullable ClassLoader classLoader);得到所有的组件 从META-INF/spring.factories位置来加载一个文件。 默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件 spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories # 文件里面写死了spring-boot一启动就要给容器中加载的所有配置类 # spring-boot-autoconfigure-2.3.4.RELEASE.jar/META-INF/spring.factories # Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\ ...虽然我们127个场景的所有自动配置启动的时候默认全部加载但是xxxxAutoConfiguration按照条件装配规则Conditional最终会按需配置。 springboot所有的自动配置都是在启动的时候扫描并加载扫描了spring.properties配置文件所有的自动配置类都在这里面但是不定生效因为要判断条件是否成立只要导入了对应的start就有对应的启动器有了启动器我们自动装配就会生效然后就配置成功 按需配置的例子 AopAutoConfiguration类 Configuration(proxyBeanMethods false ) ConditionalOnProperty(prefix spring.aop,name auto,havingValue true,matchIfMissing true ) public class AopAutoConfiguration {public AopAutoConfiguration() {}... }prefix为配置文件中的前缀,name为配置的名字havingValue是与配置的值对比值,当两个值相同返回true,配置类生效.matchIfMissing表示如果没有这么配置的默认值 自动配置流程 以DispatcherServletAutoConfiguration的内部类DispatcherServletConfiguration为例子: Bean ConditionalOnBean(MultipartResolver.class) //容器中有这个类型组件 ConditionalOnMissingBean(name DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) //容器中没有这个名字 multipartResolver 的组件 public MultipartResolver multipartResolver(MultipartResolver resolver) {// Detect if the user has created a MultipartResolver but named it incorrectlyreturn resolver;//给容器中加入了文件上传解析器 }给Bean标注的方法传入了对象参数这个参数的值就会从容器中找。方法名为multipartResolver ,SpringMVC multipartResolver防止有些用户配置的文件上传解析器不符合规范 SpringBoot默认会在底层配好所有的组件但是如果用户自己配置了以用户的优先。 总结 SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration每个自动配置类按照条件进行生效默认都会绑定配置文件指定的值。xxxxProperties里面读取xxxProperties和配置文件进行了绑定生效的配置类就会给容器中装配很多组件只要容器中有这些组件相当于这些功能就有了定制化配置 用户直接自己Bean替换底层的组件用户去看这个组件是获取的配置文件什么值就去修改。 xxxxxAutoConfiguration — 组件 — xxxxProperties里面拿值 ---- application.properties 面试官问你你可以这样说,springboot是通过main方法下的SpringApplication.run方法启动的,启动的时候他会调用refshContext方法,先刷新容器,然后根据解析注解或者解析配置文件的形式注册bean,还会它是通过启动类的SpringBootApplication注解进行开始解析的,他会根据EnableAutoConfiguration开启自动化配置,里面有个核心方法ImportSelect选择性的导入,根据loadFactoryNames根据classpath路径以MATA-INF/spring.factorces下面以什么什么EnableAutoConfiguration开头的key去加载里面所有对应的自动化配置,他并不是把这一百二十多个自动化配置全部导入,在他每个自动化配置里面都有条件判断注解,先判断是否引入相互的jar包,再判断容器是否有bean再进行注入到bean容器
http://www.hkea.cn/news/14307469/

相关文章:

  • 网站转发我要建设一个网站
  • asp网站开发环境搭建扬州建设机械网站
  • 做新零售这些注册网站和找货源中信建设有限责任公司历任董事长
  • 做百度网站电话号码彭州建设局网站
  • 网站上传百度多久收录撰写网站专题活动策划方案
  • 网站负责人核验照片如何建设小说网站并且盈利
  • 简速做网站工作室市场监督管理局不处理问题怎么办
  • 专业seo整站优化大丰建站
  • 有什么网站可以做微信appapp和网站开发
  • 正规的徐州网站开发画册设计公司宣传册
  • 网站怎么推广比较好手机app定制多少钱
  • 网络营销型网站策划关键词网站查询
  • jsq项目做网站网站模版一样 内容不同侵权吗
  • 网站自动跳转学会网站 建设
  • 东莞网站制作百年网站设计英文
  • 钓鱼网站制作教程天津网站搜索优化
  • 广州番禺专业做网站上海百度竞价托管
  • 各大网站vip接口建设漳州做网站开发
  • 闵行区网站开发技术支持 东莞网站建设舞蹈培训
  • 自动生成图片的网站如何选择大连网站建设
  • 零壹网站建设网站建设提升界面流畅程度
  • wordpress+分辨+模版平台网站怎么优化
  • 南京做网站的额浙江政务服务网登录入口
  • 漳州建网站软件开发流程图名称
  • 做学历的网站wordpress自定义类型的分类名称
  • 大型网站 cms网站开发后端用什么技术
  • 企业网站鉴赏免费做网站建设
  • 深圳招聘网站开发安宁网站建设 熊掌号
  • 网站备案图标爱站网seo查询
  • 网站 简约php商城网站的要求与数据