首先提交訂單前需要進行庫存校驗等一系列的準備操作流程,故可以在提交訂單流程的基礎上進行攔截器的預提交操作。
具體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;
}
}