AOP記錄異常郵件傳送記錄

flzhang發表於2016-06-12

一般我們的異常都會丟擲到控制層,如果使用struts2也就是action。然後try{//正確程式碼實現}catch{//在裡面記錄錯誤日誌},這樣咋一看是不錯,程式碼很完美。但是如果專案中有成千上萬個專案怎麼辦?難道在每個action的catch裡面都要加入異常記錄程式碼?很顯然工作量是很大的。7 `, X, R" [  \1 [2 D

0 S+ I4 X, f& F) \, L  C/ Y$ t
; P6 ~# Q4 g- Q4 v) H" M       鑑於專案中配置了資料庫事務,其實也是使用了AOP 詳見applicationContext-service.xml配置檔案。由於配置檔案的侷限性這裡採用註釋的方式實現。之所有使用註釋是可以自定義引數並實現日誌的詳細記錄。既然使用註釋,現成的沒有,只有自己定義來實現需求。其實spring 註釋實現的注入、hibernate的model類註釋實現與資料庫關聯以及我們最常見Override。
. t1 t; z# z( Q7 x0 p       資料:java如何實現自定義註釋http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html
1 ^. G4 }4 R% D7 R
% r5 E' J7 N7 ~; z6 ^6 z一、 記錄日誌併傳送郵件通知

(1)、定義註解:
9 k9 S. Y4 n# U) S9 j0 A7 m9 ^1.ServiceLog.java(各種引數型別詳見上面的資料)

0 D" K3 ~3 f2 ?( h

  1. import java.lang.annotation.*;
    - S. w$ {) Z3 E# t: J' }& @
  2. /**
    ! }, O0 m4 n) A# Y9 I# A3 ~
  3. * 自定義註解 攔截service  
    5 [  G& I1 R& B  E/ x
  4. * 建立者        張志朋
    . v9 C8 s$ }, K8 x
  5. * 建立時間        2015年6月3日  
  6. */
    - o. R; b, I2 Z
  7. @Target({ElementType.PARAMETER, ElementType.METHOD})   
    0 r0 w" j: w" ?& C- r$ _* }! U
  8. @Retention(RetentionPolicy.RUNTIME)   
  9. @Documented   
  10. public  @interface ServiceLog {
    % V) K# P. z; |& y- j1 i
  11.          String description()  default "";
    3 |9 v# K6 p" V, L, ]" T) c5 S% c
  12. }
複製程式碼
2.ControllerLog.java3 \' t* L! E! d0 \% b* s( N2 N
  1. import java.lang.annotation.*; 1 O6 b$ f+ A5 N  G5 R
  2. /**
    ; ~: V2 S4 G$ T+ C% R' |
  3. * 自定義註解 攔截Controller: g' a) s9 S- b- [% Z+ v" s
  4. * 建立者        張志朋
    - d3 R* O8 u" t
  5. * 建立時間        2015年6月3日
    / E5 N% e$ c6 z# q. A+ X+ b$ {
  6. *
    : ~* v& ?. ]! T
  7. */
    6 M/ `8 H( \) J+ K. u0 K) n
  8. @Target({ElementType.PARAMETER, ElementType.METHOD})   
    # V" N/ Z6 _, o, v4 i: M- J
  9. @Retention(RetentionPolicy.RUNTIME)    * D. u, W' W3 d. P9 J! h
  10. @Documented
      f3 w* U. f  r- Z4 w4 L3 r
  11. public @interface ControllerLog {
      S3 X. f9 i# w) E5 R9 Q
  12.         String description()  default "";
      ?: A, M" a3 c! H% J- g
  13. }
複製程式碼
(2)、定義切面以及切入點$ {9 ^) C" G! |6 V' ?
1.LogAspect.java

( `# e- e( r6 U, |( I1 |
  1. /**
    $ c/ W4 ]. r" ~$ L2 ]) H6 ]
  2. * 日誌記錄AOP+ ~# G$ `. M' W+ b
  3. * 建立者        張志朋* U3 Q. a' V* d' c+ {1 |' Q  i/ H" A
  4. * 建立時間        2015年6月3日
    - V+ o' ]) K0 x
  5. *
    4 ?4 h( H% d- e! [, }3 u
  6. */* a& I5 G, i9 [
  7. @Component
    / C% s$ F* b  l- r, I6 o9 m
  8. @Scope$ w& p0 A1 g7 h5 |: V# p! ?2 T7 P
  9. @Aspect
    ) L/ Y. @8 X7 t' R' [0 s
  10. public class LogAspect {. n  [5 j- F( q( ^8 Q& i3 X7 [
  11.         //Service層切點     用於記錄錯誤日誌
    ' `' \6 [8 d# Y, ~
  12.         @Pointcut("@annotation(com.web.aop.ServiceLog)")  
    ( J% V, a, ~* z9 y' z9 i
  13.         public void serviceAspect() {$ g: a. u5 m. Y" w
  14.                 6 C9 [5 x" }3 m2 z
  15.         }; ]7 {, \" L1 }) [  l1 t' i
  16.     /**
    * a) S) D4 p/ v% A: R$ V& T0 X* ?4 U
  17.      * 異常通知 用於攔截service層記錄異常日誌  ! J( E: g* X' T  ~  c5 Y
  18.      * @Author        張志朋
    ( }: D! e. F- X  O3 T3 K
  19.      * @param joinPoint- L3 l7 g* T1 F$ H  z- m
  20.      * @param e  void  B- K3 D" I. H3 D) `
  21.      * @Date        2015年6月3日
    8 ]8 g" ?" O$ M3 K* _6 e
  22.      * 更新日誌9 N- S: z6 {2 B* q5 K: C! ^, H$ w
  23.      * 2015年6月3日 張志朋  首次建立/ f( k# a5 t/ X7 p( r, f
  24.      *
    1 @' ~* t1 g( @
  25.      */! ^' U; k, B- G2 u" y; U4 v- R) x
  26.     @AfterThrowing(pointcut = "serviceAspect()", throwing = "e")    * X0 K5 m! P' l( }# \- w
  27.     public  void doAfterThrowing(JoinPoint joinPoint, Throwable e) { 2 X; e8 [$ n8 `; l
  28.                 HttpServletRequest request = ServletActionContext.getRequest();1 w4 k0 ?4 h( O6 ~1 h8 p) w7 D/ n
  29.                 TeacherEntity user = CommonUtil.getUser();
    ! B0 S4 H7 k+ }" e% R4 c
  30.                 String ip = AddressUtils.getIpAddr(request);
    6 \& v' p: u8 J
  31.                 try {( L* R+ }4 E: g- p2 |5 p1 I
  32.                         String params = "";4 F2 u- c  b7 v5 x: q) w
  33.                         if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0) {
    . X3 M$ m% [/ s( i1 M  k. C: {3 Y! m: l" J
  34.                                 for (int i = 0; i < joinPoint.getArgs().length; i++) {
    , |& ~/ _. c0 w& i; ~/ F
  35.                                         params += JSONUtil.toJSONstring(joinPoint.getArgs()[i]) + ";";- m4 ^8 \* @9 c% `8 a
  36.                                 }
    , ~/ y. l) l  {& f
  37.                         }; {7 t9 m$ K$ T! R1 P0 h2 C
  38.                         String description = getServiceMthodDescription(joinPoint);//使用者操作
    3 b! m: A8 I: G: x! k! w; f3 ?
  39.                         String exceptionCode  =e.getClass().getName();//異常型別程式碼* D" q% b# H1 P1 N
  40.                         String exceptionDetail = e.getMessage();//異常詳細資訊
    , _+ }& J4 I5 J
  41.                         String method = joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()";//異常方法
    1 ?/ {0 _" @( j4 q" p( O
  42.                         /*==========記錄資料庫異常日誌==========*/  4 P* G$ z, O& F
  43.                         Log log = new Log();
    5 ~1 x( J  G6 u
  44.                         log.setDescription(description);
    * ?+ ]: w2 M7 p, C& F3 J1 z
  45.                         log.setExceptionCode(exceptionCode);
    ( k5 Z* j3 _' ^
  46.                         log.setExceptionDetail(exceptionDetail);
    4 E0 K7 l* @, B6 ^
  47.                         log.setMethod(method);2 ~/ g: N' F4 j# ?
  48.                         log.setType(Constants.LOG_ERROE);// 日誌型別
    $ v* q4 l( v( M+ K: O
  49.                         log.setRequestIp(ip);// 請求IP2 E4 ~- N, E. s2 Z
  50.                         log.setParams(params);//請求引數
    " i, w4 R& o- E8 h
  51.                         if(null!=user){' N# l6 h/ r3 I2 D/ }' q) ~
  52.                     log.setCreateUid(user.getUid());//使用者ID
    # O; [+ e7 x- d9 I
  53.                     log.setCreateName(user.getNickname());//使用者暱稱
    ( E" a) d: s) J% o4 U
  54.             }# C& ?  ?7 f2 {) I
  55.                         log.setPlatFrom(Constants.SUBJECT_CODE);. ]8 `3 x3 F& k' L, ]: o: }7 Z) w
  56.                         /*==========記錄數本地異常日誌==========*/  , O' ~) z+ t- z4 ~* b
  57.                         //LogUtil.error(description, e);
    : |& q" l. I* g+ V
  58.                         /*==========傳送異常日誌到郵箱==========*/
    1 ]3 U% s2 f; v6 A3 m6 [8 p
  59.                         StringBuffer errorMsg = new StringBuffer();8 i! O' d, {. F) C0 d$ w
  60.                         errorMsg.append("異常方法:");* F; l& W8 J- V
  61.                         errorMsg.append(method);
    ; G$ |: v# L! L! s
  62.                         errorMsg.append("</br>");8 {7 i1 F$ b3 c, V. o
  63.                         errorMsg.append("異常型別程式碼:");
    9 C; j* \6 f6 s& x3 z9 s" j
  64.                         errorMsg.append(exceptionCode);% [# B0 Y/ S- P& i) d; m6 V3 B
  65.                         errorMsg.append("</br>");
    , j6 `$ W: _: _; w
  66.                         errorMsg.append("異常詳細資訊:");. p; r6 _5 q7 D* |8 T% q
  67.                         errorMsg.append(exceptionDetail);
    ; @3 M# D' d) T$ c1 L
  68.                         errorMsg.append("</br>");4 x" A' q3 l9 _0 I/ x8 n
  69.                         log.setErrorMsg(errorMsg.toString());; h& Y* b% O9 W0 W$ c
  70.                         WebServiceMathClient  Client = new WebServiceMathClient();; x7 h7 J2 c& F9 w2 t
  71.                         Client.sendError(log);. l+ b+ S5 J# J0 e% l+ ^, r
  72.                 } catch (Exception ex) {3 q% B/ R0 Z0 H0 S1 l8 U
  73.                         e.printStackTrace();; k' e3 l( |+ ~0 |3 c7 |+ ]* e
  74.                 }) J# A4 j# B4 x; q8 b4 N& v  D
  75.     }
    $ d0 Q2 r) c, Y- i6 _( I7 q
  76.      /**$ C$ j2 z7 z  @% g7 [, ^
  77.       * 獲取註解中對方法的描述資訊 用於service層註解  (基於反射)& \  r6 Y' c1 ~
  78.       * @Author        張志朋+ c% C7 k7 D4 x
  79.       * @param joinPoint5 }" U0 W, g' f$ S8 q
  80.       * @return/ y7 K5 y* w" m
  81.       * @throws Exception  String6 D1 `5 p" J  }+ B/ G
  82.       * @Date        2015年6月3日# h1 g7 Y; v! d
  83.       * 更新日誌
    : P& s( `2 E! f( h  {% Z& Z
  84.       * 2015年6月3日 張志朋  首次建立
    - a+ j  r5 l# g0 S9 z' B" g0 j
  85.       *1 ]" @9 k' t% s, \
  86.       */1 B! U- |) f( \
  87.      @SuppressWarnings("rawtypes")
    ' }0 j* ?! T6 Y, _* `% v
  88.         public  static String getServiceMthodDescription(JoinPoint joinPoint)    ' g0 G6 P2 Q+ G5 ^+ S
  89.              throws Exception {    ( m* w& @% A0 k, v' ?, U
  90.         String targetName = joinPoint.getTarget().getClass().getName();      I: V# i5 i; j( l3 u
  91.         String methodName = joinPoint.getSignature().getName();    $ a9 t; `2 q( g3 K5 N
  92.         Object[] arguments = joinPoint.getArgs();   
    : u) \& M4 C& m" I7 E6 z
  93.         Class targetClass = Class.forName(targetName);    , I* G; G0 ?0 o
  94.         Method[] methods = targetClass.getMethods();    2 x1 P8 ~9 ^7 ~( r2 j. z8 f
  95.         String description = "";   
      m4 u# Z4 Y& L! s
  96.          for (Method method : methods) {    6 q0 X) I, F# P$ v
  97.              if (method.getName().equals(methodName)) {    ' d" n& `1 ]; U0 z, N
  98.                 Class[] clazzs = method.getParameterTypes();    8 z4 D* r+ T. n( e
  99.                  if (clazzs.length == arguments.length) {   
    ( `  k8 [: R: e
  100.                     description = method.getAnnotation(ServiceLog. class).description();   
      K6 E1 [& N9 |7 A9 u1 I2 h5 M. J% r
  101.                      break;   
    % y$ V4 X- h- M3 m( z/ Q$ ]% |
  102.                 }   
    + P* q  R- v, ^, _
  103.             }   
    % c% a( T9 C2 p
  104.         }    3 e& ~% G' z- I/ ]
  105.          return description;    , ~  v4 J7 A4 T: }2 S4 F8 p. Q
  106.     }
    : ?+ E2 P" ~$ D
  107.     }
複製程式碼
, T7 V% N3 B! B
這裡說明一下  serviceAspect()方法 上面註釋了 @Pointcut("@annotation(com.acts.web.aop.ServiceLog)")  、也就說明這是一個切入點,springAOP對其進行了封裝。# u$ g! \5 u3 w' }7 W0 H4 t& j( _7 y0 f
doAfterThrowing()方法上面加入了@AfterThrowing(pointcut = "serviceAspect()", throwing = "e") 對切入點的所有異常資訊進行處理(記錄日誌到資料庫或者傳送錯誤資訊到指定郵箱等等等,可以做任何你想做的事情)。, Z7 h; x$ U* D. U, E

5 C3 `* u! D  m( c0 e2.QuesPerServiceImpl.java(注意此類必須實現介面 預設JDK的動態代理實現是基於介面實現的 否則會報錯)

7 x% _8 P1 [- n- }3 J1 l4 o, `
  1. @ServiceLog(description="獲取待審試題數量")
    ' C# V1 a3 Y9 t. E5 V  B
  2. public long getAuditQuesNum(TeacherEntity currentUser) throws Exception {5 \9 a& ~6 {4 `- |9 ?' E& L& c
  3.                 return quesPerDao.getAuditQuesNum(currentUser);
    . C( [! t( |/ V7 w5 w( k$ u
  4.         }
複製程式碼
' a( x0 ~+ c4 ]0 ^
之所以定義description 描述 是為了更好的記錄錯誤日誌 文字總是比方法名 更容易識別。1 C0 Z3 n7 v+ X# ^
二、AOP實現許可權控制
0 _( Y' f! I- H+ R4 P3 k& J       上面說過使用動態代理的類 必須實現介面但是我們的action並沒有實現介面。 JDK 的動態代理只能對實現了介面的目標類進行代理,而不實現介面的類就不能使用 JDK 的動態代理。$ F% v5 V( H" s. a' `0 }
        還好有第三方的包為我們解決了問題。專案中引入cglib.jar,CGLIB 是針對類來實現代理,當沒有實現介面的類需要代理時就需要通過 CGLIB 來實現代理了,他的原理是對指定的目標類生成一個子類,並覆蓋其中方法實現增強,但是因為採用的是繼承,所以不能對 finall 類進行繼承。( {, s  ]2 z  E! N7 U! ]) l* B
首先配置檔案要引入這樣一段配置(看註釋說明):
& `2 m6 Q- q. p3 [7 e* ]  s
  1. <!--通知spring使用cglib而不是jdk的來生成代理方法 AOP可以攔截到Controller(Action)-->
    * N% z4 |% b0 h: U" J$ s$ `% U
  2.         <aop:aspectj-autoproxy proxy-target-class="true"/>
複製程式碼

, F' X  o% r8 W* d3 P/ i(1)、定義註釋:
0 F( W" ^- s9 a; k% w1.Permission.java

# A, I1 S0 h; T) m  C* R2 v
  1. /**/ N4 f: v' A" C1 X8 g6 d3 r( G& J
  2. * 自定義許可權管理
    ; ~, [% }9 Y4 E$ ~. y; z
  3. * 建立者        張志朋
    3 w) N! C9 J+ `) r2 w( w
  4. * 建立時間        2015年6月30日6 h! R: f* O* W8 R) f* X8 V+ _
  5. *1 N* y; g7 u- ~5 J% m- R
  6. */$ t$ a- X- e( T) _
  7. @Target({ElementType.PARAMETER, ElementType.METHOD})   
    8 o/ U! L2 f/ }5 ~
  8. @Retention(RetentionPolicy.RUNTIME)   
    # s4 w5 l2 ]" h; b
  9. @Documented
    8 T* Z7 n8 I8 M+ {0 j
  10. public @interface Permission {
    * q: v# L- H% N: B1 {& Y/ ?( \1 o
  11.         String name()  default ""; //操作行為
    7 v0 M  K6 V: O4 ~2 ]* F
  12.         int id() default -1;//許可權值
    5 o& M+ Q+ [5 _% S. O
  13. }
複製程式碼
(2)、定義切面以及切入點2 ~* o& }# H  m. j6 V! N0 t1 U8 N
1.PsemissionAspect.java
0 U+ g8 C+ _7 g6 K( T: V% }+ A
  1. /**% V/ {# B- w7 j8 z
  2. * 許可權管理% f! C% F7 {; w) B( c
  3. * 建立者        張志朋
    " l" Q; A$ v5 m" }( W% n
  4. * 建立時間        2015年7月3日
    3 l- }$ F1 \: a/ s$ [( U2 n! x* }- O
  5. *% l2 Y! |8 y8 c/ Y. R. O
  6. */, h; k+ k7 X- I- A5 P  z  i
  7. @Component
    * \& L( a4 ]# n
  8. @Scope7 J/ [* j# j/ I" ]1 T% x6 N0 Q6 ^
  9. @Aspect" p  X9 T- |+ ?+ t- C2 b6 M
  10. public class PsemissionAspect {
    ) _% i0 V1 b/ l: S
  11.         
    ; z1 D1 B. h( E) j
  12.     //Controller層切點 用於許可權控制
    4 v9 C; c4 Q0 B4 O0 {$ K- ~
  13.         @Pointcut("@annotation(com.acts.web.aop.Permission)")  ( l* c8 d* V4 E8 P
  14.         public void permissionAspect() {
    5 w  z/ Q  {% Z  M  u, I8 s
  15.                
    % Q( @. \" i4 `2 P# f+ s# n" U
  16.         }
    8 M, [5 B2 L" d6 z! B3 \
  17.         /**
    5 w3 k3 f5 T, I$ @" S
  18.          * 用於攔截Controller層使用者操作許可權(環繞通知)$ [% e5 v$ N. m* `) Y
  19.          * @Author        張志朋' f+ |; s' \1 m  x, o
  20.          * @param joinPoint  void
    & Z( j% N/ O. w7 P) g% X' K9 g- [
  21.          * @Date        2015年6月3日
    2 b  |- Z! T0 M( k
  22.          * 更新日誌5 Q% }* O/ A- f
  23.          * 2015年6月3日 張志朋  首次建立/ u; i# F0 C5 g# S% [, b- q9 X
  24.          *' N/ T8 _: u( p) {" o, y0 X: A
  25.          */
    4 Y; {1 _8 t1 p, p. r$ ~* s
  26.     @Around("permissionAspect()")    ) x( w# {1 ?. w' l
  27.     public  Object permission(ProceedingJoinPoint  joinPoint)throws Throwable {  8 o) |) B0 V+ Z3 t
  28.         Object retVal = null;) ^8 U# G% D+ z7 s
  29.                 int role  =  getControllerMethodRole(joinPoint);! K1 [# g6 T5 W# F
  30.                 TeacherEntity user = CommonUtil.getUser();! f, y0 S+ q0 l/ W. m! f* S9 J
  31.                 if((user.getSpecRole()&role)==role){//沒有許可權6 T$ c1 \0 E( \+ J$ L  h
  32.                         retVal  = joinPoint.proceed();) z. _3 ?( l5 g% P+ B" q
  33.                 }else{/ O* W# X( ?: }" j4 |) ?
  34.                         noAuthorization();
    5 _' ~; |; L$ P$ n$ R
  35.                 }8 K+ T" f$ Y9 ~+ w$ s
  36.             return retVal;
    ! }7 F- o! h2 M9 y6 z0 T, d1 s% I
  37.     }& h2 k' S. q/ T! @
  38.     /**
    " r7 H  z7 r& U  b- a
  39.      * 沒有許可權 實現跳轉/ o3 g, c6 N: _- B
  40.      * @Author        張志朋
    4 \* o( `2 q/ P. C- m
  41.      * @throws IOException  void
    " b* V7 {) k/ E% y( s& ?$ |; w
  42.      * @Date        2015年7月3日
    % F* W, a3 p. }
  43.      * 更新日誌
    . l2 v8 d9 C- Y6 n$ h
  44.      * 2015年7月3日 張志朋  首次建立
    ) l+ G; i$ a+ |# a$ [
  45.      *
    , r- ?) H. ?  C
  46.      */# M! f  l3 `* e6 `
  47.     public void noAuthorization() throws IOException{& h) n% K0 r4 {$ F/ B( F
  48.             HttpServletRequest request = ServletActionContext.getRequest();/ |  k8 X0 [# M4 S4 p( y/ I
  49.                 String path =  request.getContextPath();+ r7 x" D4 v- p- R% E9 r" T
  50.                 HttpServletResponse response  = ServletActionContext.getResponse();
    9 o  s$ c8 a" m. S8 G6 n3 ]6 q
  51.                 response.sendRedirect(path+"/pages/noAuthorization.jsp");
    7 j, Y, C, q9 C- g
  52.     }/ V+ k% Q) m9 b+ W) f! |- p
  53.     /**4 o5 M  E. ?7 F( Q! a7 @" |
  54.      * 獲取註解中對方法的許可權值 用於Controller層註解  
    8 k( J2 ~; t  ^* K4 A
  55.      * @Author        張志朋
    2 [6 N. F9 V: M
  56.      * @param joinPoint
    + ^- R# }' s1 r  h  x
  57.      * @return
    . v* d9 G0 W, v5 z1 t) q5 c
  58.      * @throws Exception  int' r8 C3 [& v, z7 X, i
  59.      * @Date        2015年7月3日
    5 @' S% [" y: I; [! ]* s. x9 b! n5 I4 f
  60.      * 更新日誌
    1 @( \) T. m) S, y' K; Z, c+ E* G
  61.      * 2015年7月3日 張志朋  首次建立7 U, T9 U( y2 Y! z
  62.      *2 Z4 ?2 c: Y8 o, T
  63.      */
    9 @8 Q9 C$ x8 R& o  K7 V7 ^( L
  64.     @SuppressWarnings("rawtypes")
    8 c' k& S" Z* |7 _9 l
  65.         public  static int getControllerMethodRole(JoinPoint joinPoint)  throws Exception {
    & o6 `9 D! I8 w. f
  66.         String targetName = joinPoint.getTarget().getClass().getName();    ! `' K; B2 l5 w
  67.         String methodName = joinPoint.getSignature().getName();    ( D* y9 w, o" V' E; W
  68.         Object[] arguments = joinPoint.getArgs();    , F* I# _8 K& H3 ^( ^; s
  69.         Class targetClass = Class.forName(targetName);    , r# D, w9 N, R8 S2 @2 A0 c
  70.         Method[] methods = targetClass.getMethods();   
    3 s7 H7 F4 H9 p% Z3 J# j
  71.         int role = -1;    * }' t8 i( O# ?% W# w
  72.          for (Method method : methods) {    + a# n, }0 f1 X5 E# t4 M( P, C
  73.              if (method.getName().equals(methodName)) {    * S9 C8 v/ G8 W5 @3 s8 G  y
  74.                 Class[] clazzs = method.getParameterTypes();   
    ! E% o" N; b3 U; P
  75.                  if (clazzs.length == arguments.length) {    - i* n; p5 M9 }: u) @
  76.                          role = method.getAnnotation(Permission. class).id();    5 u( i9 ~1 B2 ~
  77.                      break;   
    * B, g1 A4 i. A2 H# b
  78.                 }   
    3 G: E: Y( ?; f* }9 X
  79.             }    ( g* S9 u, x' O. v( D& B1 J& V4 I
  80.         }   
    " ~' p7 a& d8 _4 P! a
  81.          return role;   
    5 i% {4 P3 O- ?
  82.     }
複製程式碼

: X  N' a& G: o+ n2.action層程式碼實現:3 j. @6 G! b. H* z
  1. /**
    $ e4 K; e( u9 |: w. v" W0 J3 y
  2.          * 試題稽核不通過
    3 Q- S' a8 g2 N* @. p# m8 ~
  3.          * @Author        張志朋  void
    , h6 F/ v% s( }
  4.          * @Date        2015年5月4日
    & [- w* s  k  O% c9 \" F0 \- A. r
  5.          * 更新日誌. R5 [/ y4 i1 E) L/ P
  6.          * 2015年5月4日 張志朋  首次建立9 q' `2 s) k! k# r1 v! M$ R( O
  7.          *: }. L" Z! S  Q
  8.          */
    ; ]$ a  I- Q5 i1 l0 J& t
  9.         @Permission(name="稽核試題許可權(稽核不通過)",id=Constants.ROLE_QUES_AUDIT)2 U, ]( e; H$ z
  10.         public void auditQuestions(){
    6 _! V+ i! M7 k
  11.                 try {
    $ F0 h; h' u+ ~) }0 c0 N5 h" P7 E
  12.                      //程式碼實現
    . \3 F. o8 r2 t& a- U2 q" u/ f$ u
  13.                 } catch (Exception e) {' b4 H' W+ @! i0 M
  14.                      e.printStackTrace();
    ) ]+ \5 j5 v# _# Z
  15.                 }- G& Y$ {* t" ~
  16. # {8 s$ ~+ |2 ~7 c; U2 l
  17.         }
複製程式碼

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/750077/viewspace-2119041/,如需轉載,請註明出處,否則將追究法律責任。

相關文章