SSH框架网上商城项目第2战之基本增删查改、Service和Action的抽取

上一节《SSH框架网上商城项目第1战之整合Struts2、Hibernate4.3和Spring4.2》我们搭建好了Struts2、Hibernate和Spring的开发环境,并成功将它们整合在一起。这节主要完成一些基本的增删改查以及Service、Dao和Action的抽取。
1. Service层的抽取
        上一节中,我们在service层简单写了save和update方法,这里我们开始完善该部分的代码,然后对service层的代码进行抽取。
1.1 完善CategoryService层
        对数据库的操作无非是增删改查,首先我们来完善CategoryService层的接口和实现:

//CategoryService接口
public interface CategoryService extends BaseService<Category> { 

 public void save(Category category); //插入 

 public void update(Category category);//更新 

 public void delete(int id); //删除 

 public Category get(int id); //获取一个Category 

 public List<Category> query(); //获取全部Category 

}

对CategoryService接口的具体实现:

public class CategoryServiceImpl extends BaseServiceImpl<Category> implements CategoryService { 

 private SessionFactory sessionFactory; 

 //Spring会注进来
 public void setSessionFactory(SessionFactory sessionFactory) {
 this.sessionFactory = sessionFactory;
 } 

 protected Session getSession() {
 //从当前线程获取session,如果没有则创建一个新的session
 return sessionFactory.getCurrentSession();
 } 

 @Override
 public void save(Category category) {
 getSession().save(category);
 } 

 @Override
 public void update(Category category) {
 getSession().update(category);
 } 

 @Override
 public void delete(int id) {
 /*第一种方法有个弊端,就是没删除一次得先查询一次
 Object obj = getSession().get(Category.class, id);
 if(obj != null) {
  getSession().delete(obj);
 }*/
 String hql = "delete Category while id=:id";
 getSession().createQuery(hql) //
  .setInteger("id", id) //
  .executeUpdate();
 } 

 @Override
 public Category get(int id) {
 return (Category) getSession().get(Category.class, id);
 } 

 @Override
 public List<Category> query() {
 String hql = "from Category";
 return getSession().createQuery(hql).list();
 }
}

1.2 Service层抽取实现
完成了CategoryService后,我们来抽取Service层的基础实现。思路是这样的:我们抽取一个基础接口BaseService以及基础接口的实现BaseServiceImpl,后面开发的时候,如果需要新的Service,只需要做两步即可:首先定义一个新的接口xxxService继承BaseService接口,这个接口可以增加新的抽象方法;然后定义一个新的实现类xxxServiceImpl继承BaseServiceImpl并实现xxxService接口即可。这样更加便于项目的维护。
我们先根据上面的CategoryService接口来创建BaseService接口:

//基础接口BaseService,使用泛型
public interface BaseService<T> {
 public void save(T t); 

 public void update(T t); 

 public void delete(int id); 

 public T get(int id); 

 public List<T> query();
}

然后再根据CategoryServiceImpl实现类创建BaseService接口的实现类BaseServiceImpl:

/**
 * @Description TODO(公共模块的抽取)
 * @author eson_15
 *
 */
@SuppressWarnings("unchecked")
public class BaseServiceImpl<T> implements BaseService<T> { 

 private Class clazz; //clazz中存储了当前操作的类型,即泛型T
 private SessionFactory sessionFactory; 

 public BaseServiceImpl() {
  //下面三个打印信息可以去掉,这里是给自己看的
  System.out.println("this代表的是当前调用构造方法的对象" + this);
 System.out.println("获取当前this对象的父类信息" + this.getClass().getSuperclass());
 System.out.println("获取当前this对象的父类信息(包括泛型信息)" + this.getClass().getGenericSuperclass());
 //拿到泛型的参数类型
 ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
 clazz = (Class)type.getActualTypeArguments()[0];
 } 

 public void setSessionFactory(SessionFactory sessionFactory) {
 this.sessionFactory = sessionFactory;
 } 

 protected Session getSession() {
 //从当前线程获取session,如果没有则创建一个新的session
 return sessionFactory.getCurrentSession();
 } 

 @Override
 public void save(T t) {
 getSession().save(t);
 } 

 @Override
 public void update(T t) {
 getSession().update(t);
 } 

 @Override
 public void delete(int id) {
 System.out.println(clazz.getSimpleName());
 String hql = "delete " + clazz.getSimpleName() + " as c where c.id=:id";
 getSession().createQuery(hql) //
   .setInteger("id", id) //
   .executeUpdate();
 } 

 @Override
 public T get(int id) {
 return (T) getSession().get(clazz, id);
 } 

 @Override
 public List<T> query() {
 String hql = "from " + clazz.getSimpleName();
 return getSession().createQuery(hql).list();
 } 

}

抽取完了后,我们就可以改写CategoryService接口和CategoryServiceImpl实现类了。如下:

//CategoryService接口继承BaseService接口
public interface CategoryService extends BaseService<Category> {
 /*
 * 只要添加CategoryService本身需要的新的方法即可,公共方法已经在BaseService中了
 */
} 

/**
 * @Description TODO(模块自身的业务逻辑)
 * @author eson_15
 *
 */
public class CategoryServiceImpl extends BaseServiceImpl<Category> implements CategoryService { 

 /*
 * 只需实现CategoryService接口中新增的方法即可,公共方法已经在BaseServiceImpl中实现了
 */
}

从代码中可以看出,新增的Service只需要继承BaseService接口,然后在接口中新增本Service所需要的业务逻辑即可。新增的ServiceImpl只需要继承BaseServiceImpl并实现新增的业务逻辑即可。
        但是别忘了很重要的一点:就是修改Spring的配置文件beans.xml中的bean

<!-- 泛型类是不能实例化的,所以要加lazy-init属性 -->
<bean id="baseService" class="cn.it.shop.service.impl.BaseServiceImpl" lazy-init="true">
 <property name="sessionFactory" ref="sessionFactory" />
</bean> 

<bean id="categoryService" class="cn.it.shop.service.impl.CategoryServiceImpl" parent="baseService"/>

将原来categoryService中的property干掉,然后增加parent属性,指明继承baseService;然后配置一下baseService,将sessionFactory配到baseService中去,另外要注意一点:设置lazy-init属性为true,因为baseService是泛型类,泛型类是不能实例化的。至此,Service层的抽取就搞定了。

2. Service层添加一个Account
        刚刚抽取好了Service层,那么现在我们想写一个Account(管理员)的service就很简单了:
        首先写一个AccountService接口继承BaseService:

public interface AccountService extends BaseService<Account> { //注意BaseService里的泛型现在是Account
 /*
 * 只要添加AccountService本身需要的新的方法即可,公共方法已经在BaseService中了
 */
}

然后写一个AccountServiceImpl实现类继承BaseServiceImpl实现类,并实现AccountService接口即可:

public class AccountServiceImpl extends BaseServiceImpl<Account> implements AccountService { 

 /*
 * 只需实现AccountService接口中新增的方法即可,公共方法已经在BaseServiceImpl中实现了
 */ 

 //管理登陆功能,后期再完善
}

最后在beans.xml文件里加上如下配置:
<bean id="accountService" class="cn.it.shop.service.impl.AccountServiceImpl" parent="baseService" />  
        这样就写好了一个新的service了,以后需要添加service就遵循这个流程,非常方便。
3. Action的抽取
3.1 Action中往域(request,session,application等)中存数据
        我们知道,在Action中可以直接通过ActionContext.getContext()去获取一个ActionContext对象,然后通过该对象再去获得相应的域对象;也可以通过实现xxxAware接口来注入相应的域对象。我们先来看一下这两种方法:

public class CategoryAction extends ActionSupport implements RequestAware,SessionAware,ApplicationAware{ 

 private Category category; 

 private CategoryService categoryService; 

 public void setCategoryService(CategoryService categoryService) {
  this.categoryService = categoryService;
 } 

 public String update() {
 System.out.println("----update----");
 categoryService.update(category);
 return "index";
 } 

 public String save() {
 System.out.println("----save----");
 return "index";
 } 

 public String query() {
  //解决方案一,采用相应的map取代原来的内置对象,这样与jsp没有依赖,但是代码量比较大
 // ActionContext.getContext().put("categoryList", categoryService.query()); //放到request域中
 // ActionContext.getContext().getSession().put("categoryList", categoryService.query()); //放到session域中
 // ActionContext.getContext().getApplication().put("categoryList", categoryService.query()); //放到application域中 

 //解决方案二,实现相应的接口(RequestAware,SessionAware,ApplicationAware),让相应的map注入
 request.put("categoryList", categoryService.query());
 session.put("categoryList", categoryService.query());
 application.put("categoryList", categoryService.query());
 return "index";
 } 

 public Category getCategory() {
 return category;
 } 

 public void setCategory(Category category) {
 this.category = category;
 } 

 private Map<String, Object> request;
 private Map<String, Object> session;
 private Map<String, Object> application; 

 @Override
 public void setApplication(Map<String, Object> application) {
 this.application = application;
 } 

 @Override
 public void setSession(Map<String, Object> session) {
 this.session = session;
 } 

 @Override
 public void setRequest(Map<String, Object> request) {
 this.request = request;
 }
}

还是上一节整合三大框架时的CategoryAction类,我们在里面加了一个query方法,在该方法中,我们通过向request域、session域和application域中存入查询的结果。第一种方法是直接使用ActionContext来实现,不需要实现任何接口,但是代码量较大;第二种方法通过实现RequestAware、SessionAware和ApplicationAware接口,实现该接口的三个抽象方法把request、session和application注入进来,然后赋给相应的成员变量中,这样就可以在query方法中向域中存放查询结果了。这代码量貌似比第一种方法更大……但是我们可以抽取,先往下看。
我们在index.jsp中新加一个查询连接来测试能否将查询结果显示出来:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
 <head>
 <title>My JSP 'index.jsp' starting page</title>
 </head> 

 <body>
 <a href="${pageContext.request.contextPath }/category_update.action?category.id=2&category.type=gga&category.hot=false">访问update</a>
 <a href="category_save.action">访问save</a>
 <a href="category_query.action">查询所有类别</a><br/>
 <c:forEach items="${requestScope.categoryList }" var="category">
 ${category.id } | ${category.type } | ${category.hot } <br/>
 </c:forEach> 

 <c:forEach items="${sessionScope.categoryList }" var="category">
 ${category.id } | ${category.type } | ${category.hot } <br/>
 </c:forEach> 

 <c:forEach items="${applicationScope.categoryList }" var="category">
 ${category.id } | ${category.type } | ${category.hot } <br/>
 </c:forEach>
 </body>
</html>

3.2 抽取BaseAction
        刚刚提到了,第二种方法的代码量更大,但是我们可以抽取一个BaseAction,专门处理这些域相关的操作。

public class BaseAction extends ActionSupport implements RequestAware,SessionAware,ApplicationAware { 

 protected Map<String, Object> request;
 protected Map<String, Object> session;
 protected Map<String, Object> application; 

 @Override
 public void setApplication(Map<String, Object> application) {
 this.application = application;
 } 

 @Override
 public void setSession(Map<String, Object> session) {
 this.session = session;
 } 

 @Override
 public void setRequest(Map<String, Object> request) {
 this.request = request;
 }
}

然后我们自己的Action如果需要用到这些域对象来存储数据时,直接继承BaseAction即可,就能直接使用request、session和application对象了。所以修改后的CategoryAction如下:

public class CategoryAction extends BaseAction { 

 private Category category;
<pre name="code" class="java">
 private CategoryService categoryService; 

 public void setCategoryService(CategoryService categoryService) {
  this.categoryService = categoryService;
 }
public String update() {System.out.println("----update----");categoryService.update(category); return "index"; }public String save() {System.out.println("----save----");return "index"; } public String query() {request.put("categoryList", categoryService.query()); session.put("categoryList", categoryService.query()); application.put("categoryList", categoryService.query()); return "index"; } public Category getCategory() { return category; } public void setCategory(Category category) {this.category = category; }}

后面所有要使用request、session和application域的Action,只要直接继承BaseAction即可,非常方便。
3.3 获取参数(ModelDriven)
        我们继续看上面的CategoryAction类,里面有个成员变量category,这是个POJO,定义这个变量并写好set和get方法是为了JSP页面可以通过url后面附带参数传进来,参数是category对象中的属性,比如id,type等,但是url中的参数必须写成category.id、category.type等。这样struts会自动将这写参数注入到category对象中,然后我们就可以直接使用这个category对象了,但是这样有点繁琐。我们可以使用ModelDriven来更方便的解决。

public class CategoryAction extends BaseAction implements ModelDriven<Category>{ 

 private Category category; 

 //使用ModelDriven接口必须要实现getModel()方法,此方法会把返回的项压到栈顶
 @Override
 public Category getModel() {
 category = new Category();
 return category;
 }
<pre name="code" class="java"> private CategoryService categoryService; 

 public void setCategoryService(CategoryService categoryService) {
  this.categoryService = categoryService;
 } 

 public String update() {
 System.out.println("----update----");
 categoryService.update(category);
 return "index";
 } 

 public String save() {
 System.out.println("----save----");
 return "index";
 } 

 public String query() {
 request.put("categoryList", categoryService.query());
 session.put("categoryList", categoryService.query());
 application.put("categoryList", categoryService.query());
 return "index";
 } 

}

这样我们在前台JSP页面就不用带category.id这种繁琐的参数了,看JSP页面中的ModelDriven部分:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
 <head>
 <title>My JSP 'index.jsp' starting page</title>
 </head> 

 <body>
 <a href="${pageContext.request.contextPath }/category_update.action?category.id=2&category.type=gga&category.hot=false">访问update</a>
 <a href="category_save.action?id=1&type=haha&hot=true">测试ModelDriven</a>
 <a href="category_query.action">查询所有类别</a><br/>
 <c:forEach items="${requestScope.categoryList }" var="category">
 ${category.id } | ${category.type } | ${category.hot } <br/>
 </c:forEach> 

 <c:forEach items="${sessionScope.categoryList }" var="category">
 ${category.id } | ${category.type } | ${category.hot } <br/>
 </c:forEach> 

 <c:forEach items="${applicationScope.categoryList }" var="category">
 ${category.id } | ${category.type } | ${category.hot } <br/>
 </c:forEach>
 </body>
</html>

测试结果是可以获得catgory,并且将id,type和hot属性全部赋值好。我们可以看出,通过实现ModelDriven接口,我们可以很方便的在url中携带参数,Action中只需要实现getModel方法,new一个要使用的对象返回即可。到这里我们很容易想到,struts中肯定会有很多这种model需要获取,所以这一块我们也要抽取到BaseAction中去。
3.4 抽取ModelDriven到BaseAction
        首先我们在BaseAction中添加ModelDriven部分的代码,如下:

//因为有很多不同的model都需要使用ModelDriven,所以这里使用泛型
public class BaseAction<T> extends ActionSupport implements RequestAware,SessionAware,ApplicationAware,ModelDriven<T> { 

 protected Map<String, Object> request;
 protected Map<String, Object> session;
 protected Map<String, Object> application; 

 protected T model; 

 @Override
 public void setApplication(Map<String, Object> application) {
 this.application = application;
 } 

 @Override
 public void setSession(Map<String, Object> session) {
 this.session = session;
 } 

 @Override
 public void setRequest(Map<String, Object> request) {
 this.request = request;
 } 

 @Override
 public T getModel() { //这里通过解析传进来的T来new一个对应的instance
 ParameterizedType type = (ParameterizedType)this.getClass().getGenericSuperclass();
 Class clazz = (Class)type.getActualTypeArguments()[0];
 try {
  model = (T)clazz.newInstance();
 } catch (Exception e) {
  throw new RuntimeException(e);
 }
 return model;
 }
}

抽取完了后,CategoryAction中的代码会越来越少:

//继承BaseAction,并且加上泛型
public class CategoryAction extends BaseAction<Category> { 

 private CategoryService categoryService; 

 public void setCategoryService(CategoryService categoryService) {
 this.categoryService = categoryService;
 } 

 public String update() {
 System.out.println("----update----");
 categoryService.update(model);//直接使用model
 return "index";
 } 

 public String save() {
 System.out.println("----save----");
 System.out.println(model); //直接使用model
 return "index";
 } 

 public String query() {
 request.put("categoryList", categoryService.query());
 session.put("categoryList", categoryService.query());
 application.put("categoryList", categoryService.query());
 return "index";
 } 

}

到这里,还有一个看着不爽的地方,就是categoryService这个成员变量,它一直存在在CategoryAction里,因为CategoryAction中有用到categoryService对象中的方法,所以必须得创建这个对象,并且有set方法才能注入进来。这就导致一个弊端:如果很多Action都需要使用categoryService的话,那就必须在它们的Action里创建这个对象和set方法,而且,如果一个Action中要使用好几个不同的service对象,那就得全部创建,这样就变得很冗杂。
3.5 抽取service到BaseAction
        针对上面的问题,我们将工程中所有的service对象都抽取到BaseAction中创建,这样其他Action继承BaseAction后,想用什么service就直接拿来用即可:

//我将BaseAction中的内容归归类了
public class BaseAction<T> extends ActionSupport implements RequestAware,SessionAware,ApplicationAware,ModelDriven<T> { 

 //service对象
 protected CategoryService categoryService;
 protected AccountService accountService; 

 public void setCategoryService(CategoryService categoryService) {
 this.categoryService = categoryService;
 }
 public void setAccountService(AccountService accountService) {
 this.accountService = accountService;
 } 

 //域对象
 protected Map<String, Object> request;
 protected Map<String, Object> session;
 protected Map<String, Object> application; 

 @Override
 public void setApplication(Map<String, Object> application) {
 this.application = application;
 }
 @Override
 public void setSession(Map<String, Object> session) {
 this.session = session;
 }
 @Override
 public void setRequest(Map<String, Object> request) {
 this.request = request;
 } 

 //ModelDriven
 protected T model;
 @Override
 public T getModel() {
 ParameterizedType type = (ParameterizedType)this.getClass().getGenericSuperclass();
 Class clazz = (Class)type.getActualTypeArguments()[0];
 try {
  model = (T)clazz.newInstance();
 } catch (Exception e) {
  throw new RuntimeException(e);
 }
 return model;
 }
}
 这样CategoryAction中就更加清爽了:
public class CategoryAction extends BaseAction<Category> { 

 public String update() {
 System.out.println("----update----");
 categoryService.update(model);
 return "index";
 } 

 public String save() {
 System.out.println("----save----");
 System.out.println(model);
 return "index";
 } 

 public String query() {
 request.put("categoryList", categoryService.query());
 session.put("categoryList", categoryService.query());
 application.put("categoryList", categoryService.query());
 return "index";
 } 

}

有人可能会问,BaseAction中注入了那么多service对象的话不会冗余么?这是不会的,因为就算不写在BaseAction中,Spring容器也是会创建这个对象的,这点没有关系,相反,service对象全放在BaseAction中更加便于其他Action的开发,而且BaseAction不需要配到struts.xml文件中,因为根本就没有哪个JSP会请求BaseAction,它只是让其他Action来继承用的。
        还有一点别忘了:那就是修改在beans.xml中的配置:

<!-- 如果是prototype类型,默认是使用时创建,不是启动时自动创建 -->
<bean id="baseAction" class="cn.it.shop.action.BaseAction" scope="prototype">
 <property name="categoryService" ref="categoryService"></property>
 <property name="accountService" ref="accountService"></property>
</bean> 

<bean id="categoryAction" class="cn.it.shop.action.CategoryAction" scope="prototype" parent="baseAction"/>

新加一个baseAction的bean,将工程中所有service对象作为property配好,将原来的categoryAction中的property干掉。
        以后我们如果要写新的xxxAction,直接继承BaseAction即可,如果xxxAction中有用到某个service,直接拿来用即可,只需要在beans.xml文件中加一个xxxAction对应的bean,在struts.xml文件中配置好跳转即可。

4. 将xml改成注解
        我们可以看到,随着项目越写越大,beans.xml中的配置会越来越多,而且很多配置有冗余,为了更加便于开发,我们现在将xml的配置改成注解的形式,我们先看一下beans.xml中的配置:

这些是我们之前搭建环境以及抽取的时候写的bean,这些都需要转换成注解的形式,下面我们一块一块的换掉:首先替换service部分,这部分有三个:baseService、categoryService和accountService。替换如下:

然后将beans.xml中的相应部分干掉即可。接下来修改ActIon部分,主要有baseAction、categoryAction和accountAction三个,替换如下:

然后再干掉beans.xml中的Action部分的配置即可,最后在beans.xml文件中添加一个如下配置,就可以使用注解了。
<context:component-scan base-package="cn.it.shop.."/> 
        有人可能会问,为什么service和action两个使用注解的时候不一样呢?service中使用的是@Service而action中使用的是@Controller呢?其实是一样的,只是为了区分它们是不同层的bean而已,便于阅读。

整个项目的源码下载地址:http://www.jb51.net/article/86099.htm

原文地址:http://blog.csdn.net/eson_15/article/details/51297698

以上就是SSH框架网上商城项目第2战的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • php 网上商城促销设计实例代码

    大体的思想,每一个促销要新建一个促销类,有专门的开关来控制是否生效. 用商品里面的促销识别码来判断具体调用哪一个促销实例. 首先,在添加商品的时候,分两步,第一步是添加状态,第二步是把购物车内的商品显示这个状态. 一,添加步骤几个重要的点: 1,添加商品之前,遍历所有的促销互斥条件. 例如,某一款商品不可以和另一个商品同时在一个购物车内:或者某个用户权限,不可以购买特定的一件商品等等. 2,添加商品之前,选择特定的促销实例,来进行添加之前的操作. 注:第二点与第一点的区别在于1是要遍历所有的促销

  • java网上商城开发之邮件发送功能(全)

    最近在学习网上商城时,接触到了一个邮件发送的功能.之前一直在使用邮箱进行发送邮件,但是其中的具体如何运转的却不知道是怎么回事.那么邮件发送究竟是怎么一回事呢? 邮件发送过程: 过程描述:首先是发送人将邮件通过客户端软件发送到特定的服务器上,然后通过电子邮件简单传输协议(SMTP)来进行传输,收件人通过POP3协议将邮件从服务器上接受回来.这样就实现了邮件之间的相互传送. 实现过程: 在有网络的情况下,我们可以直接使用搜狐.网易等邮箱进行发送.那么如何在没有网络的情况下,实现内部之间的发送呢? 首

  • php网上商城购物车设计代码分享

    首先,购物车的数据库设计: 1. id 2. goods_id 商品ID 3. session_id 购物车ID 4. goods_sn 商品编码 5. goods_name 商品名称 6. shop_price 商品商城售价 7. goods_price 商品真实售价(与shop_price的区别在于,当打折的时候,shop_price是打折之前商品的售价,而goods_price是打折之后的) 8. goods_number 数量 9. weight 商品重量 10. goods_attr

  • SSH框架网上商城项目第8战之查询和删除商品类别功能实现

    上一节我们完成了使用DataGrid显示所有商品信息,这节我们开始添加几个功能:添加.更新.删除和查询.首先我们实现下前台的显示,然后再做后台获取数据. 1. 添加.更新.删除和查询功能的前台实现 DataGrid控件里有个toolbar属性,是添加工具栏的,我们可以在toolbar属性中添加这些按钮来实现相应的功能.先看一下官方文档对toolbar的定义: 我们使用数组的方式定义工具栏,在query.jsp页面中新添加如下代码: <%@ page language="java"

  • SSH框架网上商城项目第4战之EasyUI菜单的实现

    上篇文章我们使用EasyUI搭建了后台页面的框架,点击这里查看,这一节我们主要使用EasyUI技术简单实现后台菜单,先将简单功能做出来,后期再继续丰富. 1. 实现左侧菜单 首先看一下效果图: 我们可以点击"基本操作"和"其他操作"来切换菜单选项,在具体的选项内,点击不同的连接,会在右侧显示出来.我们先把左边的菜单做出来. 左侧菜单内容主要有两个:"类别管理"和"商品管理".我们知道,上一节中,在aindex.jsp中应将后台

  • SSH框架网上商城项目第30战之项目总结(附源码下载地址)

    0. 写在前面 友情提示:下载地址在下面哦. 项目基本完成了,加上这个总结,与这个项目相关的博客也写了30篇了,积少成多,写博客的过程是固化思路的一个过程,对自己很有用,同时也能帮助别人.顺便说个题外话,在学习的过程中肯定会遇到很多异常出现,我们要做的首先是定位这个异常,一般异常的后面都会跟一个或多个Caused by:xxx,这些都是引起异常的原因,一般我们找最下面的一个Caused by,那里往往才是问题的根源.如果自己解决不了,可以去谷歌.百度搜索(搜索的时候别一大堆异常往上一贴,注意搜关

  • SSH框架网上商城项目第23战之在线支付功能实现

    上一节我们做好了支付页面的显示,从上一节支付页面显示的jsp代码中可以看出,当用户点击确认支付时,会跳到${shop}/pay_goBank.action的action,也就是说,提交后我们得在payAction中的goBank方法中处理一些逻辑(即21节demo中的那个流程图的逻辑),即获得明文,将明文加密成签名(密文)然后再去访问易宝服务器,易宝连接银行,完成支付. 但是考虑到MVC设计模式,我们会将上面这些业务逻辑放到Service层中处理,所以下面我们来实现21节中那个demo的支付逻辑

  • SSH框架网上商城项目第20战之在线支付平台

    之前已经完成了首页的显示,用户添加购物车,确认订单等功能,下面就是支付功能的开发了.用户确认了订单后会直接跳转到支付页面进行在线支付,在线支付需要第三方的接口,这一节主要介绍一些关于第三方支付的内容,从下一节开始,我们真正开发在线支付模块. 1. 在线支付介绍 在线支付是指卖方与买方通过因特网上的电子商务网站进行交易时,银行为其提供网上资金结算服务的一种业务.它为企业和个人提供了一个安全.快捷.方便的电子商务应用环境和网上资金结算工具.在线支付不仅帮助企业实现了销售款项的快速归集,缩短收款周期,

  • SSH框架网上商城项目第26战之订单支付后发送短信提醒

    上一节我们使用了Java mail完成了给买家发送邮件的功能,还遗留一个功能,就是给买家发送短信,告诉他订单已经生成之类的.这一节主要介绍一下如何在用户支付完成后自动给用户发送短信. 1. 申请短信发送功能 很明显,我们自己不能发短信,也没有做短信的功能,所以我们需要去借助第三方的运营商.但是像中国移动,联通,电信这种不会直接给我们提供短信服务,而是先把短信服务提供给一些运营商,然后这些运营商再提供给我们. 有一个运营商叫"中国网建sms短信通"(官网地址).这个运营商可以给我们提供短

  • java网上商城项目第1篇之用户注册模块

    本文为大家讲解了商城项目用户注册模块,供大家参考,先看看效果图: 1.前台JS校验: 事件触发: onsubmit="checkForm()" 2.使用AJAX完成异步用户名是否存在校验 ①事件触发:onblur="checkUserName()" ②AJAX function checkUsername(){ var username = $("#username").val(); $("#span1").load(&quo

随机推荐