JSP和Servlet整合案例

02系统页面创建&系统需求分析

2.2 简答题
2.2.1 根据视频,请写出登录功能的实现思路?
根据用户名和密码查询用户信息,如果查到则登录成功,如果查不到则登录失败
2.2.2 视频中要完成的三个功能需求分别是?、
实现用户登录:根据用户名和密码在数据库中查找是否有这个人,如果有则登录成功,如果没有则登录失败
实现用户退出:销毁session
实现用户注册:将用户信息插入到数据库中
2.3 编程题
2.3.1 根据视频讲解,独立完成主页面模板的套用实现。

03登录Servlet创建和MVC思想

3.1 编程题
3.2.1 根据视频中的需求分析,使用MySQL完成用户信息表的创建,将表创建语句和测试数据SQL作为答案

create table t_user(
uid int primary key auto_increment,
uname varchar(20) not null,
pwd varchar(10) not null,
sex char(4) not NULL,
age int not null,
birthday date not null
);

insert into t_user values(default,"张三","123","男",18,"1997-10-2");
insert into t_user values(default,"李四","456","男",18,"1997-10-2");

select * from t_user;

3.2.2 修改登录页面数据提交的action地址
截图作为答案

在这里插入图片描述
3.2.3 创建登录Servlet,并在Servlet完成编码设置,已经登录信息的获取的代码的编写,将实现代码粘贴作为答案

public class UserServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
		//获取请求信息
		String uname = req.getParameter("uname");
		String pwd = req.getParameter("pwd");
		//处理请求信息
		System.out.println(uname+":"+pwd);
		//响应处理结果
			//直接响应
			//请求转发
			//重定向
	}
}

3.2.4 修改登录页面中表单中用户名和密码提交的键名,,将修改后的表单代码粘贴作为答案

<input type="text" class="input input-big" name="uname" placeholder="登录账号" data-validate="required:请填写账号" />
<input type="password" class="input input-big" name="pwd" placeholder="登录密码" data-validate="required:请填写密码" />

3.2.5 简述MVC的编程思想及其好处
M:model service层和dao层和实体类层
V:view 视图层jsp页面等
C:controller 控制层servlet

04MVC实现登录查询用户信息(A)

4.3编程题
4.3.1 根据视频讲解,在项目中完成MVC中service层和Dao的创建,只需要完成接口及其实现类的创建,先不声明功能方法。
在这里插入图片描述

4.3.2 根据视频创建User实体类

public class User implements Serializable{
	private int uid;
	private String uname;
	private String pwd;
	private String sex;
	private int age;
	private String birthday;
	public int getUid() {
		return uid;
	}
	public void setUid(int uid) {
		this.uid = uid;
	}
	public String getUname() {
		return uname;
	}
	public void setUname(String uname) {
		this.uname = uname;
	}
	public String getPwd() {
		return pwd;
	}
	public void setPwd(String pwd) {
		this.pwd = pwd;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getBirthday() {
		return birthday;
	}
	public void setBirthday(String birthday) {
		this.birthday = birthday;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result
				+ ((birthday == null) ? 0 : birthday.hashCode());
		result = prime * result + ((pwd == null) ? 0 : pwd.hashCode());
		result = prime * result + ((sex == null) ? 0 : sex.hashCode());
		result = prime * result + uid;
		result = prime * result + ((uname == null) ? 0 : uname.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		User other = (User) obj;
		if (age != other.age)
			return false;
		if (birthday == null) {
			if (other.birthday != null)
				return false;
		} else if (!birthday.equals(other.birthday))
			return false;
		if (pwd == null) {
			if (other.pwd != null)
				return false;
		} else if (!pwd.equals(other.pwd))
			return false;
		if (sex == null) {
			if (other.sex != null)
				return false;
		} else if (!sex.equals(other.sex))
			return false;
		if (uid != other.uid)
			return false;
		if (uname == null) {
			if (other.uname != null)
				return false;
		} else if (!uname.equals(other.uname))
			return false;
		return true;
	}
	@Override
	public String toString() {
		return "User [uid=" + uid + ", uname=" + uname + ", pwd=" + pwd
				+ ", sex=" + sex + ", age=" + age + ", birthday=" + birthday
				+ "]";
	}
	public User() {
		super();
	}

4.3.3 根据视频讲解导入MySQL的jar包,并导入数据库操作工具类以及db.properties的配置
在这里插入图片描述在这里插入图片描述
4.3.4 根据视频完成业务层和数据库层功能代码实现

public interface UserService {
	User getUserInfoService(String uname, String pwd);
}
public class UserServiceImpl implements UserService{
	UserDao ud = new UserDaoImpl();
	//根据用户名和密码查询用户信息
	@Override
	public User getUserInfoService(String uname, String pwd) {
		return ud.getUserInfoDao(uname,pwd);
	}
}
public interface UserDao {
	User getUserInfoDao(String uname, String pwd);
}

public class UserDaoImpl implements UserDao{
	//根据用户名和密码查询用户信息
	@Override
	public User getUserInfoDao(String uname, String pwd) {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		User u = null;
		try{
			conn = (Connection) DBUtil.getConnection();
			String sql = "select * from t_user where uname=? and pwd=?";
			ps = conn.prepareStatement(sql);
			ps.setString(1,uname);
			ps.setString(2, pwd);
			rs = ps.executeQuery();
			while(rs.next()){
				u = new User();
				u.setUid(rs.getInt("uid"));
				u.setUname(rs.getString("uname"));
				u.setSex(rs.getString("sex"));
				u.setAge(rs.getInt("age"));
				u.setBirthday(rs.getString("birthday"));
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			DBUtil.closeAll(rs, ps, conn);
		}
		return u;
	}
}

4.3.5 根据视频讲解运行项目在后台打印查询到的用户信息。
在这里插入图片描述

05用户登录失败和成功处理

5.1 编程题
5.1.1 根据视频讲解,完成登录失败重定向登录页面,并在登录页面显示提示语 用户名或密码错误

UserServlet中代码的添加:
//创建或获取session对象
		HttpSession session = req.getSession();
			//重定向
		if(user!=null){//登录成功
			//成功要显示当前用户信息
			session.setAttribute("user", user);
			resp.sendRedirect("/project/main.jsp");
		}else{//登录失败
			//失败要显示提示信息
			session.setAttribute("flag", "用户名或密码错误");
			resp.sendRedirect("/project/login.jsp");
		}
Login.jsp代码的添加:
<!-- 声明java代码块 -->
                	<%
                		Object obj = session.getAttribute("flag");
                		if(obj!=null){
                	%>
              		 <div  style="font-size:18px;color:red;" class="text-center margin-big padding-big-top">用户名或密码错误</div>        	
                	<%	
                		}
                		session.invalidate();
                	%>

5.1.2 完成退出登录按钮的添加。

<div style="position: relative;left:820px" class="head-l"><span style="font-size: 15px;color: white">当前用户为:<%= ((User)session.getAttribute("user")).getUname() %></span>&nbsp;&nbsp;<a class="button button-little bg-red" href="login.html"><span class="icon-power-off"></span> 退出登录</a> </div>

5.1.3 完成登录成功,重定向主页面代码实现。并在主页显示当前登录的用户。

在这里插入图片描述

06用户退出功能实现

6.2 上级练习
6.2.1 简述用户退出的实现思路
当用户点击退出时,首先给出一个弹框,问是否退出,给用户一个友好的交互,若点击是则销毁session对象,再重定向到login.jsp页面,若点击否则不做处理
6.2.2 声明并创建Servlet处理用户退出登录的请求。

public class ExitServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
		//获取请求信息
		//处理请求信息
		//获取session对象
		HttpSession session = req.getSession();
		//强制销毁
		session.invalidate();
		//响应处理结果
			//重定向
			resp.sendRedirect("/project/login.jsp");
	}
}

6.2.3 修改退出登录按钮的herf地址为退出登录的Servlet路径,然后运行项目,点击退出登录查看运行效果

  <div style="position: relative;left:820px" class="head-l"><span style="font-size: 15px;color: white">当前用户为:<%= ((User)session.getAttribute("user")).getUname() %></span>&nbsp;&nbsp;<a class="button button-little bg-red" href="exit" id="div_a"><span class="icon-power-off"></span> 退出登录</a> </div>

6.2.3 修改代码给退出登录按钮添加退出提示语。

<script type="text/javascript">
	$(function(){
		$("#div_a").click(function(){
			return window.confirm("你真的要退出吗?");
		})
	})
</script>   

07创建用户注册页面(1)

7.1 编程题
7.1.1 根据视频讲解,在登录页面中添加注册按钮。

<div style="font-size: 15px;position: relative;left: 300px;top: -15px"><a href="reg.jsp">注册</a></div>

7.1.2 根据视频讲解,创建注册页面并将套用模板内容。

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <base href="<%=basePath%>">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<meta name="renderer" content="webkit">
<title></title>
<link rel="stylesheet" href="css/pintuer.css">
<link rel="stylesheet" href="css/admin.css">
<script src="js/jquery.js"></script>
<script src="js/pintuer.js"></script>
</head>
<body>
<div class="panel admin-panel">
  <div class="panel-head"><strong><span class="icon-key"></span> 用户注册页面</strong></div>
  <div class="body-content">
    <form method="post" class="form-x" action="">
      <div class="form-group">
        <div class="label">
          <label for="sitename">用户名:</label>
        </div>
        <div class="field">
          <input type="text" class="input w50" id="mpass" name="uname" size="50" placeholder="请输入用户名" />       
        </div>
      </div>      
      <div class="form-group">
        <div class="label">
          <label for="sitename">用户密码:</label>
        </div>
        <div class="field">
          <input type="password" class="input w50" name="pwd" size="50" placeholder="请输入新密码" data-validate="required:请输入新密码,length#>=5:新密码不能小于5位" />         
        </div>
      </div>
      <div class="form-group">
        <div class="label">
          <label for="sitename">确认新密码:</label>
        </div>
        <div class="field">
          <input type="password" class="input w50" name="npwd" size="50" placeholder="请再次输入新密码" data-validate="required:请再次输入新密码,repeat#newpass:两次输入的密码不一致" />          
        </div>
      </div>
      <div class="form-group">
        <div class="label">
          <label></label>
        </div>
        <div class="field">
          <button class="button bg-main icon-check-square-o" type="submit"> 提交</button>   
        </div>
      </div>      
    </form>
  </div>
</div>
</body></html>

7.1.3 根据视频讲解,修改注册页面原有模板内容,修改为我们自己的注册页面,并添加用户性别选项。

<div class="form-group">
			        <div class="label">
			          <label>性别:</label>
			        </div>
			        <div class="field">
			          <div class="button-group radio">
			          
			          <label class="button active">
			         	  <span class="icon-check" id="manSpan"></span>             
			              <input name="sex" value="1" id="man" type="radio" checked="checked">男         
			          </label>             
			        
			          <label class="button active" ><span class="" id="womanSpan"></span>          	
			              <input name="sex" value="0" id="woman" type="radio">女
			          </label>         
			           </div>       
			        </div>
			     </div> 

08创建用户注册页面(2)

8.1 编程题
8.1.1 根据视频讲解,完成用户性别选择功能。

<script type="text/javascript">
	$(function(){
		
		$("#man").click(function(){
			
			$("#manSpan").addClass("icon-check");
			$("#womanSpan").removeClass("icon-check");
		})
		
		$("#woman").click(function(){
			
			$("#manSpan").removeClass("icon-check");
			$("#womanSpan").addClass("icon-check");
		})
	})
</script>

8.1.2 完善注册页面,添加用户年龄和出生日期选项

 <div class="form-group">
        <div class="label">
          <label for="sitename">用户年龄:</label>
        </div>
        <div class="field">
          <input type="number" class="input w50" id="mpass" name="age" size="50" placeholder="请输入用户年龄" />       
        </div>
      </div>      
      
      <div class="form-group">
        <div class="label">
          <label for="sitename">出生日期:</label>
        </div>
        <div class="field">
          <input type="date" class="input w50" id="mpass" name="birthday" size="50" />       
        </div>
      </div>   

8.1.3 修改注册页面中自带的基础表单校验。
把注册页面中自带的基础表单校验换成我们自己的表单项的校验

09用户注册功能实现

9.1 编程题
9.1.1 根据视频讲解,继续完成注册页面,修改注册页面表单数据提交的键名。
用户名:name=“uname” 密码:name=“pwd”
性别:name=“sex” 年龄:name=“age”
出生日期:name=“birthday”
9.1.2 创建并声明处理注册功能的Servlet

public class RegServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
		//获取请求信息
		String uname = req.getParameter("uname");
		String pwd = req.getParameter("pwd");
		String num = req.getParameter("sex");
		String sex = null;
		if("1".equals(num)){
			sex = "男";
		}else if("0".equals(num)){
			sex = "女";
		}
		int age = Integer.parseInt(req.getParameter("age"));
		String birthday = req.getParameter("birthday");
		//处理请求信息		
		//获取业务层对象
		UserService us = new UserServiceImpl();
	}
}


9.1.3 完成注册功能的业务层和数据库层的代码

int addUserInfoService(String uname, String pwd, String sex, int age,
			String birthday);
@Override
	public int addUserInfoService(String uname, String pwd, String sex,
			int age, String birthday) {
		return ud.addUserInfoDao(uname,pwd,sex,age,birthday);
	}
int addUserInfoDao(String uname, String pwd, String sex, int age,
			String birthday);
@Override
	public int addUserInfoDao(String uname, String pwd, String sex, int age,
			String birthday) {
		String sql = "insert into t_user values(default,?,?,?,?,?)";
		int i = DBUtil.executeDML(sql, uname,pwd,sex,age,birthday);
		return i;
	}

9.1.4 在regServlet中完成注册成功和注册失败的代码逻辑,然后运行项目,点击注册观察运行效果。

int i = us.addUserInfoService(uname,pwd,sex,age,birthday);
		//System.out.println(i);
		//创建或获取session对象
		HttpSession session = req.getSession();
		//响应处理结果
		if(i>0){
			//将登陆结果存储进session内
			session.setAttribute("flag", "regSuccess");
			//重定向
			resp.sendRedirect("/project/login.jsp");
		}else{
			resp.sendRedirect("/project/reg.jsp");
		}

10注册成功提示语&项目问题引入和解决方案

10.1 编程题
10.1.1 根据视频讲解,完成注册成功提示语功能
见上
10.1.2 视频中目前项目存在的问题是什么?、
现在我们一个请求或者一个独立的业务逻辑都单独进行一个Servlet的创建进行请求处理。但是一个网站的功能是非常的多,如果每个都创建单独的Servlet进行处理,这样造成Servlet过多。造成资源浪费。
10.1.3 视频中给出的解决方案是什么?
服务器在接收到浏览器发送的请求后,会调用对应的Servlet进行请求处理。然后调用Servlet中的Service方法进行处理。我们将不同功能的处理封装成对应的方法。在service方法中调用其对应的功能处理方法进行请求处理。这样Servlet我们只需要一个。

11service中实现动态调用请求处理方法(1)

11.1 编程题
11.1.1 根据视频创建DataServlet,并声明登录,退出,注册三个方法。

public class DataServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
	}
	//用户登录的方法
	public void userLogin(HttpServletRequest req, HttpServletResponse resp){
		
	}
	//用户退出的方法
	public void userExit(HttpServletRequest req, HttpServletResponse resp){
			
	}
	//用户注册的方法
	public void userReg(HttpServletRequest req, HttpServletResponse resp){
			
	}
}

11.1.2 根据视频讲解在DataServlet中的service方法中完成动态调用方法处理请求的反射代码的编写

//获取请求信息
		String methodName = req.getParameter("method");
		try {
			//获取当前类的类对象
			Class c = this.getClass();
			//获取当前类的类方法对象
			Method m = c.getMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
			//调用对应的方法
			m.invoke(this, req,resp);
		} catch (Exception e) {
			e.printStackTrace();
		}

12service中实现动态调用请求处理方法(2)

12.1 编程题
12.1.1 根据视频讲解完善DataServlet中登录,注册,退出方法的中的代码实现。

//用户登录的方法
	public void userLogin(HttpServletRequest req, HttpServletResponse resp) throws IOException{
		//获取请求信息
				String uname = req.getParameter("uname");
				String pwd = req.getParameter("pwd");
				//处理请求信息
//				System.out.println(uname+":"+pwd);
				//根据用户名和密码查询是否有此人
				//调用service层进行业务逻辑处理
				UserService us = new UserServiceImpl();
				User user = us.getUserInfoService(uname,pwd);
				System.out.println("查到的用户信息为"+user);
				//响应处理结果
					//直接响应
					//请求转发
				//创建或获取session对象
				HttpSession session = req.getSession();
					//重定向
				if(user!=null){//登录成功
					//成功要显示当前用户信息
					session.setAttribute("user", user);
					resp.sendRedirect("/project/main.jsp");
				}else{//登录失败
					//失败要显示提示信息
					session.setAttribute("flag", "loginFalse");
					resp.sendRedirect("/project/login.jsp");
				}
	}
	//用户退出的方法
	public void userExit(HttpServletRequest req, HttpServletResponse resp) throws IOException{
		//获取请求信息
				//处理请求信息
				//获取session对象
				HttpSession session = req.getSession();
				//强制销毁
				session.invalidate();
				//响应处理结果
					//重定向
					resp.sendRedirect("/project/login.jsp");
	}
	//用户注册的方法
	public void userReg(HttpServletRequest req, HttpServletResponse resp) throws IOException{
		//获取请求信息
				String uname = req.getParameter("uname");
				String pwd = req.getParameter("pwd");
				String num = req.getParameter("sex");
				String sex = null;
				if("1".equals(num)){
					sex = "男";
				}else if("0".equals(num)){
					sex = "女";
				}
				int age = Integer.parseInt(req.getParameter("age"));
				String birthday = req.getParameter("birthday");
				//处理请求信息		
				//获取业务层对象
				UserService us = new UserServiceImpl();
				int i = us.addUserInfoService(uname,pwd,sex,age,birthday);
				System.out.println(i);
				//创建或获取session对象
				HttpSession session = req.getSession();
				//响应处理结果
				if(i>0){
					//将登陆结果存储进session内
					session.setAttribute("flag", "regSuccess");
					//重定向
					resp.sendRedirect("/project/login.jsp");
				}else{
					resp.sendRedirect("/project/reg.jsp");
				}
	}

12.1.2 修改登录页面在表单中添加隐藏便签,添加请求数据中的方法名,完成登录功能

<input type="hidden" name="method" value="userLogin"/>

12.1.3 修改退出按钮,完成退出功能

 <div style="position: relative;left:820px" class="head-l"><span style="font-size: 15px;color: white">当前用户为:<%= ((User)session.getAttribute("user")).getUname() %></span>&nbsp;&nbsp;<a class="button button-little bg-red" href="data?method=userExit" id="div_a"><span class="icon-power-off"></span> 退出登录</a> </div>

12.1.4 修改注册页面,完成注册功能

<input type="hidden" name="method" value="userReg" />

12.1.5 视频中最后提出的问题是什么?
现在使用反射我们实现了在service方法中动态的根据请求调用对应的方法进行请求处理。但是真实开发过程中,虽然不会每个功能都创建一个servlet,但是也不会只使用一个Servlet,我们的Servlet不只是一个,一般是一个独立的功能模块一个Servlet。我们需要在这些Servlet中的service方法中都要将反射代码声明一遍。

13-向上抽取BaseServlet类

13.1 编程题
13.1.1 根据视频,完成BaseServlet的创建

public abstract  class BaseServlet extends HttpServlet {
	protected void service(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		//设置请求编码格式
		req.setCharacterEncoding("utf-8");
		//设置响应编码格式
		resp.setContentType("text/html;charset=utf-8");
		//获取请求信息
		String methodName = req.getParameter("method");
		try {
			//获取当前类的类对象
			Class c = this.getClass();
			//获取当前类的类方法对象
			Method m = c.getMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
			//调用对应的方法
			m.invoke(this, req,resp);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

13.1.2 根据视频,修改DataServlet继承BaseServlet
然后启动项目重新访问相关功能。

public class DataServlet  extends BaseServlet{}

13.1.3 BaseServlet的使用流程是?
1、创建Servlet继承BaseServlet即可。
2、在自己的servlet中不要声明service方法,只要书写请求处理功能方法即可。
3、正常请求我们自己的servlet
注意:
请求必须附带要被执行的方法名

14-项目总结和缺陷

14.1 简答题
14.1.1 视频中项目总结的六个内容是?
1、套用模版进行页面快速构建
在自己的项目中创建jsp文件
然后将模版中的前端相关代码赋值到自己的jsp文件中
将静态资源复制到webRoot下
2、MVC的开发流程
M:model service dao pojo
v:view jsp js css html
c:controller Servlet
3、Servlet+jsp+jdbc的功能开发流程
1、浏览器发起页面请求直接给jsp
2、浏览器发起功能请求给servlet,servlet调用service,service进行业务逻辑处理,
service调用dao,dao层进行数据库操作(jdbc),dao层将处理结果返回给service
service再将结果返回给servlet,(或者继续请求转发或者重定向其他Servlet继续处理) ,
请求转发或者重定向给jsp,jsp做出页面响应。
4、request和session作用域的使用
request:请求转发的数据流转的载体
session:重定向的数据流转的载体(但是session可以解决同一个用户的不同请求的数据库共享问题)。
5、浏览器发起请求到服务器请求发起的方式(重点记忆)
非ajax请求
form表单提交:action数据提交地址,method:数据提交方式
超链接标签:href:为数据提交地址,可以直接使用?拼接请求数据,类似form表单的get请求方式。
js中的window.location.herf:为数据提交地址,可以直接使用?拼接请求数据,类似form表单的get请求方式。
注意:
使用以上请求方式发起的请求,浏览器在接收到响应内容后,会将原有内容覆盖,显示响应结果。
6、BaseServlet的抽取和使用
反射
抽象类

14.1.2 根据视频,项目目前仍然存在的缺陷是?
1、在jsp中获取从Servlet流转过来的数据特别麻烦
2、在jsp页面中使用java代码块进行逻辑处理书写和阅读极不方便
3、使用session进行数据流转是很方便的,但是session失效了,所有依赖session的功能都会出问题。
4、响应结果都是覆盖原有内容显示给用户

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值