网上商城项目总结

经过三周的学习,网上商城项目的所有功能在今天都全部完成了,写这个项目我学到了不少新的知识,为了以后方便回顾,把这个项目实现的功能都写在这里,项目是jsp+servlet+javabean实现的。

一,商城后台

1.登录,

获取到前台页面输入的管理员用户名和密码,到数据库进行查询,dao层对数据库操作,用到了QueryRunner类,创建对象时,以c3p0连接池为参数QueryRunner runner=new QueryRunner(DataSourceUtils.getDataSource());对数据库查询时,用runner的query(sql,ResultSetHandler,Object...params)方法,参数sql为sql语句,ResultSetHandler,为返回值,Object...params为sql语句中所需要的值,更新数据库时,用update(sql,Object...params)方法,参数意思和query方法中的一样。登录成功后,可以看到三个菜单,分别为分类管理,商品管理和订单管理

2.分类管理,

这个模块实现了对商场所卖商品的所有类别的增删改查,和分页查询,因为后续很多模块也需要用到分页查询,于是我们就通过反射来进行了提取,创建了PageUtil类,里面有4个属性private int pageSize;每页显示条数,private int nowPage;当前页码号,private int maxPage;最大页码号,private int totalCount;数据总条数,生成他们的get,set方法,主要代码为

public  List<T> getList(Class name,String sql,int nowpage,int pagesize) {
		
		QueryRunner query=new QueryRunner(DataSourceUtils.getDataSource());
		try {
			return query.query(sql, new BeanListHandler<T>(name), (nowpage-1)*pagesize,pagesize);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
public int getMaxPage(String sql,int pagesize) {
		int count=0;
		QueryRunner query=new QueryRunner(DataSourceUtils.getDataSource());
		try {
		    count=((Long)query.query(sql, new ScalarHandler())).intValue();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		this.totalCount=count;
		int max=(count%pagesize)==0?count/pagesize:(count/pagesize)+1;
		this.maxPage=max;
		return maxPage;
	}
只需要调用者两个方法,传入相应的参数即可得到分页所显示的数据,

3.商品管理

这里主要是对商品的增删改查操作,添加商品时,因为要显示所有的商品类别,所以采用自定函数标签来实现这一功能,在WEB-INF下新建文件夹,在文件夹里新建一个.tld结尾的文件,可根据standard.jar包下的META-INF/fn.tld里面的内容来编写自定义函数,写完后如下

<?xml version="1.0" encoding="UTF-8" ?>

<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
  version="2.0">
  
  <description>JSTL 1.1 functions library</description>
  <display-name>JSTL functions</display-name>
  <tlib-version>1.1</tlib-version>
  <short-name>myfn</short-name>
  <uri>http://lsk.com</uri>//引入自定义函数地址
  
   <function>
    <description>
     select all category
    </description>
    <name>findAllCategories</name>//自定义方法名
    <function-class>com.yinhe.dao.CategoryDao</function-class>//类的路径
    <function-signature>java.util.List findAllCategories()</function-signature>//返回类型 和类所调用的方法
  
  </function>
 </taglib>
前台调用${myfn:findAllCategories() },这里需要注意的是CategoryDao类中的findAllCategories方法必须为static的,不然前台调用会报错。
商品图片上传,用到了两个jar包commons-fileupload-1.2.1.jar 和commons-io-1.4.jar,主要实现代码为

//创建文件项目工厂
		DiskFileItemFactory factory=new DiskFileItemFactory();
		//创建一个文件上传解析器
		ServletFileUpload upload=new ServletFileUpload(factory);
		//判断表单enctype为否为mutipart-data
		
		if(upload.isMultipartContent(request)){
			//解析request对象,并把表单中的每一个输入项包装成一个fileItem 对象,并返回一个保存了所有FileItem的list集合。
			List<FileItem> list=upload.parseRequest(request);
			for (FileItem fileItem : list) {
				if (fileItem.isFormField()) {//普通表单处理
					map.put(fileItem.getFieldName(), fileItem.getString("UTF-8"));
				}else {
					//文件上传
					if (fileItem.getSize()>0) {
					String fileName=fileItem.getName();
					InputStream is=fileItem.getInputStream();
					FileOutputStream out=new FileOutputStream(new File(path, fileName));
					IOUtils.copy(is, out);
					IOUtils.closeQuietly(is);
					IOUtils.closeQuietly(out);
					fileItem.delete();
				}
				}
			}
商品编辑,对商品信息进行修改,用到了回显,修改时要判断是否上传了新的商品图片,如果是则把新图片上传到服务器,并修改各个字段,然后把原来的图片删除了,如果否,不用进行图片的上传,直接修改其他字段即可。

3.订单管理

这里是显示用户所购买过的订单,所以只要显示出来即可,不需要进行修改,同时也要把每个订单下的商品通过点击订单详情弹出一个弹出框,将商品信息显示在弹出框里,这样就需要我们进行手动的对数据进行封装,每个订单含有一个订单子项集合,每个订单集合中又有商品对象等信息,所以就需要对查出来的数据进行两层封装,

public List<Orders> getOrders(int nowpage,int pagesize) throws SQLException{
		String sql="select * from orders limit ?,?";
		QueryRunner qr=new QueryRunner(DataSourceUtils.getDataSource());
		List<Orders> orders=qr.query(sql, new BeanListHandler<Orders>(Orders.class),(nowpage-1)*pagesize,pagesize);
		for (Orders orders2 : orders) {
			String sql2="select * from orderitem where oid=?";
			List<Orderitem> orderitems=qr.query(sql2, new BeanListHandler<Orderitem>(Orderitem.class),orders2.getOid());
			orders2.setItems((ArrayList)orderitems);
			for (Orderitem orderitem : orderitems) {
				String sql3="select * from product where pid=?";
				Product p=qr.query(sql3, new BeanHandler<Product>(Product.class),orderitem.getPid());
				orderitem.setProduct(p);
			}
		}
		
		
		
		return orders;
	}
前台显示遍历集合,创建当前所有订单的弹出框并隐藏,以每个订单号给弹出框及按钮定义类和id,点击按钮调用插件定义的方法,通过不同订单号,来显示当前点击订单下的订单详情。

<script type="text/javascript">
			$(function(){
				//弹出层插件调用
				<c:forEach items="${list }" var="order" varStatus="vs">
				new PopupLayer({
					trigger:".clickedElement_${order.oid }",
					popupBlk:"#showDiv_${order.oid }",
					closeBtn:"#closeBtn_${order.oid }",
					useOverlay:true
				});
				</c:forEach>
				
			});
		</script>

BaseServlet的抽取,如果一个请求对应一个servlet类那么一个网站将会有成百上千个请求,也将对应这些类,于是我们就用到了BaseServlet的抽取,原理是反射,每个servlet类继承BaseServlet类,请求后加入参数method和值,就会自动找到该类中的方法进行处理

package com.yinhe.web.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;

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

public class BaseServlet extends HttpServlet {

	
	@Override
	protected void service(HttpServletRequest arg0, HttpServletResponse arg1)
			throws ServletException, IOException {
		arg0.setCharacterEncoding("UTF-8");
		arg1.setCharacterEncoding("UTF-8");
		String method=arg0.getParameter("method");
		Class clazz=this.getClass();
		try {
			Method m=clazz.getMethod(method, HttpServletRequest.class,HttpServletResponse.class);
			m.invoke(this, arg0,arg1);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	



}


二,商城前台

1.用户注册

注册页面的表单采用了validate插件进行了相应的验证,同时用户名也用了validate自定义方法来验证用户名是否存在,前台通过ajax来发送请求,后台根据用户填写的用户名去数据库查询,根据查询的结果向前台输出一个json类型的字符串,前台根据这个json字符串来判断用户名是否存在

$.validator.addMethod("checkUN",function(){
		var flag = false;
		$.ajax({
			url:"${pageContext.request.contextPath}/user?method=checkUser",
			data:{"username":$("#username").val()},
			dataType:"json",
			type:"post",
			//true 异步
			//false 同步
			async:false,
			//T2
			success:function(data){
				if (data=='0')
					flag = true;
			},error:function(e){
				alert(e.responseText);
			}
		});
		return flag;
	},"用户名已存在");
当用户正确输入所有信息后,点击注册,servlet处理请求,封装user对象,由于属性较多,我们用BeanUtils类中的populate(object, map)方法来进行封装,需要注意的是前台表单name值要和对象属性名一致,封装好后对数据库进行插入数据然后发送邮件

if (us.addUser(user)) {
			String emailMsg = "恭喜您注册成功,请点击下面的连接进行激活账户"
					+ "<a href='http://localhost:8080/Shopping/user?method=activation&&activation="+user.getCode()+"'>激活</a>";

			try {
				MailUtils.sendMail(user.getEmail(), emailMsg);
				response.sendRedirect("/Shopping/registerSuccess.jsp");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				response.sendRedirect("/Shopping/registerFail.jsp");
			}
			//response.sendRedirect("/Shopping/login.jsp");
		}


这时会向用户所填的邮箱了发送激活邮件,用户点击邮箱中的激活链接即可激活,在数据库中state字段来判断用户是否激活,不激活则不能登录,实现邮箱验证需要发送者邮箱开通SMTP协议,还要用到工具类MailUtils.java和jar包mail.jar

package com.yinhe.utils;

import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;

public class MailUtils {

	public static void sendMail(String email, String emailMsg)
			throws AddressException, MessagingException {
		// 1.创建一个程序与邮件服务器会话对象 Session

		Properties props = new Properties();
		props.setProperty("mail.transport.protocol", "SMTP");
		props.setProperty("mail.host", "smtp.163.com");
		props.setProperty("mail.smtp.auth", "true");// 指定验证为true

		// 创建验证器
		Authenticator auth = new Authenticator() {
			public PasswordAuthentication getPasswordAuthentication() {
				return new PasswordAuthentication("peiyifeitest222@163.com", "peiyifei888");
			}
		};

		Session session = Session.getInstance(props, auth);

		// 2.创建一个Message,它相当于是邮件内容
		Message message = new MimeMessage(session);

		message.setFrom(new InternetAddress("peiyifeitest222@163.com")); // 设置发送者

		message.setRecipient(RecipientType.TO, new InternetAddress(email)); // 设置发送方式与接收者

		message.setSubject("用户激活");
		// message.setText("这是一封激活邮件,请<a href='#'>点击</a>");

		message.setContent(emailMsg, "text/html;charset=utf-8");

		// 3.创建 Transport用于将邮件发送

		Transport.send(message);
	}
}

用户点击链接后再对user表中state字段值进行修改,然后跳转到登录界面。

2.用户登录,注销

就是获取用户从前台输入的用户名和密码,对user表进行查询,如果信息存在则将user对象存到session中,跳转到首页,这里有个功能是自动登录,如果用户点过自动登录后,关闭浏览器下次再打开此网站就不用再登录了,这个功能使用了过滤器,首先判断用户是否选择了自动登录,如果是就将用户名和密码存到cookie中,

String uname=request.getParameter("username");
		String psw=request.getParameter("password");
		String auto=request.getParameter("auto");
		
		if ("on".equals(auto)) {
			Cookie cookie=new Cookie("uname", uname);
			Cookie cookie2=new Cookie("psw", psw);
			cookie.setMaxAge(60*60);
			cookie2.setMaxAge(60*60);
			response.addCookie(cookie2);
			response.addCookie(cookie);
		}
		User u=us.login(uname,psw);
		if (u!=null) {
			
			request.getSession().setAttribute("user", u);
			response.sendRedirect("index.jsp");
		}else {
			request.setAttribute("message", "用户名或密码错误");
			request.getRequestDispatcher("login.jsp").forward(request, response);
		}
创建过滤器AutoLogin.java,然后在web.xml配置 表示每个请求都要来到这个过滤器处理

 <filter>
  		<filter-name>auto</filter-name>
  		<filter-class>com.yinhe.fiter.AutoLogin</filter-class>
  </filter>
  <filter-mapping>
  		<filter-name>auto</filter-name>
  		<url-pattern>/*</url-pattern>
  </filter-mapping>

package com.yinhe.fiter;

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.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.yinhe.bean.User;
import com.yinhe.service.UserService;
import com.yinhe.web.servlet.UserServlet;

public class AutoLogin implements Filter{

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void doFilter(ServletRequest arg0, ServletResponse arg1,
			FilterChain arg2) throws IOException, ServletException {
		// TODO Auto-generated method stub
		HttpServletRequest request=(HttpServletRequest) arg0;
		HttpServletResponse response=(HttpServletResponse)arg1;
		if (request.getSession().getAttribute("user")==null) {
			
		
		Cookie cookie[]=request.getCookies();
		if (cookie!=null) {
			String uname="";
			String psw="";
			for (Cookie cookie2 : cookie) {
				if (cookie2.getName().equals("uname")) {
					uname=cookie2.getValue();
				}
				if (cookie2.getName().equals("psw")) {
					psw=cookie2.getValue();
				}
			}
			UserService us=new UserService();
			User user=us.login(uname, psw);
			request.getSession().setAttribute("user", user);
		}
		}
		arg2.doFilter(request, response);
		
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		// TODO Auto-generated method stub
		
	}

}

在过滤器中遍历cookie,如果找到登录时保存的cookie则进行自动登录。


注销就是将我们保存在session中的user和保存在cookie中的用户名和密码进行删除

		Cookie[] cookies = request.getCookies();
		if (cookies != null){
			for (Cookie cookie : cookies) {
				if (cookie.getName().equals("username") || cookie.getName().equals("password")){
					//删除cookie 
					cookie.setMaxAge(0);
					response.addCookie(cookie);
				}	
			}
		}
		request.getSession().removeAttribute("user");


3.主页信息

主页主要信息有商品分类标题,最热商品和最新商品,我们要把它们从数据库中查询出来,首先是商品分类标题,因为这个是不经常改变的,所以我们用redis服务器来将这些信息保存在缓存中,这样不用每次刷新页面都去数据库中查询,同时首次查询也采用了ajax发送请求来进行查询,后台将查询到的List<Category>集合转换成json字符串,因为手动将集合转为json字符串比较复杂,所以我们用Gson类中的toJson方法来进行转换,使用前需要先导入jar包gson-2.2.4.jar,也可以使用JSONArray.fromObject(list).toString()方法转换,前提也需要导入jar包json-lib-2.4-jdk15.jar,当管理员修改这些标题后,我们要重新查询和保存,所以我们用保存在application域中的flag进行判断,默认值为0,修改后则为1

	Jedis jedis=JedisPoolUtils.getJedis();
		String json_list ="";
		if (jedis.get("json_list")==null||"1".equals(request.getServletContext().getAttribute("flag"))) {
			
			request.getServletContext().setAttribute("flag", "0");
			List<Category> list=cs.findAllCategories();
			request.setAttribute("list", list);
			
			//json格式转换
			Gson gson = new Gson();
			json_list = gson.toJson(list);
			System.out.println("数据库查询");
			
			jedis.set("json_list", json_list);
			
		}else {
			json_list=jedis.get("json_list");
		}
		
		response.getWriter().println(json_list);
			
		

	
	}
最热商品和最新商品根据数据库中的is_hot和pdate字段进行查询即可。


4.分类列表商品展示

用户点击商品分类标签后,发送请求,根据标签id来进行显示此分类下的商品,此页面也有分页查询,原理都一样,在此不再过多介绍,


5.商品详情展示

根据商品id查询数据库,然后在前台显示。


6.浏览记录

将点击过商品的id以!链接成字符串保存在cookie中,保存的时候要判断是不是第一次点击该商品,如果是就将该商品id添加到字符串首位,否则就移除原来的pid,再将pid添加到首位,显示的时候,找到保存在cookie中的字符串,以!分割成数组,遍历数组进行查询,将这些商品保存在list集合中,供前台使用

保存商品id

	//浏览记录
		String pids=pid;
		Cookie[] cookies=request.getCookies();
		if (cookies!=null) {
			for (Cookie cookie : cookies) {
				if ("pids".equals(cookie.getName())) {//寻找保存name为pid的cookie
					//以!分割字符串为数组
					String[] pidStrings=cookie.getValue().split("!");
					//将字符串转化为LinkedList
					List<String> list=Arrays.asList(pidStrings);
					LinkedList<String> pidList=new LinkedList<String>(list);
					//如果不是第一次点击
					if (pidList.contains(pid)) {
						//移除原来的,把这次放在首位
						pidList.remove(pid);
						pidList.addFirst(pid);
					}else {
						pidList.addFirst(pid);
					}
					if (pidList.size()>5) {
						pidList.subList(5, pidList.size()).clear();
					}
					pids=StringUtils.join(pidList,"!");
				}
			}
		}
	
		Cookie cookie=new Cookie("pids", pids);
		response.addCookie(cookie);


显示浏览记录

List<Product> list2=new ArrayList<Product>();
		Cookie[] cookies=request.getCookies();
		if (cookies!=null) {
			for (Cookie cookie : cookies) {
				if (cookie.getName().equals("pids")) {
					String pid[]=cookie.getValue().split("!");
					for (String string : pid) {
						
						Product p=ss.getProduct(string);
						list2.add(p);
					}
				}
			}
		}
		request.setAttribute("list2", list2);

7.购物车

由于数据库中没有购物车表,所以我们将购物车内的商品信息保存在session作用域中,为了更方便操作,我们需要对购物车进行封装,创建cart类和cartitem类,cart类中有HashMap<String,CartItem> cartItems和总计,cartitem类种有商品对象,数量和小计。

加入购物车

String pid=request.getParameter("pid");
		int buyNum=Integer.parseInt(request.getParameter("buyNum"));
		Product product=ss.getProduct(pid);
		
		Cart cart=(Cart) request.getSession().getAttribute("cart");
		//如果cart为空,初始化cart
		if (cart==null) {
			cart=new Cart();
		}
		//判断cart中有没有当前商品
		if (cart.getCartItems().containsKey(pid)) {
			//如果有更新数量和小计
			CartItem c=cart.getCartItems().get(pid);
			c.setBuyNum(c.getBuyNum()+buyNum);
			c.setSubTotal(c.getSubTotal()+product.getShop_price()*buyNum);
			cart.setTotal(cart.getTotal()+product.getShop_price()*buyNum);
		}else {
			//如果没有,将商品加入购物车
			CartItem cartItem=new CartItem();
			cartItem.setProduct(product);
			cartItem.setBuyNum(buyNum);
			cartItem.setSubTotal(product.getShop_price()*buyNum);
			cart.getCartItems().put(pid, cartItem);
			cart.setTotal(cart.getTotal()+product.getShop_price()*buyNum);
		}
		request.getSession().setAttribute("cart", cart);

删除购物车内某个商品

String pid=request.getParameter("pid");
		int buyNum=Integer.parseInt(request.getParameter("buyNum"));
		Product product=ss.getProduct(pid);
		Cart cart=(Cart) request.getSession().getAttribute("cart");
		HashMap<String, CartItem> m=cart.getCartItems();
		m.remove(pid);
		cart.setCartItems(m);
		cart.setTotal(cart.getTotal()-product.getShop_price()*buyNum);
		request.getSession().setAttribute("cart", cart);

修改某个商品的数量,前台用到了ajax,用每个商品id给数量input标签的id赋值,用来判断修改的是哪个商品

String pid=request.getParameter("pid");
		int buyNum=1;
		if (!request.getParameter("buyNum").equals("") ){
			buyNum=Integer.parseInt(request.getParameter("buyNum"));
		}
		
		if (buyNum<=0) {
			buyNum=1;
		}
		Product product=ss.getProduct(pid);
		Cart cart=(Cart) request.getSession().getAttribute("cart");
		HashMap<String, CartItem> m=cart.getCartItems();
		CartItem item=m.get(pid);
		//获得原来的数量
		int num=item.getBuyNum();
		//设置新的小计
		item.setSubTotal(product.getShop_price()*buyNum);
		item.setBuyNum(buyNum);
		m.put(pid, item);
		
		//设置新的总价
		cart.setTotal(cart.getTotal()-product.getShop_price()*num+product.getShop_price()*buyNum);
		
		cart.setCartItems(m);
		
		request.getSession().setAttribute("cart", cart);
		
		//小计
		double subTotal=product.getShop_price()*buyNum;
		//总价
		
		double total=cart.getTotal();
		double[] d=new double[2];
		d[0]=subTotal;
		d[1]=total;
		String jsona="";
		Gson gson=new Gson();
		jsona=gson.toJson(d);
		response.getWriter().println(jsona);
清空购物车

从session域中清除cart即可。


8.提交订单
点击订单提交后,把订单信息存到order表中,来到提交订单页面,输入收货人,地址,电话并选择支付银行后点击确认订单,首先对数据库order表中的数据进行修改,之后付款,这里用到了易宝支付,导入相应的jar包

servlet代码
	Map<String, String[]> map=request.getParameterMap();
		Orders orders=new Orders();
		BeanUtils.populate(orders, map);
		//更新数据库
		os.updateOrders(orders);
		
		//跳转到第三方支付页面
		//获得支付所需数据
		String oid=request.getParameter("oid");
		String money="0.01";//支付金额
		//银行
		String pd_FrpId=request.getParameter("pd_FrpId");
		// 发给支付公司需要哪些数据
				String p0_Cmd = "Buy";
				String p1_MerId = ResourceBundle.getBundle("merchantInfo").getString("p1_MerId");
				String p2_Order = oid;
				String p3_Amt = money;
				String p4_Cur = "CNY";
				String p5_Pid = "";
				String p6_Pcat = "";
				String p7_Pdesc = "";
				// 支付成功回调地址 ---- 第三方支付公司会访问、用户访问
				// 第三方支付可以访问网址
				String p8_Url = ResourceBundle.getBundle("merchantInfo").getString("callback");
				String p9_SAF = "";
				String pa_MP = "";
				String pr_NeedResponse = "1";
				// 加密hmac 需要密钥
				String keyValue = ResourceBundle.getBundle("merchantInfo").getString(
						"keyValue");
				String hmac = PaymentUtil.buildHmac(p0_Cmd, p1_MerId, p2_Order, p3_Amt,
						p4_Cur, p5_Pid, p6_Pcat, p7_Pdesc, p8_Url, p9_SAF, pa_MP,
						pd_FrpId, pr_NeedResponse, keyValue);


				String url = "https://www.yeepay.com/app-merchant-proxy/node?pd_FrpId="+pd_FrpId+
						"&p0_Cmd="+p0_Cmd+
						"&p1_MerId="+p1_MerId+
						"&p2_Order="+p2_Order+
						"&p3_Amt="+p3_Amt+
						"&p4_Cur="+p4_Cur+
						"&p5_Pid="+p5_Pid+
						"&p6_Pcat="+p6_Pcat+
						"&p7_Pdesc="+p7_Pdesc+
						"&p8_Url="+p8_Url+
						"&p9_SAF="+p9_SAF+
						"&pa_MP="+pa_MP+
						"&pr_NeedResponse="+pr_NeedResponse+
						"&hmac="+hmac;

				//重定向到第三方支付平台
				response.sendRedirect(url);

merchantInfo.properties文件

p1_MerId=10001126856		#易宝用户id
keyValue=cl522AV6q613Ii4W6u8K6XuW8vM1N6bFgyv769220IuYe9u37N4y7rI4Pl	#秘钥
callback=http://localhost:8080/callback		#支付成功后回调

回调

CallbackServlet.java

package com.yinhe.web.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ResourceBundle;

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

import com.yinhe.service.OrderService;
import com.yinhe.utils.PaymentUtil;

public class CallbackServlet extends BaseServlet {

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

	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	
		// 获得回调所有数据
		String p1_MerId = request.getParameter("p1_MerId");
		String r0_Cmd = request.getParameter("r0_Cmd");
		String r1_Code = request.getParameter("r1_Code");
		String r2_TrxId = request.getParameter("r2_TrxId");
		String r3_Amt = request.getParameter("r3_Amt");
		String r4_Cur = request.getParameter("r4_Cur");
		String r5_Pid = request.getParameter("r5_Pid");
		//订单编号
		String r6_Order = request.getParameter("r6_Order");
		String r7_Uid = request.getParameter("r7_Uid");
		String r8_MP = request.getParameter("r8_MP");
		String r9_BType = request.getParameter("r9_BType");
		String rb_BankId = request.getParameter("rb_BankId");
		String ro_BankOrderId = request.getParameter("ro_BankOrderId");
		String rp_PayDate = request.getParameter("rp_PayDate");
		String rq_CardNo = request.getParameter("rq_CardNo");
		String ru_Trxtime = request.getParameter("ru_Trxtime");
		// 身份校验 --- 判断是不是支付公司通知你
		String hmac = request.getParameter("hmac");
		String keyValue = ResourceBundle.getBundle("merchantInfo").getString(
				"keyValue");

		// 自己对上面数据进行加密 --- 比较支付公司发过来hamc
		boolean isValid = PaymentUtil.verifyCallback(hmac, p1_MerId, r0_Cmd,
				r1_Code, r2_TrxId, r3_Amt, r4_Cur, r5_Pid, r6_Order, r7_Uid,
				r8_MP, r9_BType, keyValue);

		if (isValid) {
			// 响应数据有效
			if (r9_BType.equals("1")) {
				//修改订单状态
				OrderService orderService=new OrderService();
				orderService.updateState(r6_Order);
				// 浏览器重定向
				response.setContentType("text/html;charset=utf-8");
				response.getWriter().println("<h1>付款成功!等待商城进一步操作!等待收货...</h1>");
			} else if (r9_BType.equals("2")) {
				// 服务器点对点 --- 支付公司通知你
				System.out.println("付款成功!");
				// 修改订单状态 为已付款
				// 回复支付公司
				response.getWriter().print("success");
			}
		} else {
			// 数据无效
			System.out.println("数据被篡改!");
		}
	}

}
支付成功后修改订单状态为已付款

9.我的订单

显示当前用户以购买过的订单,从数据库查询即可,这里也要进行数据封装,和后台管理员查询订单原理相同。

10.登录验证过滤器

订单的相关操作必须进行登录才可以,如果没登录,则自动跳转到登录界面

自定义过滤器Login.java

package com.yinhe.fiter;

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.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.yinhe.bean.User;

public class Login implements Filter{

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		// TODO Auto-generated method stub
		HttpServletRequest req=(HttpServletRequest) request;
		HttpServletResponse resp=(HttpServletResponse)response;
		
		User user=(User) req.getSession().getAttribute("user");
		System.out.println(user);
		if (user==null) {
			resp.sendRedirect("login.jsp");
		}else {
			
		
		chain.doFilter(request, response);
		}
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub
		
	}

}
web.xml配置,表示对订单的相关操作必须进行登录才可以。

 <filter>
  		<filter-name>login</filter-name>
  		<filter-class>com.yinhe.fiter.Login</filter-class>
  </filter>
  <filter-mapping>
  		<filter-name>login</filter-name>
  		<url-pattern>/ordersservlet</url-pattern>
  </filter-mapping>

到此这个项目的所有功能都结束了,温故而知新。


  • 8
    点赞
  • 115
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值