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

在网站制作意见征集是怎么做的王也天葛优

在网站制作意见征集是怎么做的,王也天葛优,专业的网站开发联系方式,免费一键网站这篇主要讲解一下如何基于SpringBoot和MyBatis技术实现一个简易的博客系统(前端页面主要是利用CSS,HTML进行布局书写),前端的静态页面代码可以直接复制粘贴,后端的接口以及前端发送的Ajax请求需要自己书写. 博客系统需要完成的接口: 注册登录博客列表页展示博客详情页展示发布博…这篇主要讲解一下如何基于SpringBoot和MyBatis技术实现一个简易的博客系统(前端页面主要是利用CSS,HTML进行布局书写),前端的静态页面代码可以直接复制粘贴,后端的接口以及前端发送的Ajax请求需要自己书写. 博客系统需要完成的接口: 注册登录博客列表页展示博客详情页展示发布博客修改博客.......  完整版代码详见Gitee:blogsystem · 徐明园/SSM配置信息 - 码云 - 开源中国 (gitee.com) 项目亮点: 密码实现加盐处理,确保安全性;Session升级,由原来的内存存储改为通过Redis存储,不会丢失,并且支持分布式部署;功能升级,对于博客列表的展示添加了分页功能;登录验证升级,添加了拦截器的功能对用于的登录进行校验;...... 一, 项目的搭建 1,导入依赖坐标(创建SpringBoot项目) 在书写任何一个项目的同时,需要先将项目的基础给搭建好,搭建项目需要提前考虑好项目的一些功能需要哪些依赖,从而进行添加,如何创建SpringBoot项目可以看我的另一篇博客:SpringBoot项目的创建和使用_蜡笔小心眼子的博客-CSDN博客 博客系统需要添加的依赖如下: ?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersionparentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.7.16/versionrelativePath/ !-- lookup parent from repository --/parentgroupIdcom.example/groupIdartifactIdblogsystem/artifactIdversion0.0.1-SNAPSHOT/versionnameblogsystem/namedescriptionblogsystem/descriptionpropertiesjava.version1.8/java.version/propertiesdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactIdversion2.3.1/version/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-devtools/artifactIdscoperuntime/scopeoptionaltrue/optional/dependencydependencygroupIdcom.mysql/groupIdartifactIdmysql-connector-j/artifactIdscoperuntime/scope/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependencydependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter-test/artifactIdversion2.3.1/versionscopetest/scope/dependency/dependenciesbuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactIdconfigurationexcludesexcludegroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId/exclude/excludes/configuration/plugin/plugins/build/project2,书写配置文件 需要使用MyBatis技术的项目需要配置你的数据库相关的信息以及Mapper的xml文件存储的位置,同时也可以在配置文件中定义一下日志的打印级别,从而方便查看数据库操作的完整信息: #配置数据库连接信息 spring:datasource:url: 你自己的数据库username: rootpassword: 数据库对应的密码driver-class-name: com.mysql.cj.jdbc.Driver#配置Mapper的xml文件存储信息 mybatis: # xml的存储位置mapper-locations: classpath:mapper/*Mapper.xmlconfiguration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl#配置日志打印级别 logging:level:com:example:demo: debug 二, 将前端页面部署到项目中(resource文件下的static目录中) 对于后端程序员来说可以不用特别注重前端样式的书写,但是需要看得懂前端的代码以及和后端交互的请求即可(学有余力的情况下可以适当学习从而优化自己项目中的前端页面),这里的静态页面信息可以直接在我的码云中进行下载:SSM配置信息: 存放SSM项目中的一些配置信息 (gitee.com)博客系统(静态页面).zip · 徐明园/SSM配置信息 - 码云 - 开源中国 (gitee.com)SSM配置信息: 存放SSM项目中的一些配置信息 (gitee.com) 将下载好的前端页面全选之后直接复制到static目录下即可: 三, 初始化数据库 在配置文件中我们已经配置了数据库的连接信息,但是此时在数据库中还没有初始化一些数据,所以我们需要初始化数据,方便写项目的时候进行测试,初始化数据库的SQL代码也可以在我们的码云中进行下载:博客系统初始化数据库-ssm.sql · 徐明园/SSM配置信息 - 码云 - 开源中国 (gitee.com) 查看数据库中的表即相应表结构: 四, 对项目的整体架构进行分层 一个企业级的SM项目都需要对其进行合理的分层,每一层处理每一层的业务逻辑,我在项目中的分层如下: common:一些工具类config:配置信息类controller:处理前端请求的类entity:实体类(也可以写成model)mapper:用来和Mapper.xml文件交互的接口类service:处于controller和mapper之间的类 五, 书写前后端交互的功能 从这里开始就是项目的核心了,这里开始可以对前后端的接口和相应功能进行书写了! 1, 统一返回对象的封装 为了给前端返回统一的对象,后端需要定义一个类对返回的数据进行封装,该类包含code,msg和data三个属性,该类定义在common包下: package com.example.blogsystem.common;import lombok.Data;import java.io.Serializable;/*** 统一返回对象* 返回成功的话 code 设置成 200* 反悔失败的话 code 设置成本身的 code*/Data public class AjaxResult implements Serializable {private int code;private String msg;private Object data;/*** 返回成功** param data* return*/public static AjaxResult success(Object data) {AjaxResult ajaxResult new AjaxResult();ajaxResult.setCode(200);ajaxResult.setMsg();ajaxResult.setData(data);return ajaxResult;}public static AjaxResult success(Object data, String msg) {AjaxResult ajaxResult new AjaxResult();ajaxResult.setCode(200);ajaxResult.setMsg(msg);ajaxResult.setData(data);return ajaxResult;}/*** 返回失败** param code* param msg* return*/public static AjaxResult fail(Integer code, String msg) {AjaxResult ajaxResult new AjaxResult();ajaxResult.setCode(code);ajaxResult.setMsg(msg);ajaxResult.setData();return ajaxResult;}public static AjaxResult fail(Integer code, String msg, String data) {AjaxResult ajaxResult new AjaxResult();ajaxResult.setCode(code);ajaxResult.setMsg(msg);ajaxResult.setData(data);return ajaxResult;} } 2, 注册功能 注册功能就是用户给后端发送一次请求之后,后端就会在数据中新增一条用户记录! 前端 !DOCTYPE html html langenheadmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0title注册页面/titlelink relstylesheet hrefcss/conmmon.csslink relstylesheet hrefcss/login.css!-- 引入jquery的js文件 --script srcjs/jquery.min.js/script /headbody !-- 导航栏 -- div classnavimg srcimg/logo2.jpg altspan classtitle我的博客系统/span!-- 用来占据中间位置 --span classspacer/spana hrefblog_list.html主页/aa hreflogin.html登陆/a!-- a href#注销/a -- /div !-- 版心 -- div classlogin-container!-- 中间的注册框 --div classlogin-dialogh3注册/h3div classrowspan用户名/spaninput typetext idusername/divdiv classrowspan密码/spaninput typepassword idpassword/divdiv classrowspan确认密码/spaninput typepassword idpassword2/divdiv classrowbutton idsubmit onclickmysub()提交/button/div/div /div!-- 最好把js的代码写在这下面 因为js代码的代码是按照从上往下执行的 如果写在上面的话 可能js的代码获取的一些标签在下面还没有生效 会获取失败 -- scriptfunction mysub(){// 1.非空判断// 1.1 先得到输入的组件var username jQuery(#username);var password jQuery(#password);var password2 jQuery(#password2);// 1.2 判断输入组件是否为空if(username.val().trim()){alert(请先输入用户名);username.focus(); // 聚焦光标return false;}if(password.val().trim()){alert(请先输入密码);password.focus();return false;}if(password2.val().trim()){alert(请先输入确认密码);password2.focus();return false;}if(password.val()!password2.val()){alert(两次密码输入不一致性请先检查);password.focus();return false;}// 2.先把提交按钮设置成不可用禁用jQuery(#submit).attr(disabled,disabled);// 3.将当前页面的数据提交给后端jQuery.ajax({url:/user/reg,type:POST,data:{username:username.val().trim(),password:password.val().trim()},success:function(res){// 4.根据后端返回的结果成功or失败再处理后续流程if(res.code200 res.data1){alert(注册成功);location.href login.html; // 调整到登录页面}else{alert(抱歉操作失败res.msg);// 取消禁用jQuery(#submit).removeAttr(disabled);}}});} /script /body/html 前端给后端发送请求都是通过Ajax来实现的,所以对于任何需要发送Ajax请求的页面都需要导入js的依赖(后面就不再赘述) 后端(这里的后端只展示controller包中的代码) RequestMapping(/reg)public AjaxResult reg(UserInfo userInfo) {//1.对前端传递来的参数进行校验if (userInfo null || !StringUtils.hasLength(userInfo.getUsername()) || !StringUtils.hasLength(userInfo.getPassword())) {return AjaxResult.fail(-1, 参数有误!);}//2.与数据库进行交互实现注册的功能//将密码进行加盐加密userInfo.setPassword(PasswordTools.encrypt(userInfo.getPassword()));int result userService.reg(userInfo);//3.对于查询结果给前端进行反馈return AjaxResult.success(result);} 3, 登录功能  登录就是前端给后端传递用户名和密码,后端从数据库中查询是否存在这样的用户! 前端 !DOCTYPE html html langenheadmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0title登陆页面/titlelink relstylesheet hrefcss/conmmon.csslink relstylesheet hrefcss/login.cssscript srcjs/jquery.min.js/script /headbody !-- 导航栏 -- div classnavimg srcimg/logo2.jpg altspan classtitle我的博客系统/span!-- 用来占据中间位置 --span classspacer/spana hrefblog_list.html主页/aa hrefreg.html注册/a /div !-- 版心 -- div classlogin-container!-- 中间的登陆框 --div classlogin-dialogh3登陆/h3div classrowspan用户名/spaninput typetext idusername/divdiv classrowspan密码/spaninput typepassword idpassword/divdiv classrowbutton idsubmit onclickmysub()提交/button/div/div /divscriptfunction mysub() {//1.对提交的数据进行判空操作var username jQuery(#username);var password jQuery(#password);if(username.val().trim() ) {alert(请输入用户名!);username.focus();return false;}if(password.val().trim() ) {alert(请输入密码!);password.focus();return false;}//2.发送数据给服务器jQuery.ajax({url:user/login,type:post,data:{username:username.val().trim(),password:password.val().trim()},success:function(res) {//这里针对服务器的响应数据 规定返回1是成功 返回0是失败if(res.code 200 res.data 1) {alert(恭喜:登录成功!);location.href myblog_list.html;} else {alert(抱歉:登录失败! res.msg);return false;}}});} /script /body/html 登录功能的前端代码和注册功能前端代码几乎一模一样 后端 RequestMapping(/login)public AjaxResult login(String username, String password, HttpServletRequest request) {//1.对前端传递来的参数进行校验if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password)) {return AjaxResult.fail(-1, 参数有误!);}//2.根据用户名去数据库中进行查询UserInfo userInfo userService.login(username);if (userInfo null || userInfo.getId() 0) {return AjaxResult.fail(-2, 用户名或者密码错误!);}//对数据库中查找的密码进行解密 // if (!PasswordTools.check(password,userInfo.getPassword())) { // return AjaxResult.fail(-2, 用户名或者密码错误!); // }if (!userInfo.getPassword().equals(password)) {return AjaxResult.fail(-2, 用户名或者密码错误!);}//当前表示登陆成功 需要存储sessionHttpSession session request.getSession();session.setAttribute(ApplicationVariable.USERINFO_SESSION_KEY, userInfo);return AjaxResult.success(1);} 登录的时候需要存储用户的session(会话)信息,因为session的Key需要在多个地方使用,我们将该属性抽象出来放在了common这个公共包下了: package com.example.blogsystem.common;public class ApplicationVariable {public static final String USERINFO_SESSION_KEY USERINFO_SESSION_KEY; }对于取出session()会话)中的的用户信息也可以将其封装公共的类,放在common包下: package com.example.blogsystem.common;import com.example.blogsystem.entity.UserInfo;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession;public class UserSessionTools {public static UserInfo getLoginUser(HttpServletRequest request) {HttpSession session request.getSession(false);if (session ! null session.getAttribute(ApplicationVariable.USERINFO_SESSION_KEY) ! null) {return (UserInfo) session.getAttribute(ApplicationVariable.USERINFO_SESSION_KEY);}return null;} }4, 实现拦截器 对于一些博客信息的操作需要用户进行登录,所以可以通过拦截器判断用户具有相应的权限,只有通过拦截器的用户才可以操作,可以将拦截的配置信息放在config包下. 实现HandlerInterceptor接口: package com.example.blogsystem.config;import com.example.blogsystem.common.ApplicationVariable; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession;Configuration public class LoginInterceptor implements HandlerInterceptor {Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {HttpSession session request.getSession(false);if (session ! null session.getAttribute(ApplicationVariable.USERINFO_SESSION_KEY) ! null) {return true;}response.sendRedirect(/login.html);//没有通过拦截器的请求需要跳转到登录页面先登录return false;} } 实现WebMvcConfigurer进行配置接口: package com.example.blogsystem.config;import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import javax.annotation.Resource;Configuration public class MyConfig implements WebMvcConfigurer {Resourceprivate LoginInterceptor loginInterceptor;Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor).addPathPatterns(/**) //拦截所有的url.excludePathPatterns(/login.html).excludePathPatterns(/reg.html).excludePathPatterns(/blog_list.html).excludePathPatterns(/blog_content.html).excludePathPatterns(/css/**).excludePathPatterns(/editor.md/**).excludePathPatterns(/img/**).excludePathPatterns(/js/**).excludePathPatterns(/user/reg).excludePathPatterns(/user/login);} }这里需要先放开所有的静态页面,图片以及登录和注册接口. 5, 博客添加功能 博客添加功能就是前端向后端提交博客的一些信息,后端在文章表中插入一条文章记录即可! 前端 !DOCTYPE html html langenheadmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0title文章添加/title!-- 引入自己写的样式 --link relstylesheet hrefcss/conmmon.csslink relstylesheet hrefcss/blog_edit.css!-- 引入 editor.md 的依赖 --link relstylesheet hrefeditor.md/css/editormd.min.css /script srcjs/jquery.min.js/scriptscript srceditor.md/editormd.js/script /headbody!-- 导航栏 --div classnavimg srcimg/logo2.jpg altspan classtitle我的博客系统/span!-- 用来占据中间位置 --span classspacer/spana hrefblog_list.html主页/aa href#注销/a/div!-- 编辑框容器 --div classblog-edit-container!-- 标题编辑区 --div classtitleinput idtitle typetext placeholder在这里写下文章标题button onclickmysub()发布文章/button/div!-- 创建编辑器标签 --div ideditorDivtextarea ideditor-markdown styledisplay:none;/textarea/div/divscriptvar editor;function initEdit(md){// 编辑器设置editor editormd(editorDiv, {// 这里的尺寸必须在这里设置. 设置样式会被 editormd 自动覆盖掉. width: 100%,// 高度 100% 意思是和父元素一样高. 要在父元素的基础上去掉标题编辑区的高度height: calc(100% - 50px),// 编辑器中的初始内容markdown: md,// 指定 editor.md 依赖的插件路径path: editor.md/lib/,saveHTMLToTextarea: true // });}initEdit(# 在这里写下一篇博客); // 初始化编译器的值// 提交function mysub(){//1.对文章标题和内容进行判空操作var title jQuery(#title);var content editor.getValue();if(title.val().trim() ) {alert(请输入文章标题!);title.focus();return false;}if(content ) {alert(请输入正文!)return false;}//2.提交数据给后端jQuery.ajax({url:/art/add,type:post,data:{title:title.val(),content:content},success:function (res) {//假设文章添加成功后端给前端返回的data中的数据是1if(res.code 200 res.data 1) {alert(恭喜:文章添加成功!);if (confirm(是否继续添加文章?)) {//如果继续继续添加文章的话 需要刷新此页面location.href location.href;} else {//不继续添加文章需要跳转到文章列表页location.href myblog_list.html;}} else{alert(抱歉:文章添加失败! res.msg);}}})// alert(editor.getValue()); // 获取值// editor.setValue(#123) // 设置值}/script /body/html 这里的前端页面引入了MarkDown编辑器,所以添加博客的时候相较于其他官方博客系统更加真实,而且该编辑器提供了一些Api让我们进行格式转换的时候更加方便. //相关API alert(editor.getValue()); // 获取值 editor.setValue(#123) // 设置值 后端 RequestMapping(/add)public AjaxResult add(ArticleInfo articleInfo, HttpServletRequest request) {//1.对前端传递来的参数进行判空操作if (articleInfo null || !StringUtils.hasLength(articleInfo.getTitle()) || !StringUtils.hasLength(articleInfo.getContent())) {return AjaxResult.fail(-1, 参数错误!);}//2.获取当前的uid进行校验UserInfo userInfo UserSessionTools.getLoginUser(request);if (userInfo null || userInfo.getId() 0) {return AjaxResult.fail(-1, 参数错误!);}//3.封装uid进行持久化articleInfo.setUid(userInfo.getId());int result articleService.add(articleInfo);//4.给前端进行数据反馈return AjaxResult.success(result);} 这里数据库存储的是MarkDown格式的数据,是为了方便进行修改的时候直接进行修改省去了一次从Html转换成MarkDown格式的操作. 6, 博客编辑功能 博客编辑功能需要实现两个操作: 1.先去查询当前文章的信息进行展示(页面加载的时候进行调用) 2.提交修改操作(触发提交按钮的时候进行调用) 前端 !DOCTYPE html html langenheadmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0title文章修改/title!-- 引入自己写的样式 --link relstylesheet hrefcss/conmmon.csslink relstylesheet hrefcss/blog_edit.css!-- 引入 editor.md 的依赖 --link relstylesheet hrefeditor.md/css/editormd.min.css/script srcjs/jquery.min.js/scriptscript srceditor.md/editormd.js/scriptscript srcjs/urltools.js/scriptscript srcjs/logout.js/script /headbody !-- 导航栏 -- div classnavimg srcimg/logo2.jpg altspan classtitle我的博客系统/span!-- 用来占据中间位置 --span classspacer/spana hrefblog_list.html主页/aa hrefjavascript:logout()注销/a /div !-- 编辑框容器 -- div classblog-edit-container!-- 标题编辑区 --div classtitleinput idtitle typetext placeholder在这里写下文章标题button onclickmysub()发布文章/button/div!-- 创建编辑器标签 --div ideditorDivtextarea ideditor-markdown styledisplay:none;/textarea/div /divscriptvar isSubmit 1;var id 0;var editor;function initEdit(md) {// 编辑器设置editor editormd(editorDiv, {// 这里的尺寸必须在这里设置. 设置样式会被 editormd 自动覆盖掉.width: 100%,// 高度 100% 意思是和父元素一样高. 要在父元素的基础上去掉标题编辑区的高度height: calc(100% - 50px),// 编辑器中的初始内容markdown: md,// 指定 editor.md 依赖的插件路径path: editor.md/lib/,saveHTMLToTextarea: true //});}// initEdit(# 在这里写下一篇博客); // 初始化编译器的值//接口1:先去查询当前文章的信息进行展示 页面加载的时候进行调用function initArt() {//1.通过queryString获取文章idid getParamByKey(id);if (id null || id 0) {isSubmit 0;alert(抱歉:非法参数!);return false;}//2.向后端发送请求 获取对应id的文章并展现在前端页面jQuery.ajax({url: /art/getdetailbyid,type: post,data: {id: id},success: function (res) {if (res.code 200 res.data ! null res.data.id 0) {//文章查询成功jQuery(#title).val(res.data.title);initEdit(res.data.content);} else {//文章获取失败isSubmit 0;alert(抱歉:非法参数! res.msg);}}});}initArt();//接口2:提交修改操作 触发提交按钮的时候进行调用// 提交function mysub() {if (isSubmit 0) {alert(抱歉:非法操作,请刷新页面再试!);return false;}//1.非空判断var title jQuery(#title);var content editor.getValue();if (title.val().trim() ) {alert(请输入文章标题!);title.focus();return false;}if (content ) {alert(请输入正文!)return false;}//2.提交请求给后端jQuery.ajax({url: /art/update,type: post,data: {id: id,title: title.val(),content: content},success: function (res) {//规定修改成功后端返回1if (res.code 200 res.data 1) {alert(恭喜:修改成功!);location.href myblog_list.html;} else {alert(抱歉:非法参数! res.msg);}}});// alert(editor.getValue()); // 获取值// editor.setValue(#123) // 设置值} /script /body/html 后端 /*** 对文章进行修改的时候也需要对拿到文章进行权限验证 拿到的文章的uid必须和登录的用户的id一致* 防止登录的用户对其他人的文章进行篡改*/RequestMapping(/getdetailbyid)public AjaxResult getdetailbyid(Integer id, HttpServletRequest request) {//1.对id进行判空操作if (id null || id 0) {return AjaxResult.fail(-1, 参数错误!);}//2.获取到登录用户的idUserInfo userInfo UserSessionTools.getLoginUser(request);if (userInfo null || userInfo.getId() 0) {return AjaxResult.fail(-1, 参数错误!);}//3.封装id和uid进行持久化操作return AjaxResult.success(articleService.getDetailByIdAndUid(id, userInfo.getId()));}RequestMapping(/update)public AjaxResult update(ArticleInfo articleInfo, HttpServletRequest request) {//1.对前端传递的参数进行判空if (articleInfo null || articleInfo.getId() 0|| !StringUtils.hasLength(articleInfo.getTitle()) || !StringUtils.hasLength(articleInfo.getContent())) {return AjaxResult.fail(-1, 参数错误!);}//2.获取uid进行封装并进行持久化UserInfo userInfo UserSessionTools.getLoginUser(request);if (userInfo null || userInfo.getId() 0) {return AjaxResult.fail(-1, 参数错误!);}articleInfo.setUid(userInfo.getId());articleInfo.setUpdatetime(LocalDateTime.now());//3.给前端返回数据int result articleService.update(articleInfo);return AjaxResult.success(result);} 根据文章id进行查找文章时,必须要进行校验,确保查询到的文章时该登录用户的文章,即文章表中的uid 用户表中的id.
http://www.pierceye.com/news/189289/

相关文章:

  • 域名备案和网站备案有什么不同wap 网站
  • 没备案的网站百度收录博客营销
  • 网站开发新技术wordpress 搜索词调用
  • 凡科手机建站教程wordpress 搜索引擎
  • asp企业网站源码下载免费ppt模板公众号
  • 西斗门的网站建设短网址生成器有哪些
  • 一站式织梦网站模板工信部备案查询网官网
  • 网站导航做外链桂林seo
  • 青岛网站建设q479185700棒软件开发者是指
  • 福永公司网站建设空间网站链接怎么做
  • 百度的企业网站谷歌浏览器下载安卓版
  • 网站建设总体情况网站设计宁波
  • 西宁做网站_君博示范360建筑网会员
  • 做DJ网站违法吗汕头seo网站推广
  • 上海网站建设网站宁波网站模板哪家性价比高
  • 珠海专业做网站制作做网站网站的代理算网站罪吗
  • 建设局网站简介通信建设网站
  • php做网站用什么开发工具大专软件技术工资一般多少
  • 网站建设服务承诺wordpress 博客园
  • seo综合查询站长工具关键词全网营销案例
  • 深圳专业做网站设计政务服务网站建设性建议
  • 做暧免费观看网站哪个网站可以给图片做链接
  • wordpress最好的主题东莞债务优化
  • 全国网站建设大赛网店网站设计
  • 学网站建设需要学多久wordpress火车头插件
  • wordpress 网站实例中国纪检监察报app下载
  • 网站链接dw怎么做营销推广方法
  • 觅知网 大而全的高质量素材站开发手机网站用什么好
  • 建设一个广告联盟的网站医院网站设计与实现
  • 公司网站备案必须是企业信息么网站搭建好有什么内容可以修改