MyBatis项目-shop购物系统

公司前辈要求的一个上项目前的练手项目,免得上项目啥都不懂。

首先定义了一个Annotation来标注需要进行的依赖注入的方法:

package com.ht.shop.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 使用这个Annotation来标注需要进行的依赖注入的方法
 *
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)//注解的生命周期,除了运行时(最长的),还可以编译阶段
@Target(ElementType.METHOD)//注解的作用范围,方法,类名,成员变量上
public @interface ShopDI {
	/**
	 * 如果没有定义default值,则必须在使用该annotation时为这个属性赋值
	 * value是默认属性,但是当定义两个以上的属性是,默认属性不起作用
	 */
	String adc() default "";
	String value() default "";
}
在配置文件中添加Filter进行编码过滤:

package com.ht.shop.filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;

/**
 * 过滤器,设置编码
 *
 */
@WebFilter(urlPatterns = {"/*"}, initParams = {@WebInitParam(name = "encoding", value = "UTF-8")})
public class CharacterFilter implements Filter {
	private String encoding;	
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		request.setCharacterEncoding(encoding);
		chain.doFilter(request, response);
	}
	public void init(FilterConfig fConfig) throws ServletException {
		encoding = fConfig.getInitParameter("encoding");
		if(encoding == null || "".equals(encoding.trim())){
			encoding = "UTF-8";
		}
	}
	@Override
	public void destroy() {
		encoding = null;
	}
}

同时web.xml文件中:

  <filter>
    <filter-name>sitemesh</filter-name>
    <filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>sitemesh</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

使用Properties文件获取相应信息:

package com.ht.shop.util;

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

/**
 * 通过properties文件,配置有关数据库信息和DAO依赖注入信息
 *
 */
public class PropertiesUtil {

	private static Properties jdbcProp;
	
	private static Properties daoProp;
	
	/**
	 * 获取jdbc.properties:数据库信息
	 * @return
	 */
	public static Properties getJdbcProp(){
		try {
			if (jdbcProp == null) {
				jdbcProp = new Properties();
				jdbcProp.load(PropertiesUtil.class.getResourceAsStream("/jdbc.properties"));
			} 
		} catch (Exception e) {
			e.printStackTrace();
		}
		return jdbcProp;
	}
	
	/**
	 * 获取dao.properties:需要依赖注入的dao
	 * @return
	 */
	public static Properties getDaoProp(){
		try {
			if(daoProp == null){
				daoProp = new Properties();
				daoProp.load(PropertiesUtil.class.getResourceAsStream("/dao.properties"));
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return daoProp;
	}
	
}
dao.properties:文件:

factory=com.ht.shop.dao.PropertiesFactory
userinfoDao=com.ht.shop.dao.UserInfoDao
categoryDao=com.ht.shop.dao.CategoryDao
addressDao=com.ht.shop.dao.AddressDao
productDao=com.ht.shop.dao.ProductDao
orderDao=com.ht.shop.dao.OrderDao

帮助类:

MyBatisUtil:

package com.ht.shop.util;

import java.io.IOException;
import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

/**
 * MyBatic帮助类
 * 读取配置文件信息
 *
 */
public class MyBatisUtil {
	
	private static SqlSessionFactory factory = null;
	
	static{
		try {
			InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
			factory = new SqlSessionFactoryBuilder().build(is);
		} catch (IOException e) {
			throw new RuntimeException("读取配置文件有误!", e);
		}
	}
	
	/**
	 * 获取一个SqlSession
	 */
	public static SqlSession getSqlSession(){
		return factory.openSession();
	}
	
	/**
	 * 关闭一个SqlSession
	 */
	public static void closeSession(SqlSession session){
		if(session != null){
			session.close();
		}
	}
	

}
daoUtil:
package com.ht.shop.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

import com.ht.shop.annotation.ShopDI;
import com.ht.shop.dao.IDaoFactory;

public class DaoUtil {
	
	/**
	 * 
	 * @return
	 */
	public static IDaoFactory createDaoFactory(){
		IDaoFactory factory = null;
		
		try {
			Properties prop = PropertiesUtil.getDaoProp();
			String fs = prop.getProperty("factory");
			//Class.forName返回与带有给定字符串的类或接口相关联的Class对象
			Class<?> clz = Class.forName(fs);
			String mn = "getInstance";
			//获取getInstance方法
			Method m = clz.getMethod(mn);
			factory = (IDaoFactory) m.invoke(clz);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return factory;
	}
	
	//通过反射Dao方法实现实例化
	public static void diDao(Object servlet){
		try {
			Method[] ms = servlet.getClass().getDeclaredMethods();	//获取该servlet的所有方法
			for(Method m : ms){
				// 判断当前方法是否存在ShopDI自定义注解
				if(m.isAnnotationPresent(ShopDI.class)){
					// 获取method上的ShopDI对象
					ShopDI sd = m.getAnnotation(ShopDI.class);
					// 获取Annotation的value值
					String value = sd.value();
					//判断获取的value是否为空,如果为空,就等于要使用setXX这个方法的方法名称来完成注入
					if(value == null || "".equals(value.trim())){
						value = m.getName();
						//setUserinfoDao
						if(value.startsWith("set")){
							value = value.substring(3);//去掉set
							value = value.substring(0, 1).toLowerCase() + value.substring(1);
							//value=userInfoDao
						}
					}
					// 通过一个工厂方法,得到userDao的实值对象,类似 Object o = new UserDao();
					Object daoObj = DaoUtil.createDaoFactory().getDao(value);
					//invoke对带有指定参数的指定对象调用由此 Method 对象表示的底层方法
					m.invoke(servlet, daoObj);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
文件上传有关:

package com.ht.shop.web;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.util.Streams;

/**
 * 装饰类:过滤Request
 * @author hcc
 *
 */
public class MultipartRequestWrapper extends HttpServletRequestWrapper {

	//request提交的数据
	private Map<String, String[]> params = null;
	
	public Map<String, String[]> getParams() {
		return params;
	}

	/**
	 * 设置request中的数据
	 */
	public void setParams(HttpServletRequest request) {
		params = new HashMap<String, String[]>();
		ByteArrayOutputStream baos = null;
		try {
			if(ServletFileUpload.isMultipartContent(request)){
				//文件上传
				ServletFileUpload upload = new ServletFileUpload();
				FileItemIterator iterator = upload.getItemIterator(request);
				while(iterator.hasNext()){
					FileItemStream fis = iterator.next();
					String fieldName= fis.getFieldName();
					
					InputStream is = fis.openStream();
					if(fis.isFormField()){
						String fieldValue = Streams.asString(is);
						setFormField(fieldName, fieldValue);
						is.close();
					}else{
						baos = new ByteArrayOutputStream();
						int len = 0;
						byte[] arrays = new byte[1024];
						while((len = is.read(arrays)) > 0){
							baos.write(arrays, 0, len);
						}
						is.close();
						byte[] fs = baos.toByteArray();
						
						request.setAttribute("is", fs);
						setFormField(fis.getFieldName(), fis.getName());
					}
				}
			}else{
				params = request.getParameterMap();
			}
		} catch (FileUploadException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally{
			try {
				if(baos != null){
					baos.flush();
					baos.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}
	
	private void setFormField(String fieldName, String value){
		if(params.containsKey(fieldName)){
			String[] values = params.get(fieldName);
			values = Arrays.copyOf(values, values.length + 1);
			values[values.length - 1] = value;
			params.put(fieldName, values);
		}else{
			params.put(fieldName, new String[]{value});
		}
	}
	
	public MultipartRequestWrapper(HttpServletRequest request) {
		super(request);
		setParams(request);
	}
	
	@Override
	public String getParameter(String name) {
		String[] vs = params.get(name);
		if(vs != null){
			return vs[0];
		}
		return null;
	}
	
	@Override
	public String[] getParameterValues(String name) {
		return params.get(name);
	}
	
}
RequestUtil:

package com.ht.shop.util;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

/**
 * 用于上传文件,文件写入本地
 *
 */
public class RequestUtil {
	
	private static final String PATH = "E:/sts-workspace/Shop/WebContent/img/";
	
	public static void uploadFile(String fileName, String fieldName, byte[] is, HttpServletRequest requst) throws IOException{
		FileOutputStream fos = null;
		try {
			System.out.println("fileName->[" + fileName + "]");
			fos = new FileOutputStream(PATH + fileName);
			fos.write(is, 0, is.length);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if(fos != null){
				fos.close();
			}
		}
	}
	
}
Model包中的order.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
	"http://mybatis.org/dtd/mybatis-3-config.dtd" >
	
<mapper namespace="com.ht.shop.model.Order" >
 <!-- 结果集映射 -->
	<resultMap type="Order" id="orderMap" autoMapping="false">
		<id column="order_id" property="orderId"/>
		<result column="submit_date" property="submitDate"/>
		<result column="pay_date" property="payDate"/>
		<result column="confirm_date" property="confirmDate"/>
		<result column="state" property="state"/>
		<result column="address_id" property="address.addressId"/>
		<result column="amount" property="amount"/>
		<result column="user_id" property="user.userId"/>
		<!-- 实体类 -->
		<association property="user" javaType="Userinfo" 
			select="com.ht.shop.model.UserInfo.load" column="user_id">
		</association>
		
		<association property="address" javaType="ShoppingAddress"
			select="com.ht.shop.model.ShoppingAddress.load" column="address_id">
		</association>
		<!-- 集合 -->
		<collection property="commerceItems" ofType="CommerceItem">
			<id column="id" property="id"/>
			<result column="quantity" property="quantity"/>
			<result column="amount" property="amount"/>
			<result column="product_id" property="product.productId"/>
				<association property="product" javaType="Product"
					 select="com.ht.shop.model.Product.load" column="product_id">
				</association>
		</collection>
	</resultMap>

	<insert id="add" parameterType="Order">
		insert into t_order(submit_date, state, address_id, amount, user_id, order_id)
			values(#{submitDate}, #{state}, #{address.addressId}, #{amount}, #{user.userId}, #{orderId})
	</insert>

	<select id="load" parameterType="int" resultMap="orderMap">
		SELECT o.*,c.product_id,c.quantity,c.amount
			FROM t_order o INNER JOIN t_commerce_item c ON 
			o.order_id = c.order_id
			WHERE o.order_id = #{id};
	</select>

	<select id="list" resultMap="orderMap" parameterType="Map">
		select order_id, submit_date, pay_date, confirm_date, state
			from t_order limit #{pageoffset}, #{pagesize}
		<!-- select * from t_order limit #{pageoffset}, #{pagesize} -->
	</select>
	
	<select id="list_count" resultType="int">
		select count(*) from t_order
	</select>
</mapper>
一个Servlet:

package com.ht.shop.web;

import java.util.Date;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.ht.shop.annotation.ShopDI;
import com.ht.shop.dao.IAddressDao;
import com.ht.shop.dao.IOrderDao;
import com.ht.shop.dao.IProductDao;
import com.ht.shop.dao.IUserInfoDao;
import com.ht.shop.model.CommerceItem;
import com.ht.shop.model.Order;
import com.ht.shop.model.Product;
import com.ht.shop.model.ShopCart;
import com.ht.shop.model.UserInfo;
import com.ht.shop.page.Pager;

@WebServlet(name = "order.do", urlPatterns = { "/order.do" })
public class OrderServlet extends BaseServlet {
	private static final long serialVersionUID = 1L;

	private IOrderDao orderDao;
	
	private IProductDao productDao;
	
	private IAddressDao addressDao;
	
	private IUserInfoDao userinfoDao;
	
	@ShopDI(value="orderDao")
	public void setOrderDao(IOrderDao orderDao) {
		this.orderDao = orderDao;
	}

	@ShopDI(value="productDao")
	public void setProductDao(IProductDao productDao) {
		this.productDao = productDao;
	}

	@ShopDI(value="addressDao")
	public void setAddressDao(IAddressDao addressDao) {
		this.addressDao = addressDao;
	}

	@ShopDI(value="userinfoDao")
	public void setUserInfoDao(IUserInfoDao userinfoDao) {
		this.userinfoDao = userinfoDao;
	}

	public String list(HttpServletRequest req, HttpServletResponse res){
		Pager<Order> orderPager = orderDao.find("com.ht.shop.model.Order.list", null);
		req.setAttribute("orderPager", orderPager);
		return "order/list.jsp";
	}
	
	/**
	 * 商品添加到购物车
	 */
	public String addToCart(HttpServletRequest req, HttpServletResponse res){
		String pid = req.getParameter("id");
		Product p = productDao.load(Integer.parseInt(pid));
		ShopCart cart = (ShopCart) req.getSession().getAttribute("cart");
		if(cart == null){
			//第一次创建购物车
			cart = new ShopCart();
			req.getSession().setAttribute("cart", cart);
		}
		cart.addCommerceItem(p, 1);
		return redirectPath("product.do?method=list");
	}
	
	/**
	 * 查看购物车
	 */
	public String showCart(HttpServletRequest req, HttpServletResponse res){
		UserInfo u = (UserInfo) req.getSession().getAttribute("loginUser");
		u = userinfoDao.load(u.getUserId());
		req.setAttribute("addresses", u.getAddresses());
		return "order/showCart.jsp";	
	}
	
	/**
	 * 提交订单
	 */
	public String submitOrder(HttpServletRequest req, HttpServletResponse res){
		String totalPrice = req.getParameter("totalPrice");
		String addressId = req.getParameter("address");
		UserInfo user = (UserInfo) req.getSession().getAttribute("loginUser");
		ShopCart cart = (ShopCart) req.getSession().getAttribute("cart");
		
		Order order = new Order();
		order.setOrderId(101);
		order.setUser(user);
		order.setAmount(Double.parseDouble(totalPrice));
		
		order.setSubmitDate(new Date());
		order.setAddress(addressDao.load(Integer.parseInt(addressId)));
		order.setState(1);
		order.setCommerceItems(cart.getCommerceItems());
		
		orderDao.add(order);
		//保存订单中的commerceItem
		for(CommerceItem item : order.getCommerceItems()){
			orderDao.addCommerceItem(item, order);
		}
		return redirectPath("order.do?method=list");
	}
	
	public String show(HttpServletRequest req, HttpServletResponse res){
		String orderId = req.getParameter("id");
		Order o = orderDao.load(Integer.parseInt(orderId));
		req.setAttribute("o", o);
		return "order/show.jsp";
	}
	
	public String clearShopCart(HttpServletRequest req, HttpServletResponse res){
		ShopCart cart = (ShopCart) req.getSession().getAttribute("cart");
		cart.clear();
		return redirectPath("order.do?method=showCart");
	}
	
	public String comItemAddQtyInput(HttpServletRequest req, HttpServletResponse res){
		String pId = req.getParameter("pid");
		req.setAttribute("pid", pId);
		return "order/comItemAddQtyInput.jsp";
	}
	
	public String comItemAddQty(HttpServletRequest req, HttpServletResponse res){
		String pId = req.getParameter("pid");
		String count = req.getParameter("qty");
		ShopCart cart = (ShopCart) req.getSession().getAttribute("cart");
		cart.addCommerceItem(productDao.load(Integer.parseInt(pId)), Integer.parseInt(count));
		req.getSession().setAttribute("cart", cart);
		return redirectPath("order.do?method=showCart");
	}
	
	public String clearCommerceItem(HttpServletRequest req, HttpServletResponse res){
		String pid = req.getParameter("pid");
		ShopCart cart = (ShopCart) req.getSession().getAttribute("cart");
		cart.deleteCommerceItem(Integer.parseInt(pid));
		return redirectPath("order.do?method=showCart");
	}
}
BaseDao:

package com.ht.shop.dao;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.session.SqlSession;

import com.ht.shop.model.SystemContext;
import com.ht.shop.page.Pager;
import com.ht.shop.util.MyBatisUtil;

public class BaseDao<T> {
	
	public Pager<T> find(String sqlId, Map<String, Object> params){
		int pageSize = SystemContext.getPageSize();
		int pageOffSet = SystemContext.getPageOffset();
		
		Pager<T> pagers = new Pager<T>();
		List<T> datas = null;
		SqlSession session = null;
		
		try {
			session = MyBatisUtil.getSqlSession();
			if(params == null){
				params = new HashMap<String, Object>();
			}
			params.put("pagesize", pageSize);
			params.put("pageoffset", pageOffSet);
			System.out.println("sqlId->[" + sqlId + "]");
			datas = session.selectList(sqlId, params);
			int totalRecord = session.selectOne(sqlId+"_count", params);
			pagers.setDatas(datas);
			pagers.setPageOffSet(pageOffSet);
			pagers.setPageSize(pageSize);
			pagers.setTotalRecord(totalRecord);
		} finally {
			MyBatisUtil.closeSession(session);
		}
		return pagers;
	}

	public void add(T obj){
		SqlSession session = null;
		try {
			session = MyBatisUtil.getSqlSession();
			session.insert(obj.getClass().getName()+".add", obj);
			session.commit();//锟角碉拷锟结交
		} catch (Exception e) {
			e.printStackTrace();
			session.rollback();
		} finally {
			MyBatisUtil.closeSession(session);
		}
	}
	
	public void add(String sqlId, Object obj){
		SqlSession session = null;
		
		try {
			session = MyBatisUtil.getSqlSession();
			session.insert(sqlId, obj);
			session.commit();
		} catch(Exception e){
			session.rollback();
		} finally {
			MyBatisUtil.closeSession(session);
		}
	}
	
	public void update(T obj){
		SqlSession session = null;
		try {
			session = MyBatisUtil.getSqlSession();
			session.update(obj.getClass().getName()+".update", obj);
			session.commit();//锟角碉拷锟结交
		} catch (Exception e) {
			session.rollback();
		} finally {
			MyBatisUtil.closeSession(session);
		}
	}
	
	public void delete(Class<T> cls, int id){
		SqlSession session = null;
		try {
			session = MyBatisUtil.getSqlSession();
			session.delete(cls.getName()+".delete", id);
			session.commit();//锟角碉拷锟结交
		} catch (Exception e) {
			session.rollback();
		} finally {
			MyBatisUtil.closeSession(session);
		}
	}
	
	public T load(Class<T> cls, int id){
		SqlSession session = null;
		T t = null;
		try {
			session = MyBatisUtil.getSqlSession();
			t = session.selectOne(cls.getName()+".load", id);
		} finally{
			MyBatisUtil.closeSession(session);
		}
		return t;
	}
	

	public T loadBySqlId(String sqlId, Object obj){
		SqlSession session = null;
		T t = null;
		try {
			session = MyBatisUtil.getSqlSession();
			t = session.selectOne(sqlId, obj);
		} finally {
			MyBatisUtil.closeSession(session);
		}
		return t;
	}
	
	public List<T> list(String sqlId, Map<String, Object> param){
		List<T> list = null;
		SqlSession session = null;
		try {
			session = MyBatisUtil.getSqlSession();
			list = session.selectList(sqlId, param);
		} finally {
			MyBatisUtil.closeSession(session);
		}
		return list;
	}
	
	public List<T> list(Class<T> cls, Map<String, Object> param){
		return this.list(cls.getName()+".list", param);
	}
	
}
OrderDao:

package com.ht.shop.dao;

import com.ht.shop.model.CommerceItem;
import com.ht.shop.model.Order;

public class OrderDao extends BaseDao<Order> implements IOrderDao {
<span style="white-space:pre">	</span>@Override
	public void add(Order obj) {
		super.add(obj);
	}
	@Override
	public void addCommerceItem(CommerceItem item, Order order) {
		item.setOrder(order);
		System.out.println("item->[" + item + "]");
		super.add(CommerceItem.class.getName()+".add", item);
	}
	@Override
	public Order load(int id) {
		return super.load(Order.class, id);
	}
}
以下为程序截图:

登录界面:

订单界面:

商品界面:

商品类别界面

用户界面:


另外还有购物车,但是没有实现持久化,只是放在了Session中,这里就不展示了。
源码稍后补上,出了点问题。









  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
1、学会各类开发软件安装、项目导入以及项目发布,含项目源码,需求文档,配套软件等 2、该项目主要功能完善,主要用于简历项目经验丰富,以及毕业设计或者二次开发 3、提供项目源码,设计文档、数据库sql文件以及所有配套软件,按照教程即可轻松实现项目安装部署 本课程为素材版,需要实战版的同学可以点击如下链接: 项目实战课程:代码视频讲解版如下java项目实战之电商系统全套(前台和后台)(java毕业设计ssm框架项目)https://edu.csdn.net/course/detail/25771java项目之oa办公管理系统(java毕业设计)https://edu.csdn.net/course/detail/23008java项目之hrm人事管理项目(java毕业设计)https://edu.csdn.net/course/detail/23007JavaWeb项目实战之点餐系统前台https://edu.csdn.net/course/detail/20543JavaWeb项目实战之点餐系统后台https://edu.csdn.net/course/detail/19572JavaWeb项目实战之宿舍管理系统(Java毕业设计含源码)https://edu.csdn.net/course/detail/26721JavaWeb项目实战之点餐系统全套(前台和后台)https://edu.csdn.net/course/detail/20610java项目实战之电子商城后台(java毕业设计SSM框架项目)https://edu.csdn.net/course/detail/25770java美妆商城项目|在线购书系统(java毕业设计项目ssm版)https://edu.csdn.net/course/detail/23989系统学习课程:JavaSE基础全套视频(环境搭建 面向对象 正则表达式 IO流 多线程 网络编程 java10https://edu.csdn.net/course/detail/26941Java Web从入门到电商项目实战挑战万元高薪(javaweb教程)https://edu.csdn.net/course/detail/25976其他素材版(毕业设计或课程设计)项目:点击老师头像进行相关课程学习

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值