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

个人注册网站一般做什么学做吃的网站

个人注册网站一般做什么,学做吃的网站,客户管理系统网站模板下载,做公司网站需要会什么科目目录 1 Filter1.1 Filter概述1.2 Filter快速入门1.2.1 开发步骤1.2.2 代码演示 1.3 Filter执行流程1.4 Filter拦截路径配置1.5 过滤器链1.5.1 概述1.5.2 代码演示1.5.3 问题 1.6 案例1.6.1 需求1.6.2 分析1.6.3 代码实现1.6.3.1 创建Filter1.6.3.2 编写逻辑代码1.6.3.3 测试并抛… 目录 1 Filter1.1 Filter概述1.2 Filter快速入门1.2.1 开发步骤1.2.2 代码演示 1.3 Filter执行流程1.4 Filter拦截路径配置1.5 过滤器链1.5.1 概述1.5.2 代码演示1.5.3 问题 1.6 案例1.6.1 需求1.6.2 分析1.6.3 代码实现1.6.3.1 创建Filter1.6.3.2 编写逻辑代码1.6.3.3 测试并抛出问题1.6.3.4 问题分析及解决1.6.3.5 过滤器完整代码 2 Listener2.1 概述2.2 分类2.3 代码演示 3 Ajax3.1 概述3.1.1 作用3.1.2 同步和异步 3.2 快速入门3.2.1 服务端实现3.2.2 客户端实现3.2.3 测试 3.3 案例3.3.1 分析3.3.2 后端实现3.3.3 前端实现 4 axios4.1 基本使用4.2 快速入门4.2.1 后端实现4.2.2 前端实现 4.3 请求方法别名 5 JSON5.1 概述5.2 JSON 基础语法5.2.1 定义格式5.2.2 代码演示5.2.3 发送异步请求携带参数 5.3 JSON串和Java对象的相互转换5.3.1 Fastjson 概述5.3.2 Fastjson 使用5.3.3 代码演示 6 案例6.1 需求6.2 查询所有功能6.2.1 环境准备6.2.2 后端实现6.2.3 前端实现 6.3 添加品牌功能6.3.1 后端实现6.3.2 前端实现 1 Filter 1.1 Filter概述 Filter 表示过滤器是 JavaWeb 三大组件(Servlet、Filter、Listener)之一。 过滤器可以把对资源的请求拦截下来从而实现一些特殊的功能。 如下图所示浏览器可以访问服务器上的所有的资源servlet、jsp、html等 而在访问到这些资源之前可以使过滤器拦截来下也就是说在访问资源之前会先经过 Filter如下图 拦截器拦截到后可以做什么功能呢 过滤器一般完成一些通用的操作。 比如每个资源都要写一些代码完成某个功能我们总不能在每个资源中写这样的代码吧而此时我们可以将这些代码写在过滤器中因为请求每一个资源都要经过过滤器。 我们之前做的品牌数据管理的案例中就已经做了登陆的功能而如果我们不登录能不能访问到数据呢我们可以在浏览器直接访问首页 可以看到 查询所有 的超链接 当我点击该按钮居然可以看到品牌的数据 这显然和我们的要求不符。我们希望实现的效果是用户如果登陆过了就跳转到品牌数据展示的页面如果没有登陆就跳转到登陆页面让用户进行登陆要实现这个效果需要在每一个资源中都写上这段逻辑而像这种通用的操作我们就可以放在过滤器中进行实现。这个就是权限控制以后我们还会进行细粒度权限控制。过滤器还可以做 统一编码处理、 敏感字符处理 等等… 1.2 Filter快速入门 1.2.1 开发步骤 进行 Filter 开发分成以下三步实现 定义类实现 Filter接口并重写其所有方法 配置Filter拦截资源的路径在类上定义 WebFilter 注解。而注解的 value 属性值 /* 表示拦截所有的资源 在doFilter方法中输出一句话并放行 上述代码中的 chain.doFilter(request,response); 就是放行也就是让其访问本该访问的资源。 1.2.2 代码演示 创建一个项目项目下有一个 hello.jsp 页面项目结构如下 pom.xml 配置文件内容如下 ?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdorg.example/groupIdartifactIdfilter-demo/artifactIdversion1.0-SNAPSHOT/versionpackagingwar/packagingpropertiesmaven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.target/propertiesdependenciesdependencygroupIdjavax.servlet/groupIdartifactIdjavax.servlet-api/artifactIdversion3.1.0/versionscopeprovided/scope/dependency/dependenciesbuildpluginsplugingroupIdorg.apache.tomcat.maven/groupIdartifactIdtomcat7-maven-plugin/artifactIdversion2.2/versionconfigurationport80/port/configuration/plugin/plugins/build /projecthello.jsp 页面内容如下 % page contentTypetext/html;charsetUTF-8 languagejava % html headtitleTitle/title /head bodyh1hello JSP~/h1 /body /html我们现在在浏览器输入 http://localhost/filter-demo/hello.jsp 访问 hello.jsp 页面这里是可以访问到 hello.jsp 页面内容的。 接下来编写过滤器。过滤器是 Web 三大组件之一所以我们将 filter 创建在 com.itheima.web.filter 包下起名为 FilterDemo WebFilter(/*) public class FilterDemo implements Filter {Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println(FilterDemo...);}Overridepublic void init(FilterConfig filterConfig) throws ServletException {}Overridepublic void destroy() {} }重启启动服务器再次重新访问 hello.jsp 页面这次发现页面没有任何效果但是在 idea 的控制台可以看到如下内容 上述效果说明 FilterDemo 这个过滤器的 doFilter() 方法执行了但是为什么在浏览器上看不到 hello.jsp 页面的内容呢这是因为在 doFilter() 方法中添加放行的方法才能访问到 hello.jsp 页面。那就在 doFilter() 方法中添加放行的代码 //放行chain.doFilter(request,response);再次重启服务器并访问 hello.jsp 页面发现这次就可以在浏览器上看到页面效果。 FilterDemo 过滤器完整代码如下 WebFilter(/*) public class FilterDemo implements Filter {Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println(1.FilterDemo...);//放行chain.doFilter(request,response);}Overridepublic void init(FilterConfig filterConfig) throws ServletException {}Overridepublic void destroy() {} }1.3 Filter执行流程 如上图是使用过滤器的流程我们通过以下问题来研究过滤器的执行流程 放行后访问对应资源资源访问完成后还会回到Filter中吗 从上图就可以看出肯定 会 回到Filter中 如果回到Filter中是重头执行还是执行放行后的逻辑呢 如果是重头执行的话就意味着 放行前逻辑 会被执行两次肯定不会这样设计了所以访问完资源后会回到 放行后逻辑执行该部分代码。 通过上述的说明我们就可以总结Filter的执行流程如下 接下来我们通过代码验证一下在 doFilter() 方法前后都加上输出语句如下 同时在 hello.jsp 页面加上输出语句如下 执行访问该资源打印的顺序是按照我们标记的标号进行打印的话说明我们上边总结出来的流程是没有问题的。启动服务器访问 hello.jsp 页面在控制台打印的内容如下 以后我们可以将对请求进行处理的代码放在放行之前进行处理而如果请求完资源后还要对响应的数据进行处理时可以在放行后进行逻辑处理。 1.4 Filter拦截路径配置 拦截路径表示 Filter 会对请求的哪些资源进行拦截使用 WebFilter 注解进行配置。如WebFilter(拦截路径) 拦截路径有如下四种配置方式 拦截具体的资源/index.jsp只有访问index.jsp时才会被拦截目录拦截/user/*访问/user下的所有资源都会被拦截后缀名拦截*.jsp访问后缀名为jsp的资源都会被拦截拦截所有/*访问所有资源都会被拦截 通过上面拦截路径的学习大家会发现拦截路径的配置方式和 Servlet 的请求资源路径配置方式一样但是表示的含义不同。 1.5 过滤器链 1.5.1 概述 过滤器链是指在一个Web应用可以配置多个过滤器这多个过滤器称为过滤器链。 如下图就是一个过滤器链我们学习过滤器链主要是学习过滤器链执行的流程 上图中的过滤器链执行是按照以下流程执行 执行 Filter1 的放行前逻辑代码执行 Filter1 的放行代码执行 Filter2 的放行前逻辑代码执行 Filter2 的放行代码访问到资源执行 Filter2 的放行后逻辑代码执行 Filter1 的放行后逻辑代码 以上流程串起来就像一条链子故称之为过滤器链。 1.5.2 代码演示 编写第一个过滤器 FilterDemo 配置成拦截所有资源WebFilter(/*) public class FilterDemo implements Filter {Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {//1. 放行前对 request数据进行处理System.out.println(1.FilterDemo...);//放行chain.doFilter(request,response);//2. 放行后对Response 数据进行处理System.out.println(3.FilterDemo...);}Overridepublic void init(FilterConfig filterConfig) throws ServletException {}Overridepublic void destroy() {} }编写第二个过滤器 FilterDemo2 配置炒年糕拦截所有资源WebFilter(/*) public class FilterDemo2 implements Filter {Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {//1. 放行前对 request数据进行处理System.out.println(2.FilterDemo...);//放行chain.doFilter(request,response);//2. 放行后对Response 数据进行处理System.out.println(4.FilterDemo...);}Overridepublic void init(FilterConfig filterConfig) throws ServletException {}Overridepublic void destroy() {} } 修改 hello.jsp 页面中脚本的输出语句% page contentTypetext/html;charsetUTF-8 languagejava % html headtitleTitle/title /head bodyh1hello JSP~/h1%System.out.println(3.hello jsp);% /body /html启动服务器在浏览器输入 http://localhost/filter-demo/hello.jsp 进行测试在控制台打印内容如下 从结果可以看到确实是按照我们之前说的执行流程进行执行的。 1.5.3 问题 上面代码中为什么是先执行 FilterDemo 后执行 FilterDemo2 呢 我们现在使用的是注解配置Filter而这种配置方式的优先级是按照过滤器类名(字符串)的自然排序。 比如有如下两个名称的过滤器 BFilterDemo 和 AFilterDemo 。那一定是 AFilterDemo 过滤器先执行。 1.6 案例 1.6.1 需求 访问服务器资源时需要先进行登录验证如果没有登录则自动跳转到登录页面 1.6.2 分析 我们要实现该功能是在每一个资源里加入登陆状态校验的代码吗显然是不需要的只需要写一个 Filter 在该过滤器中进行登陆状态校验即可。而在该 Filter 中逻辑如下 1.6.3 代码实现 1.6.3.1 创建Filter 在 brand-demo 工程创建 com.itheima.web.filter 包在该下创建名为 LoginFilter 的过滤器 WebFilter(/*) public class LoginFilter implements Filter {Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {}public void init(FilterConfig config) throws ServletException {}public void destroy() {} }1.6.3.2 编写逻辑代码 在 doFilter() 方法中编写登陆状态校验的逻辑代码。 我们首先需要从 session 对象中获取用户信息但是 ServletRequest 类型的 requset 对象没有获取 session 对象的方法所以此时需要将 request对象强转成 HttpServletRequest 对象。 HttpServletRequest req (HttpServletRequest) request;然后完成以下逻辑 获取Session对象从Session对象中获取名为 user 的数据判断获取到的数据是否是 null 如果不是说明已经登陆放行如果是说明尚未登陆将提示信息存储到域对象中并跳转到登陆页面 代码如下 WebFilter(/*) public class LoginFilter implements Filter {Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {HttpServletRequest req (HttpServletRequest) request;//1. 判断session中是否有userHttpSession session req.getSession();Object user session.getAttribute(user);//2. 判断user是否为nullif(user ! null){// 登录过了//放行chain.doFilter(request, response);}else {// 没有登陆存储提示信息跳转到登录页面req.setAttribute(login_msg,您尚未登陆);req.getRequestDispatcher(/login.jsp).forward(req,response);}}public void init(FilterConfig config) throws ServletException {}public void destroy() {} }1.6.3.3 测试并抛出问题 在浏览器上输入 http://localhost:8080/brand-demo/ 可以看到如下页面效果 从上面效果可以看出没有登陆确实是跳转到登陆页面了但是登陆页面为什么展示成这种效果了呢 1.6.3.4 问题分析及解决 因为登陆页面需要 css/login.css 这个文件进行样式的渲染下图是登陆页面引入的css文件图解 而在请求这个css资源时被过滤器拦截就相当于没有加载到样式文件导致的。解决这个问题只需要对所以的登陆相关的资源进行放行即可。还有一种情况就是当我没有用户信息时需要进行注册而注册时也希望被过滤器放行。 综上我们需要在判断session中是否包含用户信息之前应该加上对登陆及注册相关资源放行的逻辑处理 //判断访问资源路径是否和登录注册相关 //1,在数组中存储登陆和注册相关的资源路径 String[] urls {/login.jsp,/imgs/,/css/,/loginServlet,/register.jsp,/registerServlet,/checkCodeServlet}; //2,获取当前访问的资源路径 String url req.getRequestURL().toString(); //3,遍历数组获取到每一个需要放行的资源路径 for (String u : urls) {//4,判断当前访问的资源路径字符串是否包含要放行的的资源路径字符串/*比如当前访问的资源路径是 /brand-demo/login.jsp而字符串 /brand-demo/login.jsp 包含了 字符串 /login.jsp 所以这个字符串就需要放行*/if(url.contains(u)){//找到了放行chain.doFilter(request, response);//break;return;} }1.6.3.5 过滤器完整代码 WebFilter(/*) public class LoginFilter implements Filter {Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {HttpServletRequest req (HttpServletRequest) request;//判断访问资源路径是否和登录注册相关//1,在数组中存储登陆和注册相关的资源路径String[] urls {/login.jsp,/imgs/,/css/,/loginServlet,/register.jsp,/registerServlet,/checkCodeServlet};//2,获取当前访问的资源路径String url req.getRequestURL().toString(); //3,遍历数组获取到每一个需要放行的资源路径for (String u : urls) {//4,判断当前访问的资源路径字符串是否包含要放行的的资源路径字符串/*比如当前访问的资源路径是 /brand-demo/login.jsp而字符串 /brand-demo/login.jsp 包含了 字符串 /login.jsp 所以这个字符串就需要放行*/if(url.contains(u)){//找到了放行chain.doFilter(request, response);//break;return;}}//1. 判断session中是否有userHttpSession session req.getSession();Object user session.getAttribute(user);//2. 判断user是否为nullif(user ! null){// 登录过了//放行chain.doFilter(request, response);}else {// 没有登陆存储提示信息跳转到登录页面req.setAttribute(login_msg,您尚未登陆);req.getRequestDispatcher(/login.jsp).forward(req,response);}}public void init(FilterConfig config) throws ServletException {}public void destroy() {} }2 Listener 2.1 概述 Listener 表示监听器是 JavaWeb 三大组件(Servlet、Filter、Listener)之一。 监听器可以监听就是在 applicationsessionrequest 三个对象创建、销毁或者往其中添加修改删除属性时自动执行代码的功能组件。 request 和 session 我们学习过。而 application 是 ServletContext 类型的对象。 ServletContext 代表整个web应用在服务器启动的时候tomcat会自动创建该对象。在服务器关闭时会自动销毁该对象。 2.2 分类 JavaWeb 提供了8个监听器 这里面只有 ServletContextListener 这个监听器后期我们会接触到ServletContextListener 是用来监听 ServletContext 对象的创建和销毁。 ServletContextListener 接口中有以下两个方法 void contextInitialized(ServletContextEvent sce)ServletContext 对象被创建了会自动执行的方法void contextDestroyed(ServletContextEvent sce)ServletContext 对象被销毁时会自动执行的方法 2.3 代码演示 我们只演示一下 ServletContextListener 监听器 定义一个类实现ServletContextListener 接口重写所有的抽象方法使用 WebListener 进行配置 代码如下 WebListener public class ContextLoaderListener implements ServletContextListener {Overridepublic void contextInitialized(ServletContextEvent sce) {//加载资源System.out.println(ContextLoaderListener...);}Overridepublic void contextDestroyed(ServletContextEvent sce) {//释放资源} }启动服务器就可以在启动的日志信息中看到 contextInitialized() 方法输出的内容同时也说明了 ServletContext 对象在服务器启动的时候被创建了。 3 Ajax 3.1 概述 AJAX (Asynchronous JavaScript And XML)异步的 JavaScript 和 XML。 我们先来说概念中的 JavaScript 和 XMLJavaScript 表明该技术和前端相关XML 是指以此进行数据交换。而这两个我们之前都学习过。 3.1.1 作用 AJAX 作用有以下两方面 与服务器进行数据交换通过AJAX可以给服务器发送请求服务器将数据直接响应回给浏览器。如下图 我们先来看之前做功能的流程如下图 如上图Servlet 调用完业务逻辑层后将数据存储到域对象中然后跳转到指定的 jsp 页面在页面上使用 EL表达式 和 JSTL 标签库进行数据的展示。 而我们学习了AJAX 后就可以使用AJAX和服务器进行通信以达到使用 HTMLAJAX来替换JSP页面了。如下图浏览器发送请求servletservlet 调用完业务逻辑层后将数据直接响应回给浏览器页面页面使用 HTML 来进行数据展示。 2. 异步交互可以在不重新加载整个页面的情况下与服务器交换数据并更新部分网页的技术如搜索联想、用户名是否可用校验等等… 上图所示的效果我们经常见到在我们输入一些关键字例如 奥运后就会在下面联想出相关的内容而联想出来的这部分数据肯定是存储在百度的服务器上而我们并没有看出页面重新刷新这就是 更新局部页面 的效果。再如下图 我们在用户名的输入框输入用户名当输入框一失去焦点如果用户名已经被占用就会在下方展示提示的信息在这整个过程中也没有页面的刷新只是在局部展示出了提示信息这就是 更新局部页面 的效果。 3.1.2 同步和异步 知道了局部刷新后接下来我们再聊聊同步和异步: 同步发送请求过程如下 ​ 浏览器页面在发送请求给服务器在服务器处理请求的过程中浏览器页面不能做其他的操作。只能等到服务器响应结束后才能浏览器页面才能继续做其他的操作。异步发送请求过程如下 浏览器页面发送请求给服务器在服务器处理请求的过程中浏览器页面还可以做其他的操作。 3.2 快速入门 3.2.1 服务端实现 在项目的创建 com.itheima.web.servlet 并在该包下创建名为 AjaxServlet 的servlet WebServlet(/ajaxServlet) public class AjaxServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1. 响应数据response.getWriter().write(hello ajax~);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);} }3.2.2 客户端实现 在 webapp 下创建名为 01-ajax-demo1.html 的页面在该页面书写 ajax 代码 创建核心对象不同的浏览器创建的对象是不同的 var xhttp; if (window.XMLHttpRequest) {xhttp new XMLHttpRequest(); } else {// code for IE6, IE5xhttp new ActiveXObject(Microsoft.XMLHTTP); }发送请求//建立连接 xhttp.open(GET, http://localhost:8080/ajax-demo/ajaxServlet); //发送请求 xhttp.send();获取响应xhttp.onreadystatechange function() {if (this.readyState 4 this.status 200) {// 通过 this.responseText 可以获取到服务端响应的数据alert(this.responseText);} };完整代码如下 !DOCTYPE html html langen headmeta charsetUTF-8titleTitle/title /head bodyscript//1. 创建核心对象var xhttp;if (window.XMLHttpRequest) {xhttp new XMLHttpRequest();} else {// code for IE6, IE5xhttp new ActiveXObject(Microsoft.XMLHTTP);}//2. 发送请求xhttp.open(GET, http://localhost:8080/ajax-demo/ajaxServlet);xhttp.send();//3. 获取响应xhttp.onreadystatechange function() {if (this.readyState 4 this.status 200) {alert(this.responseText);}}; /script /body /html3.2.3 测试 在浏览器地址栏输入 http://localhost:8080/ajax-demo/01-ajax-demo1.html 在 01-ajax-demo1.html加载的时候就会发送 ajax 请求效果如下 我们可以通过 开发者模式 查看发送的 AJAX 请求。在浏览器上按 F12 快捷键 这个是查看所有的请求如果我们只是想看 异步请求的话点击上图中 All 旁边的 XHR会发现只展示 Type 是 xhr 的请求。如下图 3.3 案例 需求在完成用户注册时当用户名输入框失去焦点时校验用户名是否在数据库已存在 3.3.1 分析 前端完成的逻辑 给用户名输入框绑定光标失去焦点事件 onblur发送 ajax请求携带username参数处理响应是否显示提示信息 后端完成的逻辑 接收用户名调用service查询User。此案例是为了演示前后端异步交互所以此处我们不做业务逻辑处理返回标记 整体流程如下 3.3.2 后端实现 在 com.ithiema.web.servlet 包中定义名为 SelectUserServlet 的servlet。代码如下 WebServlet(/selectUserServlet) public class SelectUserServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1. 接收用户名String username request.getParameter(username);//2. 调用service查询User对象此处不进行业务逻辑处理直接给 flag 赋值为 true表明用户名占用boolean flag true;//3. 响应标记response.getWriter().write( flag);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);} }3.3.3 前端实现 项目 webapp 下。 register.css * {margin: 0;padding: 0;list-style-type: none; } .reg-content{padding: 30px;margin: 3px; } a, img {border: 0; }body {background-image: url(../imgs/reg_bg_min.jpg) ;text-align: center; }table {border-collapse: collapse;border-spacing: 0; }td, th {padding: 0;height: 90px;} .inputs{vertical-align: top; }.clear {clear: both; }.clear:before, .clear:after {content: ;display: table; }.clear:after {clear: both; }.form-div {background-color: rgba(255, 255, 255, 0.27);border-radius: 10px;border: 1px solid #aaa;width: 424px;margin-top: 150px;margin-left:1050px;padding: 30px 0 20px 0px;font-size: 16px;box-shadow: inset 0px 0px 10px rgba(255, 255, 255, 0.5), 0px 0px 15px rgba(75, 75, 75, 0.3);text-align: left; }.form-div input[typetext], .form-div input[typepassword], .form-div input[typeemail] {width: 268px;margin: 10px;line-height: 20px;font-size: 16px; }.form-div input[typecheckbox] {margin: 20px 0 20px 10px; }.form-div input[typebutton], .form-div input[typesubmit] {margin: 10px 20px 0 0; }.form-div table {margin: 0 auto;text-align: right;color: rgba(64, 64, 64, 1.00); }.form-div table img {vertical-align: middle;margin: 0 0 5px 0; }.footer {color: rgba(64, 64, 64, 1.00);font-size: 12px;margin-top: 30px; }.form-div .buttons {float: right; }input[typetext], input[typepassword], input[typeemail] {border-radius: 8px;box-shadow: inset 0 2px 5px #eee;padding: 10px;border: 1px solid #D4D4D4;color: #333333;margin-top: 5px; }input[typetext]:focus, input[typepassword]:focus, input[typeemail]:focus {border: 1px solid #50afeb;outline: none; }input[typebutton], input[typesubmit] {padding: 7px 15px;background-color: #3c6db0;text-align: center;border-radius: 5px;overflow: hidden;min-width: 80px;border: none;color: #FFF;box-shadow: 1px 1px 1px rgba(75, 75, 75, 0.3); }input[typebutton]:hover, input[typesubmit]:hover {background-color: #5a88c8; }input[typebutton]:active, input[typesubmit]:active {background-color: #5a88c8; } .err_msg{color: red;padding-right: 170px; } #password_err,#tel_err{padding-right: 195px; }#reg_btn{margin-right:50px; width: 285px; height: 45px; margin-top:20px; }#checkCode{width: 100px; }#changeImg{color: aqua; }a.jpg reg_bg_min.jpg register.html !DOCTYPE html html langen headmeta charsetUTF-8title欢迎注册/titlelink hrefcss/register.css relstylesheet /head bodydiv classform-divdiv classreg-contenth1欢迎注册/h1span已有帐号/span a hreflogin.html登录/a/divform idreg-form action# methodgettabletrtd用户名/tdtd classinputsinput nameusername typetext idusernamebrspan idusername_err classerr_msg styledisplay: none用户名不太受欢迎/span/td/trtrtd密码/tdtd classinputsinput namepassword typepassword idpasswordbrspan idpassword_err classerr_msg styledisplay: none密码格式有误/span/td/trtrtd验证码/tdtd classinputsinput namecheckCode typetext idcheckCodeimg srcimgs/a.jpga href# idchangeImg看不清/a/td/tr/tablediv classbuttonsinput value注 册 typesubmit idreg_btn/divbr classclear/form/div /body /html并在 register.html 页面的 body 结束标签前编写 script 标签在该标签中实现如下逻辑 第一步给用户名输入框绑定光标失去焦点事件 onblur //1. 给用户名输入框绑定 失去焦点事件 document.getElementById(username).onblur function () {}第二步发送 ajax请求携带username参数 在 第一步 绑定的匿名函数中书写发送 ajax 请求的代码 //2. 发送ajax请求 //2.1. 创建核心对象 var xhttp; if (window.XMLHttpRequest) {xhttp new XMLHttpRequest(); } else {// code for IE6, IE5xhttp new ActiveXObject(Microsoft.XMLHTTP); } //2.2. 发送请求 xhttp.open(GET, http://localhost:8080/ajax-demo/selectUserServlet); xhttp.send();//2.3. 获取响应 xhttp.onreadystatechange function() {if (this.readyState 4 this.status 200) {//处理响应的结果} };由于我们发送的是 GET 请求所以需要在 URL 后拼接从输入框获取的用户名数据。而我们在 第一步 绑定的匿名函数中通过以下代码可以获取用户名数据 // 获取用户名的值 var username this.value; //this 给谁绑定的事件this就代表谁而携带数据需要将 URL 修改为 xhttp.open(GET, http://localhost:8080/ajax-demo/selectUserServlet?usernameusername);第三步处理响应是否显示提示信息 当 this.readyState 4 this.status 200 条件满足时说明已经成功响应数据了。 此时需要判断响应的数据是否是 “true” 字符串如果是说明用户名已经占用给出错误提示如果不是说明用户名未被占用清除错误提示。代码如下 //判断 if(this.responseText true){//用户名存在显示提示信息document.getElementById(username_err).style.display ; }else {//用户名不存在 清楚提示信息document.getElementById(username_err).style.display none; }综上所述前端完成代码如下 //1. 给用户名输入框绑定 失去焦点事件 document.getElementById(username).onblur function () {//2. 发送ajax请求// 获取用户名的值var username this.value;//2.1. 创建核心对象var xhttp;if (window.XMLHttpRequest) {xhttp new XMLHttpRequest();} else {// code for IE6, IE5xhttp new ActiveXObject(Microsoft.XMLHTTP);}//2.2. 发送请求xhttp.open(GET, http://localhost:8080/ajax-demo/selectUserServlet?usernameusername);xhttp.send();//2.3. 获取响应xhttp.onreadystatechange function() {if (this.readyState 4 this.status 200) {//alert(this.responseText);//判断if(this.responseText true){//用户名存在显示提示信息document.getElementById(username_err).style.display ;}else {//用户名不存在 清楚提示信息document.getElementById(username_err).style.display none;}}}; }4 axios Axios 对原生的AJAX进行封装简化书写。 Axios官网是https://www.axios-http.cn 4.1 基本使用 axios 使用是比较简单的分为以下两步 引入 axios 的 js 文件script srcjs/axios-0.18.0.js/script使用axios 发送请求并获取响应结果 发送 get 请求axios({method:get,url:http://localhost:8080/ajax-demo1/aJAXDemo1?usernamezhangsan }).then(function (resp){alert(resp.data); })发送 post 请求axios({method:post,url:http://localhost:8080/ajax-demo1/aJAXDemo1,data:usernamezhangsan }).then(function (resp){alert(resp.data); });axios() 是用来发送异步请求的小括号中使用 js 对象传递请求相关的参数 method 属性用来设置请求方式的。取值为 get 或者 post。url 属性用来书写请求的资源路径。如果是 get 请求需要将请求参数拼接到路径的后面格式为 url?参数名参数值参数名2参数值2。data 属性作为请求体被发送的数据。也就是说如果是 post 请求的话数据需要作为 data 属性的值。 then() 需要传递一个匿名函数。我们将 then() 中传递的匿名函数称为 回调函数意思是该匿名函数在发送请求时不会被调用而是在成功响应后调用的函数。而该回调函数中的 resp 参数是对响应的数据进行封装的对象通过 resp.data 可以获取到响应的数据。 4.2 快速入门 4.2.1 后端实现 定义一个用于接收请求的servlet代码如下 WebServlet(/axiosServlet) public class AxiosServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println(get...);//1. 接收请求参数String username request.getParameter(username);System.out.println(username);//2. 响应数据response.getWriter().write(hello Axios~);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println(post...);this.doGet(request, response);} }4.2.2 前端实现 引入 js 文件script srcjs/axios-0.18.0.js/script发送 ajax 请求 get 请求axios({method:get,url:http://localhost:8080/ajax-demo/axiosServlet?usernamezhangsan }).then(function (resp) {alert(resp.data); })post 请求axios({method:post,url:http://localhost:8080/ajax-demo/axiosServlet,data:usernamezhangsan }).then(function (resp) {alert(resp.data); })整体页面代码如下 !DOCTYPE html html langen headmeta charsetUTF-8titleTitle/title /head bodyscript srcjs/axios-0.18.0.js/script script//1. get/* axios({method:get,url:http://localhost:8080/ajax-demo/axiosServlet?usernamezhangsan}).then(function (resp) {alert(resp.data);})*///2. post 在js中{} 表示一个js对象而这个js对象中有三个属性axios({method:post,url:http://localhost:8080/ajax-demo/axiosServlet,data:usernamezhangsan}).then(function (resp) {alert(resp.data);}) /script /body /html4.3 请求方法别名 为了方便起见 Axios 已经为所有支持的请求方法提供了别名。如下 get 请求 axios.get(url[,config])delete 请求 axios.delete(url[,config])head 请求 axios.head(url[,config])options 请求 axios.option(url[,config])post 请求axios.post(url[,data[,config])put 请求axios.put(url[,data[,config])patch 请求axios.patch(url[,data[,config]) 而我们只关注 get 请求和 post 请求。 入门案例中的 get 请求代码可以改为如下 axios.get(http://localhost:8080/ajax-demo/axiosServlet?usernamezhangsan).then(function (resp) {alert(resp.data); });入门案例中的 post 请求代码可以改为如下 axios.post(http://localhost:8080/ajax-demo/axiosServlet,usernamezhangsan).then(function (resp) {alert(resp.data); })5 JSON 5.1 概述 概念JavaScript Object Notation。JavaScript 对象表示法. 如下是 JavaScript 对象的定义格式 {name:zhangsan,age:23,city:北京 }接下来我们再看看 JSON 的格式 {name:zhangsan,age:23,city:北京 }通过上面 js 对象格式和 json 格式进行对比发现两个格式特别像。只不过 js 对象中的属性名可以使用引号可以是单引号也可以是双引号而 json 格式中的键要求必须使用双引号括起来这是 json 格式的规定。json 格式的数据有什么作用呢 作用由于其语法格式简单层次结构鲜明现多用于作为数据载体在网络中进行数据传输。如下图所示就是服务端给浏览器响应的数据这个数据比较简单如果现需要将 JAVA 对象中封装的数据响应回给浏览器的话应该以何种数据传输呢 大家还记得 ajax 的概念吗 是 异步的 JavaScript 和 xml。这里的 xml就是以前进行数据传递的方式如下 studentname张三/nameage23/agecity北京/city /student再看 json 描述以上数据的写法 { name:张三,age:23,city:北京 }上面两种格式进行对比后就会发现 json 格式数据的简单以及所占的字节数少等优点。 5.2 JSON 基础语法 5.2.1 定义格式 JSON 本质就是一个字符串但是该字符串内容是有一定的格式要求的。 定义格式如下 var 变量名 {key:value,key:value,...};JSON 串的键要求必须使用双引号括起来而值根据要表示的类型确定。value 的数据类型分为如下 数字整数或浮点数字符串使用双引号括起来逻辑值true或者false数组在方括号中对象在花括号中null 示例 var jsonStr {name:zhangsan,age:23,addr:[北京,上海,西安]}5.2.2 代码演示 创建一个页面在该页面的 script 标签中定义json字符串 !DOCTYPE html html langen headmeta charsetUTF-8titleTitle/title /head body script//1. 定义JSON字符串var jsonStr {name:zhangsan,age:23,addr:[北京,上海,西安]}alert(jsonStr);/script /body /html通过浏览器打开页面效果如下图所示 现在我们需要获取到该 JSON 串中的 name 属性值应该怎么处理呢 如果它是一个 js 对象我们就可以通过 js对象.属性名 的方式来获取数据。JS 提供了一个对象 JSON 该对象有如下两个方法 parse(str) 将 JSON串转换为 js 对象。使用方式是 var jsObject JSON.parse(jsonStr);stringify(obj) 将 js 对象转换为 JSON 串。使用方式是var jsonStr JSON.stringify(jsObject) 代码演示 !DOCTYPE html html langen headmeta charsetUTF-8titleTitle/title /head body script//1. 定义JSON字符串var jsonStr {name:zhangsan,age:23,addr:[北京,上海,西安]}alert(jsonStr);//2. 将 JSON 字符串转为 JS 对象let jsObject JSON.parse(jsonStr);alert(jsObject)alert(jsObject.name)//3. 将 JS 对象转换为 JSON 字符串let jsonStr2 JSON.stringify(jsObject);alert(jsonStr2) /script /body /html5.2.3 发送异步请求携带参数 后面我们使用 axios 发送请求时如果要携带复杂的数据时都会以 JSON 格式进行传递如下 axios({method:post,url:http://localhost:8080/ajax-demo/axiosServlet,data:usernamezhangsan }).then(function (resp) {alert(resp.data); })请求参数不可能由我们自己拼接字符串吧肯定不用可以提前定义一个 js 对象用来封装需要提交的参数然后使用 JSON.stringify(js对象) 转换为 JSON 串再将该 JSON 串作为 axios 的 data 属性值进行请求参数的提交。如下 var jsObject {name:张三};axios({method:post,url:http://localhost:8080/ajax-demo/axiosServlet,data: JSON.stringify(jsObject) }).then(function (resp) {alert(resp.data); })而 axios 是一个很强大的工具。我们只需要将需要提交的参数封装成 js 对象并将该 js 对象作为 axios 的 data 属性值进行它会自动将 js 对象转换为 JSON 串进行提交。如下 var jsObject {name:张三};axios({method:post,url:http://localhost:8080/ajax-demo/axiosServlet,data:jsObject //这里 axios 会将该js对象转换为 json 串的 }).then(function (resp) {alert(resp.data); })注意 js 提供的 JSON 对象我们只需要了解一下即可。因为 axios 会自动对 js 对象和 JSON 串进行想换转换。发送异步请求时如果请求参数是 JSON 格式那请求方式必须是 POST。因为 JSON 串需要放在请求体中。 5.3 JSON串和Java对象的相互转换 学习完 json 后接下来聊聊 json 的作用。以后我们会以 json 格式的数据进行前后端交互。前端发送请求时如果是复杂的数据就会以 json 提交给后端而后端如果需要响应一些复杂的数据时也需要以 json 格式将数据响应回给浏览器。 在后端我们就需要重点学习以下两部分操作 请求数据JSON字符串转为Java对象响应数据Java对象转为JSON字符串 接下来给大家介绍一套 API可以实现上面两部分操作。这套 API 就是 Fastjson 5.3.1 Fastjson 概述 Fastjson 是阿里巴巴提供的一个Java语言编写的高性能功能完善的 JSON 库是目前Java语言中最快的 JSON 库可以实现 Java 对象和 JSON 字符串的相互转换。 5.3.2 Fastjson 使用 Fastjson 使用也是比较简单的分为以下三步完成 导入坐标dependencygroupIdcom.alibaba/groupIdartifactIdfastjson/artifactIdversion1.2.83/version /dependencyJava对象转JSONString jsonStr JSON.toJSONString(obj);将 Java 对象转换为 JSON 串只需要使用 Fastjson 提供的 JSON 类中的 toJSONString() 静态方法即可。JSON字符串转Java对象User user JSON.parseObject(jsonStr, User.class);将 json 转换为 Java 对象只需要使用 Fastjson 提供的 JSON 类中的 parseObject() 静态方法即可。 5.3.3 代码演示 引入坐标创建User实体类 id name password 以及set get tostring方法 创建一个类FastJsonDemo专门用来测试 Java 对象和 JSON 串的相互转换代码如下public class FastJsonDemo {public static void main(String[] args) {//1. 将Java对象转为JSON字符串User user new User();user.setId(1);user.setUsername(zhangsan);user.setPassword(123);String jsonString JSON.toJSONString(user);System.out.println(jsonString);//{id:1,password:123,username:zhangsan}//2. 将JSON字符串转为Java对象User u JSON.parseObject({\id\:1,\password\:\123\,\username\:\zhangsan\}, User.class);System.out.println(u);//User{id1, namenull, password123}} }6 案例 6.1 需求 使用Axios JSON 完成品牌列表数据查询和添加。页面效果还是下图所示 6.2 查询所有功能 如上图所示就该功能的整体流程。前后端需以 JSON 格式进行数据的传递由于此功能是查询所有的功能前端发送 ajax 请求不需要携带参数而后端响应数据需以如下格式的 json 数据 6.2.1 环境准备 将 02-AJAX\04-资料\3. 品牌列表案例\初始工程 下的 brand-demo 工程拷贝到我们自己 工作空间 然后再将项目导入到我们自己的 Idea 中。工程目录结构如下 注意 在给定的原始工程中已经给定一些代码。而在此案例中我们只关注前后端交互代码实现要根据自己的数据库环境去修改连接数据库的信息在 mybatis-config.xml 核心配置文件中修改 6.2.2 后端实现 在 com.itheima.web 包下创建名为 SelectAllServlet 的 servlet具体的逻辑如下 调用 service 的 selectAll() 方法进行查询所有的逻辑处理将查询到的集合数据转换为 json 数据。我们将此过程称为 序列化如果是将 json 数据转换为 Java 对象我们称之为 反序列化将 json 数据响应回给浏览器。这里一定要设置响应数据的类型及字符集 response.setContentType(text/json;charsetutf-8); SelectAllServlet 代码如下 WebServlet(/selectAllServlet) public class SelectAllServlet extends HttpServlet {private BrandService brandService new BrandService();Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1. 调用Service查询ListBrand brands brandService.selectAll();//2. 将集合转换为JSON数据 序列化String jsonString JSON.toJSONString(brands);//3. 响应数据 application/json text/jsonresponse.setContentType(text/json;charsetutf-8);response.getWriter().write(jsonString);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);} }6.2.3 前端实现 引入 js 文件 在 brand.html 页面引入 axios 的 js 文件 script srcjs/axios-0.18.0.js/script绑定 页面加载完毕 事件 在 brand.html 页面绑定加载完毕事件该事件是在页面加载完毕后被触发代码如下 window.onload function() {}发送异步请求 在页面加载完毕事件绑定的匿名函数中发送异步请求代码如下 //2. 发送ajax请求 axios({method:get,url:http://localhost:8080/brand-demo/selectAllServlet }).then(function (resp) {});处理响应数据 在 then 中的回调函数中通过 resp.data 可以获取响应回来的数据而数据格式如下 现在我们需要拼接字符串将下面表格中的所有的 tr 拼接到一个字符串中然后使用 document.getElementById(brandTable).innerHTML 拼接好的字符串 就可以动态的展示出用户想看到的数据 而表头行是固定的所以先定义初始值是表头行数据的字符串如下 //获取数据 let brands resp.data; let tableData tr\n th序号/th\n th品牌名称/th\n th企业名称/th\n th排序/th\n th品牌介绍/th\n th状态/th\n th操作/th\n /tr;接下来遍历响应回来的数据 brands 拿到每一条品牌数据 for (let i 0; i brands.length ; i) {let brand brands[i];}紧接着就是从 brand 对象中获取数据并且拼接 数据行累加到 tableData 字符串变量中 tableData \n tr align\center\\n td(i1)/td\n tdbrand.brandName/td\n tdbrand.companyName/td\n tdbrand.ordered/td\n tdbrand.description/td\n tdbrand.status/td\n \n tda href\#\修改/a a href\#\删除/a/td\n /tr;最后再将拼接好的字符串写到表格中 // 设置表格数据 document.getElementById(brandTable).innerHTML tableData;整体页面代码如下 !DOCTYPE html html langen headmeta charsetUTF-8titleTitle/title /head body a hrefaddBrand.htmlinput typebutton value新增/abr hr table idbrandTable border1 cellspacing0 width100%/tablescript srcjs/axios-0.18.0.js/scriptscript//1. 当页面加载完成后发送ajax请求window.onload function () {//2. 发送ajax请求axios({method:get,url:http://localhost:8080/brand-demo/selectAllServlet}).then(function (resp) {//获取数据let brands resp.data;let tableData tr\n th序号/th\n th品牌名称/th\n th企业名称/th\n th排序/th\n th品牌介绍/th\n th状态/th\n th操作/th\n /tr;for (let i 0; i brands.length ; i) {let brand brands[i];tableData \n tr align\center\\n td(i1)/td\n tdbrand.brandName/td\n tdbrand.companyName/td\n tdbrand.ordered/td\n tdbrand.description/td\n tdbrand.status/td\n \n tda href\#\修改/a a href\#\删除/a/td\n /tr;}// 设置表格数据document.getElementById(brandTable).innerHTML tableData;})} /script /body /html6.3 添加品牌功能 如上所示当我们点击 新增 按钮会跳转到 addBrand.html 页面。在 addBrand.html 页面输入数据后点击 提交 按钮就会将数据提交到后端而后端将数据保存到数据库中。 具体的前后端交互的流程如下 说明 前端需要将用户输入的数据提交到后端这部分数据需要以 json 格式进行提交数据格式如下 6.3.1 后端实现 在 com.itheima.web 包下创建名为 AddServlet 的 servlet具体的逻辑如下 获取请求参数 由于前端提交的是 json 格式的数据所以我们不能使用 request.getParameter() 方法获取请求参数 如果提交的数据格式是 usernamezhangsanage23 后端就可以使用 request.getParameter() 方法获取如果提交的数据格式是 json后端就需要通过 request 对象获取输入流再通过输入流读取数据 将获取到的请求参数json格式的数据转换为 Brand 对象 调用 service 的 add() 方法进行添加数据的逻辑处理 将 json 数据响应回给浏览器。 AddServlet 代码如下 WebServlet(/addServlet) public class AddServlet extends HttpServlet {private BrandService brandService new BrandService();Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1. 接收数据,request.getParameter 不能接收json的数据/* String brandName request.getParameter(brandName);System.out.println(brandName);*/// 获取请求体数据BufferedReader br request.getReader();String params br.readLine();// 将JSON字符串转为Java对象Brand brand JSON.parseObject(params, Brand.class);//2. 调用service 添加brandService.add(brand);//3. 响应成功标识response.getWriter().write(success);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);} }6.3.2 前端实现 在 addBrand.html 页面给 提交 按钮绑定点击事件并在绑定的匿名函数中发送异步请求代码如下 //1. 给按钮绑定单击事件 document.getElementById(btn).onclick function () {//2. 发送ajax请求axios({method:post,url:http://localhost:8080/brand-demo/addServlet,data:???}).then(function (resp) {// 判断响应数据是否为 successif(resp.data success){location.href http://localhost:8080/brand-demo/brand.html;}}) }现在我们只需要考虑如何获取页面上用户输入的数据即可。 首先我们先定义如下的一个 js 对象该对象是用来封装页面上输入的数据并将该对象作为上面发送异步请求时 data 属性的值。 // 将表单数据转为json var formData {brandName:,companyName:,ordered:,description:,status:, };接下来获取输入框输入的数据并将获取到的数据赋值给 formData 对象指定的属性。比如获取用户名的输入框数据并把该数据赋值给 formData 对象的 brandName 属性 // 获取表单数据 let brandName document.getElementById(brandName).value; // 设置数据 formData.brandName brandName;说明其他的输入框都用同样的方式获取并赋值。 但是有一个比较特殊就是状态数据如下图是页面内容 我们需要判断哪儿个被选中再将选中的单选框数据赋值给 formData 对象的 status 属性代码实现如下 let status document.getElementsByName(status); for (let i 0; i status.length; i) {if(status[i].checked){//formData.status status[i].value ;} }整体页面代码如下 !DOCTYPE html html langenheadmeta charsetUTF-8title添加品牌/title /head body h3添加品牌/h3 form action methodpost品牌名称input idbrandName namebrandNamebr企业名称input idcompanyName namecompanyNamebr排序input idordered nameorderedbr描述信息textarea rows5 cols20 iddescription namedescription/textareabr状态input typeradio namestatus value0禁用input typeradio namestatus value1启用brinput typebutton idbtn value提交 /formscript srcjs/axios-0.18.0.js/scriptscript//1. 给按钮绑定单击事件document.getElementById(btn).onclick function () {// 将表单数据转为jsonvar formData {brandName:,companyName:,ordered:,description:,status:,};// 获取表单数据let brandName document.getElementById(brandName).value;// 设置数据formData.brandName brandName;// 获取表单数据let companyName document.getElementById(companyName).value;// 设置数据formData.companyName companyName;// 获取表单数据let ordered document.getElementById(ordered).value;// 设置数据formData.ordered ordered;// 获取表单数据let description document.getElementById(description).value;// 设置数据formData.description description;let status document.getElementsByName(status);for (let i 0; i status.length; i) {if(status[i].checked){//formData.status status[i].value ;}}//console.log(formData);//2. 发送ajax请求axios({method:post,url:http://localhost:8080/brand-demo/addServlet,data:formData}).then(function (resp) {// 判断响应数据是否为 successif(resp.data success){location.href http://localhost:8080/brand-demo/brand.html;}})} /script /body /html说明 查询所有 功能和 添加品牌 功能就全部实现大家肯定会感觉前端的代码很复杂而这只是暂时的后面学习了 vue 前端框架后这部分前端代码就可以进行很大程度的简化。
http://www.sadfv.cn/news/113998/

相关文章:

  • 雇人做淘宝网站多少钱wordpress小程序投稿
  • 定制型网站建设平台养老网站建设方案
  • 建设官方网站怎么登录物业公司网站建设方案
  • 长沙外贸企业网站建设c 网站开发调试
  • 电子商务网站制作教程自己做网站 有名6
  • 建设门户网站所需wordpress 4.5 漏洞
  • 做搞机网站诚信网站的申请有几家公司可以做的
  • 怡清源在慧聪网网站建设情况域名可以自己注册吗
  • 凡科网站做门户网怎么样动画设计和动漫设计一样吗
  • 刷单类网站开发珠海seo海网站建设
  • 如何申请网站空间和注册域名网页设计图片如何居中
  • 博望网站建设做传销网站后果严重吗
  • 腾讯云点播做视频网站在百度上做网站怎么做
  • 沈阳世纪兴网站制作三 网站开发使用软件环境
  • 网站开发H5海外广告投放渠道
  • 西安建设网站制作搭建WordPress教程
  • 网站都要交域名费么学做网站论坛vip码
  • 做网站的软件多少钱长沙微信网站公司
  • 东莞网站建设市场分析品牌网站建设的作用
  • 现在网站建设尺寸一般多少30天网站建设实录
  • 如何做网站首页收录建设银行手机银行官方网站下载安装
  • 网站开发进度设计北京网站制作业务如何开展
  • html5营销网站建设上榜网络
  • 网站开发如何无感更新白城网站建设哪家好
  • 有服务器自己怎么做网站前台模板之家免费
  • 素材网站整站下载全国推广优化网站
  • 青岛网站建设推进福建龙岩有哪些网络平台
  • 重庆品牌服装网站建设手机软件编程
  • 徐州云龙区建设局网站专业做网站+上海
  • 英文网站怎么设计中铁十六局门户网