08__Servlet

servlet

1. servlet的入门

1.1 什么是servlet
(1)servlet 是运行在 Web 服务器中的小型 Java 程序。
(2)servlet 通常通过 HTTP(超文本传输协议)接收和响应来自 Web 客户端的请求。
1.2 实现servlet(完成1或2只能说是一个普通的java程序,只有完成3才能让服务器知道这是一个servlet)
(1)实现Servlet接口
* 如果实现接口,需要把接口里面的方法都实现
(2)继承GenericServlet, HttpServlet类
* 如果继承类,不需要把类中的方法都实现
(3)需要web服务器知道java程序不是一个普通的java程序,而是一个servlet
* 通过配置进行操作
* 在web项目中,web.xml里面进行配置
1.3 servlet的入门程序
(1)写一个servlet,实现向页面输出内容 hello servlet
(2)步骤
第一步,创建一个类,使用这个类继承GenericServlet类
第二步,实现类里面的 service(ServletRequest req, ServletResponse res)
* ServletRequest代表请求
* ServletResponse代表响应
第三步,使用ServletResponse向页面输出内容 getWriter()
第四步,在web项目中的web.xml进行配置,让服务器知道是一个servlet

<servlet>
	<servlet-name>servletDemo1</servlet-name>(可以随便取个名字)
	<servlet-class>cn.itcast.servlet.ServletDemo1</servlet-class>(包类路径)
</servlet>
<servlet-mapping>
	<servlet-name>servletDemo1</servlet-name>(同上面的servlet-name名字一致)
	<url-pattern>/hello</url-pattern>(访问路径)
</servlet-mapping>

package cn.itcast.servlet;
import java.io.IOException;
import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class ServletDemo1 extends GenericServlet {
	@Override
	public void service(ServletRequest req, ServletResponse resp)
			throws ServletException, IOException {
		// 向页面输出内容
		resp.getWriter().write("hello servlet");
	}
}

2. servlet的执行过程(画图分析执行过程)

2.1 执行过程
(1)根据在浏览器地址栏输入的地址,找web.xml中相同的url-pattern
(2)找到了url-pattern,找他对应的servlet-name
(3)根据找到的servlet-name到另外一个标签里面(servlet)相同名称的servlet-name
(4)在servlet标签里面找到了相同名称的servlet-name,找servlet的包类路径servlet-class
利用反射原理,让servlet里面的service方法执行
在这里插入图片描述

3. servlet的生命周期

3.1 什么是生命周期:一个人从出生到死亡
3.2 servlet的生命周期:从servlet创建到servlet销毁的过程
3.3 在servlet接口里面有五个方法,其中有三个方法是与生命周期相关的方法
(1)init方法,在servlet创建时候执行这个方法,执行一次,servlet在第一次访问时候创建
(2)service方法,在每次访问servlet时候会执行这个方法,执行多次
(3)destroy方法,销毁servlet时候执行这个方法,执行一次

package cn.itcast.servlet;
import java.io.IOException;
import javax.servlet.GenericServlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class ServletDemo2 extends GenericServlet {
	/*
	 * 1、servlet在什么时候创建?
	 * 在服务器启动的时候servlet不会创建,在第一次访问的时候创建.
	 * 2、创建几次?
	 * 创建一次.
	 * */
	@Override
	public void init(ServletConfig config) throws ServletException {
		System.out.println("init............");
	}

	/*
	 * 1、在什么时候执行service方法?
	 * 每次访问servlet的时候都会执行.
	 * 2、执行几次?
	 * 执行多次.
	 */
	@Override
	public void service(ServletRequest arg0, ServletResponse arg1)
			throws ServletException, IOException {
		System.out.println("service...............");
	}

	/*
	 * 1、在什么时候执行destroy方法?
	 * 在servlet销毁时候执行
	 * 2、执行几次?
	 * 执行一次
	 * */
	@Override
	public void destroy() {
		System.out.println("destory............");
	}
}

4. servlet开发细节的问题

4.1 HttpServletRequest和ServletRequest关系(子父接口之间的关系)
HttpServletResponse和ServletResponse关系
(1)ServletRequest和ServletResponse不带协议
HttpServletRequest和HttpServletResponse带协议
(2)sun公司设计时候,认为未来互联网的发展有很多的协议,目前只是http协议
4.2 在GenericServlet类里面有init没有参数的方法和init有参数的方法的关系
(1)有参数init方法最终也要调用init没有参数的方法,直接使用init没有参数的方法就可以了
4.3 在HttpServlet类里面service方法和doxxx方法关系
(1)根据提交的方式,调用不同的doXX的方法
比如提交方式是get,调用doGet方法;比如提交方式是post,调用doPost方法
(2)一般在开发中,直接写doGet和doPost方法就可以了
(3)一般在创建servlet时候,直接继承HttpServlet实现servlet
(4)创建servlet的时候有简单的方法,右键New->Servlet(重写的方法一般只要doGet和doPost)
4.4 如何在服务器启动时候创建servlet
(1)通过配置文件进行配置,在servlet标签里面写标签
* <load-on-startup>正整数的值(大于1)</load-on-startup>
4.5 简化编程
(1)当通过get提交方式时候,实现从1加到100
当通过post提交方式时候,实现从1加到100
(2)无论什么提交方式,代码都能执行到
* 在dopost方法里面调用doget方法

package cn.itcast.config;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ConfigDemo extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		int sum = 0;
		for(int i = 0; i < 100; i++) {
			sum += i;
		}
		System.out.println(sum);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}

5. url-pattern的配置

5.1 配置有三种方式
第一种方式:完全路径匹配
(1)写法 : /aa /hello
第二种方式:目录匹配
(1)写法: /aa/*
第三种方式:扩展名匹配
(1)写法: *.do *.action
5.2 优先级
完全路径匹配 > 目录匹配 > 扩展名匹配
5.3 练习

对于如下的一些映射关系:
Servlet1 映射到 /abc/*
Servlet2 映射到 /*
Servlet3 映射到 /abc
Servlet4 映射到 *.do
问题:
1.当请求URL为"/abc/a.html"时,"/abc/*"和"/*"都匹配,哪个servlet响应?
	Servlet1
2.当请求URL为"/abc","/abc/*"和"/abc"都匹配,哪个servlet响应?
	Servlet3 
3.当请求URL为"/abc/a.do"时,"/abc/*"和"*.do"都匹配,哪个servlet响应?
	Servlet1
4.当请求URL为"/a.do"时,"/*"和"/*.do"都匹配,哪个servlet响应?
	Servlet2
5.当请求URL为"/xxx/yyy/a.do"时,"/*"和"*.do"都匹配,哪个servlet响应?
	Servlet2

6. 开发中路径的问题

6.1 相对路径
(1)在html文件中引入图片
(2)有三种情况
第一种:图片和html在同一个目录下面
* 直接写图片的名称<img src="a.jpg"/>
第二种:图片在html的上层目录
* 写 …/ 表示上层目录<img src="../b.jpg"/>
第三种:图片在html的下层目录
* 直接写目录名称和图片名称<img src="cc/c.jpg"/>
6.2 绝对路径(一般开发中都使用)
(1)第一种写法:http://ip地址+端口号/文件的路径
* 文件的路径:部署到Tomcat中webapps下的文件路径
* <img src="http://127.0.0.1/day07-3/path02/a.jpg"/>
(2)第二种写法:直接写/文件的路径
* <img src="/day07-3/path02/a.jpg"/>

7. 重定向和转发

7.1 重定向
(1)使用的是客户端路径
(2)重定向请求两次,使用的是客户端路径,携带项目名称 ,比如 /day07/demo3
在这里插入图片描述
7.2 转发
(1)使用的是服务端路径
(2)转发请求一次,使用的是服务器端路径,不需要携带项目名称 , 比如 /demo4
在这里插入图片描述

8. ServletConfig对象

8.0 创建ServletConfig对象
(1)直接使用方法创建对象 getServletConfig()
8.1 得到当前运行的servlet的名称
(1)web.xml中<servlet><servlet-name>ConfigDemo1</servlet-name></servlet>
(2)String getServletName()

//创建servletconfig对象
ServletConfig config = getServletConfig();
//得到当前运行的servlet名称
String name = config.getServletName();
System.out.println(name);

8.2 创建(得到)servletContext对象
(1)ServletContext getServletContext()
(2)一般都使用 getServletContext()方法
8.3 获取初始化参数
(1)在web.xml中进行配置初始化参数。
配置方法:在servlet标签里面进行配置。

  <servlet>
    <description>This is the description of my J2EE component</description>
    <display-name>This is the display name of my J2EE component</display-name>
    <servlet-name>ConfigDemo2</servlet-name>
    <servlet-class>cn.itcast.config.ConfigDemo2</servlet-class>
    <init-param>
    	<param-name>username</param-name>
    	<param-value>root</param-value>
    </init-param>
    <init-param>
    	<param-name>password</param-name>
    	<param-value>123456</param-value>
    </init-param>
  </servlet>

(2)getInitParameter和getInitParameterNames
String getInitParameter(String name) :根据名称得到值(参数是初始化参数名称)
* 代码

//得到servletconfig对象
ServletConfig config = getServletConfig();
//getInitParameter(String name)
String username = config.getInitParameter("username");
String password = config.getInitParameter("password");

Enumeration getInitParameterNames() :得到所有的初始化参数的名称
* 代码

//得到servletconfig对象
ServletConfig config = getServletConfig();
//得到所有的初始化参数名称
Enumeration<String> enumrEnumeration = config.getInitParameterNames();
//得到每个参数的名称
while(enumrEnumeration.hasMoreElements()) {
	String name = enumrEnumeration.nextElement();
	//根据name得到值
	String value = config.getInitParameter(name);
	System.out.println(name+" :: "+value);
}

9. ServletContext对象

9.1 创建ServletContext对象
(1)第一种方式,使用ServletConfig对象里面的方法 getServletContext()
(2)第二种方式,直接使用 getServletContext()
9.2 获取全局的初始化参数
(1)配置全局初始化参数

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <display-name></display-name>	
  <context-param>
  	<param-name>url</param-name>
  	<param-value>localhost</param-value>
  </context-param>
  <context-param>
  	<param-name>name</param-name>
  	<param-value>zhangsan</param-value>
  </context-param>
  <servlet>
    <description>This is the description of my J2EE component</description>
    <display-name>This is the display name of my J2EE component</display-name>
    <servlet-name>ContextDemo1</servlet-name>
    <servlet-class>cn.itcast.context.ContextDemo1</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>ContextDemo1</servlet-name>
    <url-pattern>/demo1</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

(2)getInitParameter和getInitParameterNames
String getInitParameter(String name) :根据名称得到全局初始化参数的值
* 代码

//得到servletContext对象
ServletContext context = getServletContext();
//根据名称得到全局初始化参数的值
String url = context.getInitParameter("url");
String name = context.getInitParameter("name");

Enumeration getInitParameterNames() :得到所有的全局初始化参数的名称
* 代码

//得到servletContext对象
ServletContext context = getServletContext();
//使用方法得到所有的全局初始化参数的名称
Enumeration<String> enumrEnumeration = context.getInitParameterNames();
//得到每个全局初始化参数的名称
while(enumrEnumeration.hasMoreElements()) {
	String name = enumrEnumeration.nextElement();
	String value = context.getInitParameter(name);
	System.out.println(name+" :: "+value);
}

9.3 在启动tomcat服务器时候,会为每个项目创建一个servletContext对象。
在这个项目里面如果通过servlet1向servletContext里面设置一个值,在这个项目里面的其他的servlet里面可以的这个值
(1)servletContext域对象:在一定的范围内,存值和取值,范围是整个web项目
(2)存值:setAttribute(String name, Object object)
(3)取值:getAttribute(String name)
(4)首先创建servlet1,通过servlet1向servletContext里面设置一个值
其次,再创建servlet2,在servlet2获取通过servlet1设置的值

10. 练习:统计网站的访问次数

10.1 创建一个servlet,每次访问这个servlet计算一次访问

package cn.itcast.count;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * 统计网站访问次数
 */
public class CountServlet extends HttpServlet {
	
	@Override
	public void init() throws ServletException {
		// 得到servletContext对象
		ServletContext context = getServletContext();
		//初始值
		context.setAttribute("num", 0);
	}
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//首先把servletContext里面的值取出来 +1 放回去
		// 得到servletContext对象
		ServletContext context = getServletContext();
		//获取值
		int num = (Integer) context.getAttribute("num");
		//把获取的值+1 ,放回去
		context.setAttribute("num", num+1);
		response.getWriter().write("welcome");
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}

package cn.itcast.count;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ShowServlet extends HttpServlet {
	/**
	 * 显示访问的次数
	 */
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 得到servletContext对象
		ServletContext context = getServletContext();
		//获取值
		int num = (Integer) context.getAttribute("num");
		response.getWriter().write("time: "+num);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}

10.2 实现的步骤(分析图)
在这里插入图片描述

11. 使用servletContext对象获取web项目中的资源

11.1 使用传统方式获取web项目中的文件
(1)创建web项目,创建properties文件
(2)得到要操作文件的输入流,使用相对路径
* classes/db1.properties : 相对路径
* 相对虚拟机的位置
* 在web项目中,虚拟机在tomcat启动时候,tomcat在bin里面
(3)使用传统方式里面的相对路径,不能读取web项目中的文件
11.2 使用servletContext对象读取web项目中的文件
(1)InputStream getResourceAsStream(java.lang.String path) :得到要操作文件的输入流
第一个操作:文件放到src下面
= 路径:第一个位置 /,理解为项目的名称;后面写文件在tomcat的webapps里面的具体的路径
= 代码
//路径:第一个位置 /,理解为项目的名称;后面写文件在tomcat的webapps里面的具体的路径
InputStream in = context.getResourceAsStream("/WEB-INF/classes/db1.properties");

第二个操作:文件放到包里面
= 路径:第一个位置 /,理解为项目的名称;后面写文件在tomcat的webapps里面的具体的路径
= 代码
//路径:第一个位置 /,理解为项目的名称;后面写文件在tomcat的webapps里面的具体的路径
InputStream in = context.getResourceAsStream("/WEB-INF/classes/cn/itcast/read/db2.properties");

第三个操作:文件放到webroot下面
= 路径:第一个位置 /,理解为项目的名称;后面写文件在tomcat的webroot里面的具体的路径
= 代码:
//路径:第一个位置 /,理解为项目的名称;后面写文件在tomcat的webroot里面的具体的路径
InputStream in = context.getResourceAsStream("/db3.properties");

* 注意:当把文件放到和webroot同级的目录下面,这个文件不会部署到tomcat里面,
所以使用servletContext对里面getResourceAsStream方法不能得到文件的内容
package cn.itcast.read;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletDemo2 extends HttpServlet {

	/**
	 * 使用servletContext对象里面
	 * getResourceAsStream(java.lang.String path) :得到要操作文件的输入流
	 */
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		test3();
	}

	//读取webroot下面properties格式文件的方法
	public void test3() throws IOException {
		//创建对象
		Properties p = new Properties();
		//得到servletContext对象
		ServletContext context = getServletContext();
		//得到要操作文件的输入流
		//路径:第一个位置 / 理解为项目名称;后面写文件在tomcat的webapps下面的具体的路径
		InputStream in = context.getResourceAsStream("/db3.properties");
		//把文件的输入流放到对象里面
		p.load(in);
		//依次得到文件里面内容
		String url = p.getProperty("url");
		String username = p.getProperty("username");
		String password = p.getProperty("password");
		System.out.println(url);
		System.out.println(username);
		System.out.println(password);
	}

	//读取包下面properties格式文件的方法
	public void test2() throws IOException {
		//创建对象
		Properties p = new Properties();
		//得到servletContext对象
		ServletContext context = getServletContext();
		//得到要操作文件的输入流
		//路径:第一个位置 / 理解为项目名称;后面写文件在tomcat的webapps下面的具体的路径
		InputStream in = context.getResourceAsStream("/WEB-INF/classes/cn/itcast/read/db2.properties");
		//把文件的输入流放到对象里面
		p.load(in);
		//依次得到文件里面内容
		String url = p.getProperty("url");
		String username = p.getProperty("username");
		String password = p.getProperty("password");
		System.out.println(url);
		System.out.println(username);
		System.out.println(password);
	}
	
	//读取src下面properties格式文件的方法
	private void test1() throws IOException {
		//创建对象
		Properties p = new Properties();
		//得到servletContext对象
		ServletContext context = getServletContext();
		//得到要操作文件的输入流
		//路径: 第一个位置 /,理解为项目的名称;后面写文件在tomcat里面的具体的路径
		InputStream in = context.getResourceAsStream("/WEB-INF/classes/db1.properties");
		//把文件的输入流放到对象
		p.load(in);
		//依次得到文件里面内容
		String url = p.getProperty("url");
		String username = p.getProperty("username");
		String password = p.getProperty("password");
		System.out.println(url);
		System.out.println(username);
		System.out.println(password);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}

(2)String getRealPath(java.lang.String path):得到要操作文件的完全路径(带盘符的路径)
= 参数:和getResourceAsStream类似的
== 第一个位置 / ,项目名称;后面写文件在tomcat的webapps里面的具体的路径
= 代码
//使用getRealPath方法
//路径:第一个位置 / ,项目名称;后面写文件在tomcat的webapps里面的具体的路径
String path = context.getRealPath("/db3.properties");
//C:\Users\asus\Desktop\javaweb\day06\apache-tomcat-7.0.53\webapps\day07-7\db3.properties
//得到要操作文件的输入流
InputStream in = new FileInputStream(path);

package cn.itcast.read01;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletDemo4 extends HttpServlet {

	/**
	 * 使用servletContext里面的getRealPath方法进行操作
	 */
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//创建servletContext对象
		ServletContext context = getServletContext();
		//使用getRealPath方法
		//路径:第一个位置 / ,项目名称;后面写文件在tomcat的webapps里面的具体的路径
		String path = context.getRealPath("/db3.properties");
		//C:\Users\asus\Desktop\javaweb\day06\apache-tomcat-7.0.53\webapps\day07-7\db3.properties
		//System.out.println(path);
		//创建对象
		Properties p = new Properties();
		//得到要操作文件的输入流
		InputStream in = new FileInputStream(path);
		//把流放到对象里面
		p.load(in);
		//依次得到文件里面的内容
		String url = p.getProperty("url");
		String username = p.getProperty("username");
		String password = p.getProperty("password");
		System.out.println(url);
		System.out.println(username);
		System.out.println(password);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}

12. 使用类加载器读取文件

12.0 读取的文件的位置是 classes里面的文件
12.1 得到类加载器
(1)首先得到Class
* 第一种方式:类名.class
* 第二种方式:对象.getClass()
* 第三种方式:Class.forName(“包类路径”)
(2)使用Class得到类加载器
12.2 代码
//得到类的Class
Class clazz = ServletDemo1.class;
//得到类加载器
ClassLoader loader = clazz.getClassLoader();
//得到要操作文件的输入流
//文件的路径,因为读取的classes里面的文件,所以直接写文件的名称
InputStream in = loader.getResourceAsStream(“db1.properties”);

package cn.itcast.read;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletDemo1 extends HttpServlet {
	/**
	 * 使用类加载器读取文件
	 */
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//得到类的Class
		Class clazz = ServletDemo1.class;
		//得到类加载器
		ClassLoader loader = clazz.getClassLoader();
		//得到要操作文件的输入流
		InputStream in = loader.getResourceAsStream("db1.properties");
		//使用Properties类读取文件的内容
		Properties p = new Properties();
		p.load(in);
		//依次得到文件里面内容
		String url = p.getProperty("url");
		String username = p.getProperty("username");
		String password = p.getProperty("password");
		System.out.println(url);
		System.out.println(username);
		System.out.println(password);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}

13. 默认的servlet

13.1 比如在浏览器的地址栏随便输入一个地址,出现404,资源找不到,这个效果是由默认的servlet实现的
13.2 在tomcat的conf里面找到web.xml,有对默认servlet的配置
* 如果自己创建servlet,让这个servlet在启动时候创建,大于1的值
* 默认servlet的配置里面url-pattern是 /,当把自己创建的servlet的url-pattern写成/,这个servlet就会
称为一个默认的servlet

<servlet>
	<servlet-name>default</servlet-name>
	<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
	<init-param>
	    <param-name>debug</param-name>
	    <param-value>0</param-value>
	</init-param>
	<init-param>
	    <param-name>listings</param-name>
	    <param-value>false</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
	<servlet-name>default</servlet-name>
	<url-pattern>/</url-pattern>
 </servlet-mapping>

13.3 在默认的servlet的初始化参数里面有 listings,当把这个参数的值设置成true之后,
当直接访问web项目中文件夹时候,会把文件夹里面的所有内容显示出来

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

左绍骏

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

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

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

打赏作者

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

抵扣说明:

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

余额充值