IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> servlet&Ajax&Json -> 正文阅读

[Java知识库]servlet&Ajax&Json

web开发概述

web程序:所有的程序都部署在服务器端,通过浏览器远程访问

服务器:提供服务 1、接收请求 2、响应

? 广义:软件+硬件

? 狭义:程序 ——放置文件(项目),供英特网中的其它电脑访问

流程:客户端浏览器访问程序,先通过IP找到服务器地址,端口号找到程序(服务器)

在这里插入图片描述

web开发环境搭建

tomcat:apache公司提供的一款开源服务器

  1. 下载,解压 http://tomcat.apache.org
  2. 配置JAVA_HOME环境变量
  3. 在tomcat的bin目录 双击运行 startup.bat命令 启动tomcat
  4. 访问:IP+端口号

在这里插入图片描述

在这里插入图片描述

  • bin 放着各种命令 startup.bat命令 shutdown.bat
  • conf 放着配置文件 列如server.xml 修改端口号
  • lib tomcat运行所需要的jar包
  • logs 运行产生的日志文件
  • temp 临时缓存文件
  • webapps 部署web程序的目录
  • work 工作目录

创建发布web程序

  1. 右键项目——>add framework support(变为web项目)

    • src:Java代码
    • web:配置文件,网页代码

在这里插入图片描述

  1. 自动部署

    1. add configuration——>加号——>Tomcat Server Local
    2. Deployment部署——>artifacts:Application context:访问web的根目录
    3. Update classes and resources:自动更新

Servlet

  • 是用Java编写的服务器端程序。其主要功能在于交互式地浏览和修改数据,生成动态Web内容。狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。
  • Servlet运行于支持Java的应用服务器中。从实现上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。

Servlet作用

  • 接收客户端浏览器发送的请求
  • 调用其他java代码处理请求
  • 向客户端浏览器做出响应

Servlet使用

  1. 导入jar包 servlet-api.jar

  2. 继承HttpServlet

  3. 重写父类方法

    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    /*
       继承 HttpServlet
       重写父类方法
       配置servlet
     */
    public class DemoServlet extends HttpServlet {
    
        /*
         构造方法  初始化对象
         只被执行了一次,只创建了一个对象, 此对象由服务器创建的,
         默认是在客户端第一次访问该servlet时创建 servlet对象
         当 <load-on-startup>0</load-on-startup> 值>=0 时,会在服务器启动时创建
         */
        public DemoServlet() {
            System.out.println("DemoServlet");
        }
    
        /*
          初始化,当servlet对象创建后,服务器会自动调用init(),
          完成一些初始化操作.
          如果我们没有需要初始化的操作,也可以不重写init(),但是服务器依然会调用,会调用父类的init()
         */
        @Override
        public void init(ServletConfig config) throws ServletException {
            System.out.println("init");
            System.out.println(config.getInitParameter("name"));//获得配置文件中的信息
            System.out.println(config.getServletName());
        }
    
        /*
           为请求提供服务,每一次http请求,都会调用service(请求,响应)
         */
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("service");
        }
    
        /*
         当servlet对象销毁时,服务器会调用destroy(),
         让我完成一些最终的操作(例如保存日志....)
         如果我们没有一些最终的操作,也可以不重写destroy(),但是服务器依然会调用父类中destroy()
         */
        /*@Override
        public void destroy() {
            System.out.println("destroy");
        }*/
    }
    
  4. 配置Servlet

<!--    _ml:属于标记语言       
 html:标记内容指导内容如何显示       
 xml:可扩展标记语言,用来保存数据,保存配置文件数据    
web.xml:web程序配置文件,保存各种配置信息,在服务器启动时,由服务器读取-->
<!--配置servlet   把servlet配置进来,服务器就知道有这个类-->

<!--配置reg-->
<!--让服务器知道有这个类-->
<servlet>    
    <servlet-name>reg</servlet-name>    
    <servlet-class>com.ff.firstWeb.servlet.RegServlet</servlet-class></servlet>
<!--为Servlet配置一个供前端访问的地址-->
<servlet-mapping>    
    <servlet-name>reg</servlet-name>    
    <url-pattern>/reg</url-pattern>
</servlet-mapping>

Servlet生命周期

在这里插入图片描述

Http请求

请求行:请求方式:get / post 请求地址URL: Http协议版本:

请求头:包含主机地址,以及客户端的一些环境信息,以键值对的形式传递.

Host: 127.0.0.1:8088 请求的主机地址

请求体:请求体代表着浏览器在post请求方式中传递给服务器的参数,请求体中参数以键值形式传递, 多个用&链接,服务器接收到后再解析.

username=admin&userpwd=123

get&post

get
  • 超链接访问,默认是GET方式
  • form提交,不指定method,默认为GET方式
post

form提交,指定method=“POST”

区别
  • Get方式主要是从服务器获取信息;post主要是想服务器提交信息
  • Get方式在通过URL提交数据,数据在URL中可以看到;POST方式,数据放置在请求体中提交。
  • GET方式提交的数据大小受限制一般1kb(不同浏览器也会有不同);而POST则没有此限制。
应用
  • getParameter(name) — String 通过name获得值
  • getParameterValues — String[ ] 通过name获得多值
  • setCharacterEncoding(编码格式)
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;

public class Demo1Servlet extends HttpServlet {

    //构造方法默认有
    //init 不需要刻意不重写,服务器调用父类的
    //service 每次请求都要调用,由于http请求分为get,post请求,在servet中两者处理上略微不同,
    //所以父类中定义了doGet()  doPost()分别处理get,post请求.
    //在父类的service方法中写了一个判断 get-->doget  post-->dopost

    /*
      doget()处理get请求
      org.apache.catalina.connector.RequestFacade 实现 HttpServletRequest接口
      HttpServletRequest :封装了请求的信息,可以从中获取任何请求信息。
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doGet"+req);
        //请求行数据
        System.out.println(req.getMethod());    //GET
        System.out.println(req.getProtocol());  //HTTP/1.1
        System.out.println(req.getServerName());    //localhost
        System.out.println(req.getServerPort());    //8080

        //请求头
        System.out.println(req.getRemoteAddr());//获得客户端的ip
        System.out.println(req.getRemotePort());//客户端端口
        System.out.println(req.getHeader("User-Agent"));
        //接收用户请求的数据  tomcat8.0以后get请求数据的解码方式支持中文
        String name =  req.getParameter("name");
        System.out.println(name);//张三
        System.out.println(req.getParameter("age"));

    }

    /*
      dopost()处理post请求
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doPost");
        req.setCharacterEncoding("utf-8");//设置post请求数据解码格式

        System.out.println(req.getParameter("account"));
        System.out.println(req.getParameter("passoword"));
        System.out.println(req.getParameter("sex"));
        String[] courses = req.getParameterValues("course");
        System.out.println(Arrays.toString(courses));

        //处理  例如调用jdbc处理


        //根据处理的结果向客户端做出响应
        //Printwriter:单向打印流
        PrintWriter out = null;
        try {
           resp.setContentType("text/html;charset=utf-8");//设置响应内容的编码格式
           out = resp.getWriter();
           out.println("<h1>登录成功</h1>");

        }catch (Exception e){
            out.println("<h1>服务器忙,请稍后再试!</h1>");
        }

    }

    //destroy 不需要刻意不重写,服务器调用父类的
}

Http响应

  1. 通过Response对象设置编码格式
  2. 通过Response对象获得一个Printwriter打印输出字符流
  3. 通过流对象打印要输出的内容
//根据处理的结果向客户端做出响应
        //Printwriter:单向打印流
        PrintWriter out = null;
        try {
           resp.setContentType("text/html;charset=utf-8");//设置响应内容的编码格式
           out = resp.getWriter();
           out.println("<h1>登录成功</h1>");

        }catch (Exception e){
            out.println("<h1>服务器忙,请稍后再试!</h1>");
        }

Http状态码

在这里插入图片描述

Ajax

Ajax 全称为:“Asynchronous JavaScript and XML”(异步JavaScript 和 XML),

? 使用 Ajax,我们可以无刷新状态更新页面,对页面中的某个部分进行更新,并且实现异步提交,提升了用户体验。

同步&异步
  • 同步提交:当用户发送请求时,当前页面不可以使用,服务器响应页面到客户端,响应完成,用户才可以使用页面。
  • 异步提交:当用户发送请求时,当前页面还可以继续使用,当异步请求的数据响应给页面,页面把数据显示出来 。

实现

? 客户端发送请求,请求交给XMLHttpRequest,XMLHttpRequest把请求提交给服务器,服务器进行业务处理,服务器响应数据交给XMLHttpRequest对象,XMLHttpRequest对象接收数据,由javascript把数据写到页面上

在这里插入图片描述

XMLHttpRequest

前端js对象,用来接收servlet响应来的状态码

open(method,URL,async) 建立与服务器的连接

method参数指定请求的HTTP方法,典型的值是GET或POST

URL参数指定请求的地址

async参数指定是否使用异步请求,其值为true或false

//servlet:
//	接收前端发来的数据进行操作,再向前端js返回状态码,前端接收状态码用js对网页进行操作
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class LoginServlet_back extends HttpServlet {

    /*
     登录处理
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter out = null;
        try {
            //响应行(状态码200 404 500) 响应头(setContentType编码格式)
            //out.println("登录成功");服务器向客户端输出的内容
             resp.setContentType("text/html;charset=utf-8");//响应头
             req.setCharacterEncoding("utf-8");//设置解码格式
             String account = req.getParameter("account");
             String password = req.getParameter("password");
             LoginDao loginDao = new LoginDao();
             boolean b = loginDao.checkLogin(account, password);
            out = resp.getWriter();
            //后端只向前端响应一个状态码
            if(b){
                 out.println(0);
               //解决方案是使用ajax 从前端向后端进行发起请求交互
               //如果是ajax方式提交的数据,那么服务器端响应的数据返回后会交个XMLHttpRequest对象
             }else{
                 out.println(1);
             }
         }catch (Exception e){
            e.printStackTrace();
            out.println(2);
         }
    }

}
//javascript
<script type="text/javascript">

        function  subform(){
            var account = document.getElementById("accountId").value;
            var password = document.getElementById("passwordId").value;

            //使用XMLHttpRequest对象,发起异步请求
            var httpObj = new XMLHttpRequest();
            httpObj.open("post","login",true);
            httpObj.setRequestHeader("Content-Type","application/x-www-form-urlencoded");//设置提交数据的格式的请求头
            httpObj.send("account="+account+"&password="+password);

            //接收服务器端响应回来的数据,当发送请求之后,会触发onreadystatechange事件,
            //在此事件的回调函数中,获取响应的内容
            httpObj.onreadystatechange = function (){
                //当对象就绪状态为4,http响应状态码为200时获取响应内容
                if(httpObj.readyState==4&&httpObj.status==200){
                   if(httpobj.responseText==0){
                       alert("登录成功");
                   }else if(httpobj.responseText==1{
                       alert("账号密码错误");
                   }else{
                       alert("服务器忙");
                   }
                }
            }
        }
    </script>

JSON

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式

把java中的对象转换成js对象

优点:

  1. JSON 只允许使用UTF-8编码,不存在编码问题;
  2. JSON 只允许使用双引号作为key,特殊字符使用 \ 转义,格式简单;
  3. 浏览器内置JSON支持。如果把数据用JSON发生给浏览器,可以用JavaScript直接处理

json&jQuery封装

完整流程

Servlet接收客户端浏览器发来的数据,与数据库进行交互,用Gson对象的toJson()方法把对象转换成字符串并返回至前端js,前端js接收到字符串并用 . p a r s e J S O N ( r e s ) 把 字 符 串 转 换 成 j s 对 象 , 将 用 户 信 息 存 储 到 浏 览 器 s e s s i o n S t o r a g e 的 会 话 存 储 中 , 登 录 界 面 用 w i n d o w . s e s s i o n S t o r a g e . g e t I t e m ( " u s e r " ) 拿 到 浏 览 器 会 话 存 储 的 信 息 的 字 符 串 再 用 .parseJSON(res)把字符串转换成js 对象,将用户信息存储到浏览器sessionStorage的会话存储中,登录界面用window.sessionStorage.getItem("user")拿到浏览器会话存储的信息的字符串再用 .parseJSON(res)jssessionStoragewindow.sessionStorage.getItem("user").parseJSON(str)转换成对象后显示

import com.ffyc.webpro.dao.LoginDao;
import com.ffyc.webpro.model.User;
import com.google.gson.Gson;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class LoginServlet extends HttpServlet {

    /*
     登录处理
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter out = null;
        try {
            resp.setContentType("text/html;charset=utf-8");
            req.setCharacterEncoding("utf-8");//设置解码格式
            String account = req.getParameter("account");
            String password = req.getParameter("password");

            LoginDao loginDao = new LoginDao();
            User user = loginDao.checkLogin(account, password);
            out = resp.getWriter();
            //问题: 从服务器端向客户端要响应更多的数据.  现在响应 int  字符串
            //java程序一般将数据封装在对象中,响应到客户端,而客户端是javaScript语言,两边对象格式不一致
            //解决: 前面响应字符串,前端可以接收到. 那么在java中需要对 对象中的数据进行转换
            //     早期解决方案是将对象中的数据写入到xml文件中,将xml文件返回,这种语言比较麻烦
            // 现在诞生了一种轻量级的解决方案: json(javaScript对象表现形式) 是一种轻量级的数据格式,本质是字符串
            // 对象{键:值,键:值...}  集合:[{键:值,键:值...},{键:值,键:值...},{键:值,键:值...}.....]
            if (user != null) {
                Gson gson = new Gson();
                String s = gson.toJson(user);
                System.out.println(s);
                out.println(s);
            } else {
                out.println(1);
            }
        } catch (Exception e) {
            e.printStackTrace();
            out.println(2);
        }
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/jquery-1.8.3.min.js"></script>
    <script type="text/javascript">
        function subform() {
            //jquery封装的ajax请求, post表示post请求
            //$.post("login",{acccount:$("accountId").val(),password:$("#passwordId").val()});
            //$("#formId").serialize() 将表单数据序列化 为 键=值&键=值&键=值....
            //function(){ } 读取到响应内容后执行   type:json 直接将返回的json格式转为js对象
            // res 是一个json格式的字符串
            $.post("login", $("#formId").serialize(), function (res) {
                var obj = $.parseJSON(res);//json字符串转为js对象
                if (obj.id != null) {
                    alert("登录成功");
                    //将用户信息存储到浏览器sessionStorage的会话存储中
                    window.sessionStorage.setItem("user", res);
                    location.replace("success.html");
                } else if (res == 1) {
                    alert("账号或密码错误");
                } else {
                    alert("服务器忙");
                }
            });
        }
    </script>
</head>
<body>
<!--
 表单验证
-->
<form id="formId">
    账号<input type="text" name="account"> <br/>
    密码<input type="password" name="password"> <br/>
    <input type="button" value="登录" onclick="subform()">
</form>
<a href="register.html">注册</a>

</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/jquery-1.8.3.min.js" type="text/javascript"></script >
    <script type="text/javascript">
        $(function (){
            var str =  window.sessionStorage.getItem("user");//拿到的是json字符串
            var user = $.parseJSON(str);
            $("#accountId").html(user.id+":::"+user.account);
        })
    </script>
</head>
<body>
 登录成功<span id="accountId"></span>
</body>
</html>

session

? 后端为了知道是哪一账号操作,就需要使用session获取用户的信息

session会话:客户端浏览器与服务器交互的整个过程

session对象:在第一次向servlet发送请求时,在服务器端由服务器创建一个session对象,完成会话期间的管理

session实现会话机制
  1. 浏览器第一次请求(服务器没有id号),创建HttpSession对象,并将对象分配一个会话id号,并将id号响应给浏览器,浏览器就将id号存起来,之后每次向Servlet发送请求时,浏览器会在请求头中将id号向服务器端发送
  2. 浏览器第二次请求到服务器,服务器就会根据收到的id号查找对象的session对象使用
//获取服务器生成的session对象
HttpSession session = req.getSession();
//向session对象设置一组键值,登录成功后将用户信息存储到一个对象的session对象中.
session.setAttribute("user", user);

在这里插入图片描述

获取session

HttpSession session = req.getSession();
session.getId();		//获取session的id 
User user = (User)session.getAttribute("user");//通过前边setAttribute的键获取会话中user对象
//销毁浏览器
session.invalidate();
session生命周期

创建 :第一次访问servlet时,在服务器端创建

销毁:1、服务器关闭 2、会话对象长时间未使用 3、session.invalidate()

设置session会话时间

绝对时间(不管有没有会话):在web,xml中设置

<session-config> 
<session-timeout>50</session-timeout> //50分钟自动销毁
</session-config>

未使用销毁时间:session.setMaxInactiveInterval(60) //不使用60秒销毁

安全退出

用户退出时,销毁session

    /**
     * 安全退出,销毁服务器端的session
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        //销毁浏览器
        session.invalidate();
    }
function exit(){
            if(confirm("您确定要退出吗?")){
                //删除前端浏览器存储的用户信息
                window.sessionStorage.removeItem("user");
                //向服务器发送请求,销毁session
                $.get("index",function(res){
                    location.replace("index.html")
                });
            }
拦截未登录用户访问
        $(function (){
            //拿到json字符串
            var str = window.sessionStorage.getItem("user");
            //前端判断用户是否登录
            if(str==null){
                location.replace("login.html")
                return;
            }
            var user = $.parseJSON(str);
            $("#accountId").html(user.id+":::"+user.account);
        })

ServletContext

? 为了实现web程序中所有的Servlet数据交互,WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的

ServletContext对象,存储一些全局信息

生命周期:开始于服务器的启动,结束于服务器关闭

//servletContext对象全局共享
ServletContext servletContext = req.getServletContext();

getInitParameter(“name”)获得当前应用的初始化参数

setAttribute(“attrname”,value) 设置ServletContext属性并赋值

getAttribute(“attrname”) 获得ServletContext属性指定值

removeAttribute(“attrname”) 删除ServletContext指定属性

过滤器

? 过滤器位于客户端和web应用程序之间,用于检查和修改两者之间流过的请求

编码过滤器
import javax.servlet.*;
import java.io.IOException;

/**
 * 编码过滤器
 * @author Deevan
 */
public class EncodeFilter implements Filter {

    String code;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init");
        code = filterConfig.getInitParameter("encode");
    }

    //执行过滤代码
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
       servletRequest.setCharacterEncoding(code);
       //让请求继续向下执行,下一个目标可能是Servlet,也可能是下一个过滤器
       filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {
        System.out.println("destroy");
    }
}
 <!--编码过滤器配置-->
    <filter>
        <filter-name>encode</filter-name>
        <filter-class>com.ffyc.webpro.filter.EncodeFilter</filter-class>
        <!--把参数配置到配置文件中,用init中filterConfig.getInitParameter("encode")调用-->
        <init-param>
            <param-name>encode</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encode</filter-name>
        <!--哪一个请求能够进入这个过滤器-->
        <url-pattern>/back/*</url-pattern><!--路径中以back开头的才会进入过滤器,防止html请求-->
    </filter-mapping>
sessionID过滤器
import com.ffyc.webpro.model.User;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @author Deevan
 */
public class IsLoginFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //把ServletRequest向下转型为HttpServletRequest对象
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpSession session = httpServletRequest.getSession();
        User user = (User)session.getAttribute("user");
        if (user==null){
            PrintWriter out = servletResponse.getWriter();
            out.println(201);
        }else{
            filterChain.doFilter(servletRequest,servletResponse);
        }
    }
}
    <!--sessionID过滤器配置-->
    <filter>
        <filter-name>islogin</filter-name>
        <filter-class>com.ffyc.webpro.filter.IsLoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>islogin</filter-name>
        <url-pattern>/</url-pattern>
    </filter-mapping>
        //长时间未操作提示重新登录
        function save(){
            $.get("back/student",function (res){
                if(res==201){
                    alert("登录失效,请重新登录");
                    location.replace("login.html");
                }
            })
        }

监听器

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-10-06 12:04:30  更:2021-10-06 12:06:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 11:07:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码