Javaweb学习心得——跟着狂神也跟着学校老师一步一步悟

JavaWeb

  • PHP开发速度很快,功能很强大,跨平台,代码很简单

    • 无法承载大访问量的情况
  • JSP/Servlet:

    • B/S:浏览器和服务器

    • C/S:客户端和服务器

    • 基于java语言

    • 可以承载 三高问题:高并发,高可用,高性能

web服务器

  • Tomcat…

    服务器是一种被动的操作,用于处理用户的一些请求和给用户一些响应

Tomcat的配置

下载9的版本

  • bin:启动关闭的脚本文件
  • conf:配置文件
  • lib:依赖的jar包
  • logs:日志
  • temp:tomcat运行时临时文件存放处
  • webapps:存放网站

启动和关闭Tomcat

环境配置好后cmd中输入startup

打开根目录cmd 输入startup

检测网站:localhost:8080

更改Tomcat的端口号

位于conf文件夹中的server.xml文件中

Connector port=“”

所以server.xml是服务器必要配置

  • 可以配置端口
  • 可以配置主机名HOST name但是需要在系统的driver中更改文件
  • Tomcat默认端口号8080
  • 默认主机名为:localhost->127.0.0.1
  • mysql:3306
  • http:80
  • https:443

网站时如何进行访问的

  1. 输入一个域名,回车
  2. 检查本机的host配置文件中是否存在域名映射
    1. 有:直接返回对应的ip地址,这个网址中,有我们需要访问的web程序

​ 2.没有:去 DNS服务器找,找到返回,找不到返回找不到

发布一个web网站

将自己写的网站,放到服务器中指定的web应用的文件夹(webapps)下,就可以访问网站应该有的结构了

--webapps:Tomcat服务器的web目录
	-ROOT
	-wuhu:网站的目录名
		-WEB-INF
			-classes:java程序
			-lib:web应用所依赖的jar包
			-web.xml:网站配置
		-index.html 默认的首页
		-static
			-css
			-style.css
			-js
			-img
		-....

Http

http是什么

​ 超文本传输协议(Hyper Text Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII形式给出;而消息内容则具有一个类似MIME的格式。这个简单模型是早期Web成功的有功之臣,因为它使开发和部署非常地直截了当

  • 文本:html,字符串…
  • 超文本:图片,音乐,视频,定位,地图…
  • 默认端口:80
  • https:443

两个时代

  • http1.0
    • 客户端可以与web服务器连接后,只能获得一个web资源,断开连接
  • http2
    • 可以获取多个web资源

http 请求与响应

  • 客户端 — 发送请求 —服务器

    Request URL :https : / / www. baidu .com/请求地址Request Method :GET
    get方法/post方法
    status code : 200 oK
    状态码: 200
    Remote《远程》Address : 14.215.177.39:443
    Accept:text/htm1
    Accept-Encoding:gzip, deflate, br
    Accept-Language : zh-CN , zh ; q=o.9语言cache-contro7:max-age=o
    connection :keep-alive
    
  • 服务器 — 响应 — 客户端

cache-contro7 : private
缓存控制
connection : Keep-A7ive
连接
content-Encoding:gzip
编码
content-Type :text/html类型
  • 请求行

    请求行中的请求方式:GET
    请求方式:Get,Post,HEAD,DELETE,PUT,TRACT...
    
    • get:请求能够携带的参数比较小,大小有限制,会在浏览器的URL栏显示数据内容,不安全,但是高效
    • post:请求能够携带的参数没有限制,会在浏览器的URL栏显示数据内容,安全,但是不高效
  • 消息头

    Accept:告诉浏览器,它所支持的数据芙型
    Accept-Encoding:支持哪种编码格式GBKUTF-8 GB2312 ISo8859-1Accept-Language:告诉浏览器,它的语言环地
    cache-control:级存控制
    connection:告诉浏览器,请求完成是断开还是保持连接
    HOST:主机
    
  • 响应头

200:请求响应成功
3XX∶请求重定向
重定向:你重新到我给你新位苦去
404:找不到资源
5XX:服务器代码错误
502:网关错误

常见面试题:

当你的浏览器中地址栏输入地址并回车的一瞬间到页面能够展示回来经历了什么?


Maven

why

  1. 在JavaWeb开发中,需要使用大量的jar包,我们需要手动导入

  2. 如何能够让一个东西自动帮我导入和配置这个jar包

    由此Maven诞生了

Maven项目架构管理工具

我们目前用来就是方便导入jar包的

Maven的核心思想:约定大于配置

  • 有约束,不要去违反

Maven会规定你改如何编写我们的Java代码,必须要按照这个规范来

下载Maven

配置环境变量

添加一个

M2_HOME :路径是到maven的bin目录

MAVEN_HOME:maven目录

改为阿里云镜像
  • mirrors
    • 作用:代理下载
本地仓库

在本地的仓库,远程仓库;

建立一个本地仓库 :localRepository

IDEA中使用Maven

  1. 启动IDEA

  2. 创建一个Maven项目

  3. 选择 maven -archetype -webapp

  4. 注意更改本地仓库,本地的maven的路径

    IDEA中在设置中搜索Maven查看路径是否该改变

  • 创建一个普通的maven项目
    • 不选勾就行了

IDEA中配置TOMCAT

运行中找到TOMCAT服务器选择本地

随后设置Tomcat的路径

然后在运行前点击绿色的加号选择创建一个新的

Artifacts

随后启动tomcat

解决问题

  1. Maven无法导入东西:JDK不对
  2. Tomcat闪退:在startup中最后添加一个pause暂停查看报错
  3. IDEA中每次都配置Maven:去全局设置中 配置
  4. Maven Tomcat无法配置

Servlet

Servlet说明

  • Servlet就是sun 开发动态Web的一门技术
  • 提供了一个接口叫做Servlet,如果想开发Servlet程序
    • 编写一个类,实现Servlet接口
    • 把开发好的Java类部署到Web服务器中

实现了Servlet接口的Java程序叫做,Servlet

HelloServlet

  • 创建一个新的maven项目

  • 删除src以后的学习就只在这个项目里面建立Moudel,这个空的工程就是maven的主程序

  • 关于Maven父子工程的理解

  •     <modules>
            <module>Javea_Servlet_son</module>
        </modules>
            在父项目中会多这个
          <parent>
        <artifactId>Java-web01_HelloServlet</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
      </parent>
            在子项目中会出现parent
    
  • 父项目中的java子项目可以直接使用

son extends fa

Maven 环境优化

  1. 修改web.xml为最新的
  2. 将maven的结构搭建完整(java 和 resources)

编写一个servlet程序

  1. 在java中创建包
  2. 包里面创建类并且编写
  3. 实现一个Servlet接口(有两个默认的实现类)
  4. 继承 HttpServlet类 的 GenericServlet 的 Servlet接口既我们只需要继承GenericServlet 就可以了
public class Hello extends HttpServlet {
    //由于get或者post只是请求实现的不等同方式可以相互调用,业务逻辑都一样
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //        ServletOutputStream outputStream = resp.getOutputStream();
        PrintWriter writer = resp.getWriter();
        writer.println("Hello Servlet");
        //有输入就有输出(输出流输入流)
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
        
    }
}
  1. 编写Servlet的映射

    为什么需要,我们写的是JAVA程序,需要web中注册我们写的Servlet,还需要给他一个浏览器能够访问的路径

    <!--    注册Servlet-->
        <servlet>
    <!--        这里是网页的名字-->
            <servlet-name>hello</servlet-name>
    <!--        这里是路径-->
            <servlet-class>com.wuhu.servlet.Hello</servlet-class>
        </servlet>
    <!--    Servlet的请求路径-->
        <servlet-mapping>
            <servlet-name>hello</servlet-name>
    <!--        注意这里是/hello  所以访问到的网页就是localhost:8080/hello 就是我们写的这个 -->
            <url-pattern>/hello</url-pattern>
        </servlet-mapping>
    
  2. 配置Tomcat

    注意项目配置的路径就行了

  3. 启动测试

Servlet原理

Servlet是由Web服务器调用,web收到浏览器请求后会:

得到响应,去访问我们所写的类中得到请求,然后返回到web容器中然后反映给浏览器

自定义后缀的设置 

        <url-pattern>*.wuhu</url-pattern>
        访问到对应的类都是需要加入   .wuhu才能进入
其中*前面不能加/
  1. 优先级问题
指定了固有的映射路径,优先级最高(反而*这个是默认路径就是最后才会去访问)

ServletContext

web容器在启动的时候,它会每个web创建一个对应的ServletContext对象,代表当前的web应用

  • 共享数据

    我在这个Servlet中保存的数据可以在另一个servlet中获取

       ServletContext context = this.getServletContext();
       String username = "wuhu";
       context.setAttribute("username",username);
先set存然后
       ServletContext context = this.getServletContext();
       String  username = (String) context.getAttribute("username");
       resp.getWriter().println("name"+username);
然后get才能读取到context中装载的信息

读取资源文件

HttpServletResponse 响应

针对web的请求,分别创建一个HttpServletRequest对象,代表响应一个

  • 如果获取客户端传过来的参数:HttpServletRequest
  • 如果响应客户端传过来的参数: HttpServletResponse
  1. 负责向浏览器发送数据的方法

    • ServletOutputStream getOutputStream() throws IOException;
      PrintWriter getWriter() throws IOException;
      

      负责向浏览器发出响应头的方法

          void setCharacterEncoding(String var1);
      
          void setContentLength(int var1);
      
          void setContentLengthLong(long var1);
      
          void setDateHeader(String var1, long var2);
      
          void addDateHeader(String var1, long var2);
      
          void setHeader(String var1, String var2);
      
          void addHeader(String var1, String var2);
      
          void setIntHeader(String var1, int var2);
      
          void addIntHeader(String var1, int var2);
      
          int SC_CONTINUE = 100;
          int SC_SWITCHING_PROTOCOLS = 101;
          int SC_OK = 200;
          int SC_CREATED = 201;
          int SC_ACCEPTED = 202;
          int SC_NON_AUTHORITATIVE_INFORMATION = 203;
          int SC_NO_CONTENT = 204;
          int SC_RESET_CONTENT = 205;
          int SC_PARTIAL_CONTENT = 206;
          int SC_MULTIPLE_CHOICES = 300;
          int SC_MOVED_PERMANENTLY = 301;
          int SC_MOVED_TEMPORARILY = 302;
          int SC_FOUND = 302;
          int SC_SEE_OTHER = 303;
          int SC_NOT_MODIFIED = 304;
          int SC_USE_PROXY = 305;
          int SC_TEMPORARY_REDIRECT = 307;
          int SC_BAD_REQUEST = 400;
          int SC_UNAUTHORIZED = 401;
          int SC_PAYMENT_REQUIRED = 402;
          int SC_FORBIDDEN = 403;
          int SC_NOT_FOUND = 404;
          int SC_METHOD_NOT_ALLOWED = 405;
          int SC_NOT_ACCEPTABLE = 406;
          int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
          int SC_REQUEST_TIMEOUT = 408;
          int SC_CONFLICT = 409;
          int SC_GONE = 410;
          int SC_LENGTH_REQUIRED = 411;
          int SC_PRECONDITION_FAILED = 412;
          int SC_REQUEST_ENTITY_TOO_LARGE = 413;
          int SC_REQUEST_URI_TOO_LONG = 414;
          int SC_UNSUPPORTED_MEDIA_TYPE = 415;
          int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
          int SC_EXPECTATION_FAILED = 417;
          int SC_INTERNAL_SERVER_ERROR = 500;
          int SC_NOT_IMPLEMENTED = 501;
          int SC_BAD_GATEWAY = 502;
          int SC_SERVICE_UNAVAILABLE = 503;
          int SC_GATEWAY_TIMEOUT = 504;
          int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
      

      一些常量

  • 向浏览器输出消息
  • 下载文件
    1. 获取下载路径
    2. 下载文件名是啥
    3. 让浏览器能够支持下载我们需要的东西
    4. 获取下载文件的输入流
    5. 创建缓冲区域
    6. 获取outputstream对象
    7. 将fileoutputstream流写入buffer缓冲区
    8. 使用outputstream 将缓冲区中的数据输出到客户端

代码:

package com.aoli.servlet;


import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class fillservelet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        1.  获取下载路径
        String realPath = this.getServletContext().getRealPath("/english.txt");
        System.out.println("获取要下载的路径:"+realPath);

//        2. 下载文件名是啥
        String fillName = realPath.substring(realPath.lastIndexOf("\\") + 1);
//        3. 让浏览器能够支持下载我们需要的东西
        resp.setHeader("content-disposition","attachment;filename="+fillName);
        //获取web下载文件的头content-disposition,ttachment;filename=附件名字
//        4. 获取下载文件的输入流
        FileInputStream in = new FileInputStream(realPath);
//        5. 创建缓冲区域
        int len = 0;
        byte[] buffer = new byte[1024];
//        6. 获取outputstream对象
        ServletOutputStream out = resp.getOutputStream();

//        7. 将fileoutputstream流写入buffer缓冲区
        while ((len = in.read(buffer)) != -1) {
            out.write(buffer, 0, len);
        }
        in.close();
        out.close();
//        8. 使用outputstream 将缓冲区中的数据输出到客户端
    }
}

  • 验证码功能
    • 验证码怎么来
      • 前端实现
      • 后端实现,java的图片类,生成一个图片
 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//如何让浏览器5秒刷新一次
        resp.setHeader("refresh","3");
        //在呢村中创建一个图片
        BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
        //得到图片
        Graphics g =(Graphics2D) image.getGraphics();//就和画画差不多 g就是我们设置的画笔
        //设计图片的背景颜色
        g.setColor(Color.WHITE);//白色背景
        g.fillRect(0,0,80,20);//填充矩形
        //给图片写数据
        g.setColor(Color.blue);//设置颜色
        g.setFont(new Font(null,Font.BOLD,20));//设置字体
        g.drawString(makeNum(),0,20);//写字
        //告诉浏览器,这个请求图片的方式打开
        resp.setContentType("image/jpeg");

        //网站存在缓存,不让浏览器缓存
        resp.setDateHeader("expries",-1);
        //expries缓存控制
        resp.setHeader("Cache-Control","no-cache");
        resp.setHeader("Pragma","no-cache");
        //把图片写给浏览器
        ImageIO.write(image,"jpeg",resp.getOutputStream());//image io流写入


    }
    //生成随机数
    private String makeNum(){
        Random random = new Random();
        String num = random.nextInt(9999999)+"";
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 7-num.length(); i++) {
            sb.append("0");//用0填充使其能够到达7位
        }
        num = sb.toString() + num;
        return num;


    }
  1. 定时刷新:resp.setHeader(“refresh”,“时间”)
  2. 内存中创建一个图片:BufferedImage new出来,需要配置的参数 宽 高 颜色

response重定向

重定向和转发的区别

  • 相同点
    • 页面都会实现跳转
  • 不同点
    • 请求转发的时候url不会变化
    • 重定向的时候url会发生变化

常见场景

  • 用户登录
<%--这里使用jsp的请求寻找路径文件,找到这个验证码--%>
<%--使用jps ${}/设置的serlvet的类名   --%>
<form action="${pageContext.request.contextPath}/image" method="get">
    用户名:<input type="text" name="username" placeholder="用户名"/><br/>
    密码:<input type="text" name="password" placeholder="密码"/><br/>
    <input type="submit" value="提交"/>
</form>
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        this.getInitParameter()   初始化参数
//        this.getServletConfig()   Servlet配置
//        this.getServletContext()  Servlet上下文

        System.out.println("芜湖,我进来咯");
        PrintWriter writer = resp.getWriter();
        writer.println("<h1>wuhu</h1>");
        ServletContext context = this.getServletContext();
        String username = "wuhu";
        context.setAttribute("username",username);

        Properties properties = new Properties();
        resp.sendRedirect("/servlet_02_war/image");
    }
这里需要注意

我们看得到的是 ${} 这里我们可以获得(类似于getArrtribute(“”)的功能)

还可以获取网页路径常用于表单的提交

${pageContext.request.contextPath}/(servlet设置的引索如下)

 <url-pattern>/req</url-pattern>
${pageContext.request.contextPath}/req

HttpServletRequest 请求

代表客户端的请求,用户通过http协议访问服务器 ,请求中的所有信息会被封装到这里

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RANpSzsK-1657027797887)(C:\Users\hj\AppData\Roaming\Typora\typora-user-images\image-20220501144923322.png)]

常用的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ueGyWxpo-1657027797887)(C:\Users\hj\AppData\Roaming\Typora\typora-user-images\image-20220501145017868.png)]

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String[] hobbys = req.getParameterValues("hobby");
        System.out.println("==========================");
        System.out.println(username);
        System.out.println(password);
        System.out.println(Arrays.toString(hobbys));
        System.out.println("==========================");

        resp.sendRedirect("success.jsp");

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);

    }

获取参数并且请求转发

重定向和转发的区别

  • 相同点
    • 页面都会实现跳转
  • 不同点
    • 请求转发的时候 url不会变化 307
    • 重定向的时候 url会发生变化 302

Session

Cookic

JSP HTML

过滤器

三层架构

dao(数据库)

service(服务层)

servlet(控制层)

Cookie 、Session

会话

Session

有状态的会话:有交互式的

  • 服务器技术,利用这个技术可以保存用户绘画星系
Cookie
  • 客户端技术(响应,请求)

一般应用,记住密码和用户名

JSP基础语法

jsp作为java中的应用有一些自己的扩充语法了解即可

java的所有语法jsp都支持

jsp表达式(之前的笔记有这里就不写了)

<%
%>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xp8kJ3t5-1657027797888)(C:\Users\hj\AppData\Roaming\Typora\typora-user-images\image-20220502201606241.png)]

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


<html>
<body>
    <%
    for (int i = 0; i < 10; i++)
    {%>
        <h1>Hello World! <%=i%></h1>
<%}
%>


</body>
</html>

上面那个图的代码

JSP JSTL EL标签

JSTL一般用于我们的表单

EL表达式:${}

  • 获取数据
  • 执行预算
  • 获取web开发的常用对线

JDBC简单实用

jdbc的简单连接数据库

package com.jdbc_te;

import java.sql.*;



//jdbc简单的使用
/*
* 1.写入初始化数据库的url,username,password
* 2.加载驱动Class.forName("com.mysql.jdbc.Driver");
* 3.连接数据库Connection connection = DriverManager.getConnection(url, username, password);
* 4.向数据库发送sql的对象statement : CRUD Statement statement = connection.createStatement();
* 5.发送 ResultSet resultSet = statement.executeQuery(sql);
* 6.先开的链接后关闭
*
*       resultSet.close();
        statement.close();
        connection.close();
*
* */

public class jdbc_ {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
//        配置信息
        String url = "jdbc:mysql://localhost:3306/id?useSSL=false&useUnicode=true&characterEncoding=utf-8";
        String username = "root";
        String  password = "123456789ww";

//        加载 驱动
        Class.forName("com.mysql.jdbc.Driver");
//        连接数据库 代表数据库
        Connection connection = DriverManager.getConnection(url, username, password);
        
        //向数据库发送sql的对象statement : CRUD
        Statement statement = connection.createStatement();
        String  sql ="select * from id";
//         预编译
//        PreparedStatement preparedStatement = connection.prepareStatement(sql);
//         编写sql
//        执行sql 返回一个ResultSet 结果集
        ResultSet resultSet = statement.executeQuery(sql);

        while (resultSet.next()){
            System.out.println("id=" +resultSet.getObject("usename"));
            System.out.println("password=" +resultSet.getObject("password"));
        }

//      关闭sql 施放资源
        resultSet.close();
        statement.close();
        connection.close();
    }
}
jdbc流程操作
  • 1.写入初始化数据库的url,username,password
  • 2.加载驱动Class.forName(“com.mysql.jdbc.Driver”);
  • 3.连接数据库Connection connection = DriverManager.getConnection(url, username, password);
  • 4.向数据库发送sql的对象statement : CRUD Statement statement = connection.createStatement();
  • 5.发送 ResultSet resultSet = statement.executeQuery(sql);
  • 6.先开的链接后关闭
  • resultSet.close();
    statement.close();
    connection.close();
简单的其他操作

一般的我们使用预处理

PreparedStatement preparedStatement = connection.prepareStatement(sql)

增添删除修改都是用executeUpdate()

开启事务 以及juint的使用

导入依赖

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

再类中使用加入

@Test即可

public class jdbc_2 {
    @Test
    public void text(){
        System.out.println("hello");
    }
}

可以运行(单元测试)

总结

学到这里自己做了一个项目

知道了JDBC我们的话最好还是用那个啥properties的文件装起来方便我们的调用,除此之外我们需要封装(使用properties是方便我们加载jdbc的常用东西就不糅杂)

 static {
//        类加载器
        Properties properties = new Properties();

        InputStream is = dao.class.getClassLoader().getResourceAsStream("db.properties");
        try {
            properties.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        driver = properties.getProperty("driverClass");
        url = properties.getProperty("url");
        username = properties.getProperty("username");
        password = properties.getProperty("password");
    }
  • 公共连接类
  • 公共查询类
  • 公共修改类
  • 公共释放类

对标数据库我们需要对其进行一个对标码的创建封装成一个结构体

这个结构体的作用只是用于set和get对属性的设置个得到

对于类似登录的操作我们需要封装的是

创建一个接口,登录的接口我们需要传递连接和我们的账户去查看是否核对

    
控制层
public User getLoinUser(Connection connection,String userCode) throws SQLException;

需要创建一个业务层

    public User lofin(String usercode,String password);

通过业务层去调用控制层到时候调用的时候直接调用业务层,直接调用两个语句就可以查询到是否有返回值,所以需要有封装的思想

对于servlet我们要知道只有提交我们才回去做的,所以我们需要关注的是数据转发和网页重定向这个问题,转发就顾名思义我从上一个网页的数据能够在下一个网页中运用,这里需要用到ServletContext封装转发因为内置容器时面向所有网页的

将文件夹各个层级分清楚,业务层,控制层,视图层,HTML,CSS,JS

当然不要忘记配置我们web.xml中我们需要设置的东西

对于filter过滤器我的感受就是时刻监听立即释放就是这个样可能理解不怎么对但是我觉得是这样

对于分页查找,我们需要明白如何分页如何加载后面的删除和修改功能,

也是按照前面的标准也存在业务控制和视图层

最后的最后就是不要觉得封装很麻烦,封装都是体现高集成高聚集低耦合的一个过程,在写完封装的时候你去调用你会感谢自己写完了封装,就这样!!!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

艾米莉亚小汉堡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值