首先提交订单前需要进行库存校验等一系列的准备操作流程,故可以在提交订单流程的基础上进行拦截器的预提交操作。
具体Demo如下:
首先编辑拦截器:
package com.sanbang.interceptors;
import org.apache.log4j.Logger;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class putOrderFromsInterceptor implements HandlerInterceptor {
private static Logger log = Logger.getLogger(putOrderFromsInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//在此可以添加库存校验等预提交代码的部分
System.out.println("putOrderFromsInterceptor-----------preHandle" );
log.info("putOrderFromsInterceptor-----------preHandle");
response.sendRedirect("/front/app/goods/trytest.htm?mess='jhgjh'");
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("putOrderFromsInterceptor-----------postHandle" );
log.info("putOrderFromsInterceptor-----------postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("putOrderFromsInterceptor-----------afterCompletion" );
log.info("putOrderFromsInterceptor-----------afterCompletion");
}
}
配置拦截器:
<mvc:interceptors>
<!--下单拦截 校验-->
<mvc:interceptor>
<!--下单接口的URL-->
<mvc:mapping path="/app/goods/dealImmediatelyBuyGood.htm"/>
<bean class="com.sanbang.interceptors.putOrderFromsInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
具体下单操作方法如下:
@RequestMapping(value = "/dealImmediatelyBuyGood")
@ResponseBody
@Transactional(rollbackFor=Exception.class,propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT,timeout=5000)
public synchronized Object dealImmediatelyBuyGood(HttpServletRequest request, HttpServletResponse response,
Long WeAddressId, Long goodsId, Double count) {
Map<String, Object> mmp = null;
Result rs = Result.failure();
try {
ezs_user user = RedisUserSession.getUserInfoByKeyForApp(request);
if (user == null) {
rs = Result.failure();
rs.setErrorcode(DictionaryCode.ERROR_WEB_SESSION_ERROR);
rs.setMsg("用户未登录");
return rs;
} else {
Long auditingusertype_id = user.getEzs_store().getAuditingusertype_id();
ezs_dict dictCode = dictService.getDictByThisId(auditingusertype_id);
if (dictCode.getSequence() <= 3) {
if (user.getEzs_store().getStatus() != 2) {
rs = Result.failure();
rs.setErrorcode(DictionaryCode.ERROR_WEB_PARAM_ERROR);
rs.setMsg("您还未完成实名认证,请去个人中心完成实名认证!");
return rs;
}
}
}
ezs_orderform orderForm = new ezs_orderform();
ezs_goods buyGoods = null;
// 修改订单号生成规则
try{
buyGoods = this.ezs_goodsMapper.selectByPrimaryKey(goodsId);
orderForm.setOrder_no(createOrderNo(buyGoods));
}catch(Exception e){
e.printStackTrace();
log.info("订单号生成失败");
}
boolean isour=this.childCompanyGoodsService.isChildCompanyGood(buyGoods);
if(isour){
mmp = this.childCompanyGoodsService.immediateAddOrderFormFunc(orderForm, user, "GOODS", WeAddressId, buyGoods, count);
}else{
mmp = this.goodsService.immediateAddOrderFormFunc(orderForm, user, "GOODS", WeAddressId, buyGoods, count);
}
Integer ErrorCode = (Integer) mmp.get("ErrorCode");
if (ErrorCode != null && ErrorCode.equals(DictionaryCode.ERROR_WEB_REQ_SUCCESS)) {
rs = Result.success();
rs.setMsg(mmp.get("Msg").toString());
} else {
rs = Result.failure();
rs.setMsg(mmp.get("Msg").toString());
}
//判断是否为子公司
/*if(isour&&rs.getSuccess()) {
rs=CheckOrderService.signContentProcess(rs, orderForm.getOrder_no());
if(!rs.getSuccess()) {
throw new Exception("立即下单:签章错误orderno="+orderForm.getOrder_no()+"错误信息为:"+rs.toString());
}
}*/
} catch (Exception e) {
e.printStackTrace();
rs.setSuccess(false);
rs.setMsg("提交订单失败");
}
return rs;
}
如此即可实现对下单的拦截。
亦可使用基于AOP的方式实现下单操作前校验,如下:基于注解的aspect
首先是execution()函数 用来匹配执行方法的连接点
语法结构: execution( 方法修饰符 方法返回值 方法所属类 匹配方法名 ( 方法中的形参表 ) 方法申明抛出的异常 )
其中(方法返回值、匹配方法名 ( 方法中的形参表 ))不能省略的,各部分都支持通配符 “*” 来匹配全部。
比较特殊的为形参表部分,其支持两种通配符
- "*":代表一个任意类型的参数;
- “..”:代表零个或多个任意类型的参数。
例如:
()匹配一个无参方法
(..)匹配一个可接受任意数量参数和类型的方法
(*)匹配一个接受一个任意类型参数的方法
(*,Integer)匹配一个接受两个参数的方法,第一个可以为任意类型,第二个必须为Integer。
代码实例如下:
首先添加启用aop配置:
<aop:aspectj-autoproxy proxy-target-class="true" />
package com.sanbang.Aspects;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Aspect
@Component
public class putOrderFormAspect {
private static Logger log = Logger.getLogger(putOrderFormAspect.class);
/**
* 定义一个方法,用于声明切入点表达式,方法中一般不需要添加其他代码
* 使用@Pointcut声明切入点表达式
* 后面的通知直接使用方法名来引用当前的切点表达式;如果是其他类使用,加上包名即可
*/
@Pointcut("execution(public * com.sanbang.app.controller.AppGoodsController.dealImmediatelyBuyGood(..))")
public void declearJoinPointExpression(){}
/**
* 前置通知
* @param joinPoint
*/
@Before("declearJoinPointExpression()") //该标签声明次方法是一个前置通知:在目标方法开始之前执行
public void beforMethod(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
//获取目标方法的传入参数,可按照索引进行获取
for (int i=0;i<args.length;i++){
System.out.println("参数"+i+":"+args[i].toString());
}
System.out.println("this method "+methodName+" begin. param<"+ args+">");
log.info("beforMethod 开始执行。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。");
}
/**
* 后置通知(无论方法是否发生异常都会执行,所以访问不到方法的返回值)
* @param joinPoint
*/
@After("declearJoinPointExpression()")
public void afterMethod(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
System.out.println("this method "+methodName+" end.");
}
/**
* 返回通知(在方法正常结束执行的代码)
* 返回通知可以访问到方法的返回值!
* @param joinPoint
*/
@AfterReturning(value="declearJoinPointExpression()",returning="result")
public void afterReturnMethod(JoinPoint joinPoint,Object result){
String methodName = joinPoint.getSignature().getName();
System.out.println("this method "+methodName+" end.result<"+result+">");
}
/**
* 异常通知(方法发生异常执行的代码)
* 可以访问到异常对象;且可以指定在出现特定异常时执行的代码
* @param joinPoint
* @param ex
*/
@AfterThrowing(value="declearJoinPointExpression()",throwing="ex")
public void afterThrowingMethod(JoinPoint joinPoint,Exception ex){
String methodName = joinPoint.getSignature().getName();
System.out.println("this method "+methodName+" end.ex message<"+ex+">");
}
/**
* 环绕通知(需要携带类型为ProceedingJoinPoint类型的参数)
* 环绕通知包含前置、后置、返回、异常通知;ProceedingJoinPoin 类型的参数可以决定是否执行目标方法
* 且环绕通知必须有返回值,返回值即目标方法的返回值
* @param point
*/
@Around(value="declearJoinPointExpression()")
public Object aroundMethod(ProceedingJoinPoint point){
Object result = null;
String methodName = point.getSignature().getName();
try {
//前置通知
System.out.println("The method "+ methodName+" start. param<"+ Arrays.asList(point.getArgs())+">");
//执行目标方法
result = point.proceed();
//返回通知
System.out.println("The method "+ methodName+" end. result<"+ result+">");
} catch (Throwable e) {
//异常通知
System.out.println("this method "+methodName+" end.ex message<"+e+">");
throw new RuntimeException(e);
}
//后置通知
System.out.println("The method "+ methodName+" end.");
return result;
}
}