精华内容
下载资源
问答
  • 记录 spring mvc controller层操作记录 Java代码 package com.wssys.framework; import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.Calendar; import javax....
    记录 spring mvc controller层操作记录 
    Java代码  
    1. package com.wssys.framework;  
    2.   
    3. import java.lang.reflect.Method;  
    4. import java.text.SimpleDateFormat;  
    5. import java.util.Calendar;  
    6.   
    7. import javax.servlet.http.HttpServletRequest;  
    8. import org.apache.shiro.SecurityUtils;  
    9. import org.aspectj.lang.ProceedingJoinPoint;  
    10. import org.aspectj.lang.annotation.Around;  
    11. import org.aspectj.lang.annotation.Aspect;  
    12. import org.aspectj.lang.annotation.Pointcut;  
    13. import org.springframework.beans.factory.annotation.Autowired;  
    14. import org.springframework.stereotype.Component;  
    15. import org.springframework.web.context.request.RequestContextHolder;  
    16. import org.springframework.web.context.request.ServletRequestAttributes;  
    17.   
    18. import com.wssys.bean.BolBean;  
    19. import com.wssys.bean.ComPanyForm;  
    20. import com.wssys.bean.DeliverBean;  
    21. import com.wssys.bean.GoodsForm;  
    22. import com.wssys.dao.SyslogDao;  
    23. import com.wssys.entity.Companycontacts;  
    24. import com.wssys.entity.PusFrontUser;  
    25. import com.wssys.entity.PusMenu;  
    26. import com.wssys.entity.PusRole;  
    27. import com.wssys.entity.PusSysUser;  
    28. import com.wssys.entity.Syslog;  
    29. import com.wssys.utils.StringUtil;  
    30. import com.wssys.utils.TCPIPUtil;  
    31.   
    32. /** 
    33.  * @Aspect 实现spring aop 切面(Aspect): 
    34.  *  一个关注点的模块化,这个关注点可能会横切多个对象。事务管理是J2EE应用中一个关于横切关注点的很好的例子。 在Spring AOP中,切面可以使用通用类(基于模式的风格)或者在普通类中以 @Aspect注解(@AspectJ风格)来实现。  
    35.  *  AOP代理(AOP Proxy): AOP框架创建的对象,用来实现切面契约(aspect contract)(包括通知方法执行等功能)。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。 注意:Spring 2.0最新引入的基于模式(schema-based )风格和@AspectJ注解风格的切面声明,对于使用这些风格的用户来说,代理的创建是透明的。  
    36.  */  

    37. @Component  
    38. @Aspect  
    39. public class LogService {  
    40.   
    41.     @Autowired  
    42.     private SyslogDao syslogDao;  
    43.   
    44.     public LogService() {  
    45.         System.out.println("Aop");  
    46.     }  
    47.   
    48.     /** 
    49.      * 在Spring2.0中,Pointcut的定义包括两个部分:Pointcut表示式(expression)和Pointcut签名(signature)。让我们先看看execution表示式的格式: 
    50.      * 括号中各个pattern分别表示修饰符匹配(modifier-pattern?)、返回值匹配(ret-type-patten)、类路径匹配(declaring-type-pattern?)、方法名匹配(name-pattern)、参数匹配((param-pattern))、异常类型匹配(throws-pattern?),其中后面跟着“?”的是可选项。 
    51.      * @param point 
    52.      * @throws Throwable 
    53.      */  
    54.     @Pointcut("@annotation(com.wssys.framework.MethodLog)")  
    55.     public void methodCachePointcut() {  
    56.   
    57.     }  
    58.   
    59.     // // @Before("execution(* com.wssys.controller.*(..))")  
    60.     // public void logAll(JoinPoint point) throws Throwable {  
    61.     // System.out.println("打印========================");  
    62.     // }  
    63.     //  
    64.     // // @After("execution(* com.wssys.controller.*(..))")  
    65.     // public void after() {  
    66.     // System.out.println("after");  
    67.     // }  
    68.   
    69.     // 方法执行的前后调用  
    70.     // @Around("execution(* com.wssys.controller.*(..))||execution(* com.bpm.*.web.account.*.*(..))")  
    71.     // @Around("execution(* com.wssys.controller.*(..))")  
    72.     // @Around("execution(* org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(..))")  
    73.     @Around("methodCachePointcut()")  
    74.     public Object around(ProceedingJoinPoint point) throws Throwable {  
    75.         HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder  
    76.                 .getRequestAttributes()).getRequest();  
    77.         SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E");  
    78.         Calendar ca = Calendar.getInstance();  
    79.         String operDate = df.format(ca.getTime());  
    80.         String ip = TCPIPUtil.getIpAddr(request);  
    81.         PusSysUser user = (PusSysUser) SecurityUtils.getSubject()  
    82.                 .getPrincipal();  
    83.         String loginName;  
    84.         String name;  
    85.         if (user != null) {  
    86.             loginName = user.getAccount();  
    87.             // name = user.name;  
    88.         } else {  
    89.             loginName = "匿名用户";  
    90.             // name = "匿名用户";  
    91.         }  
    92.   
    93.         String monthRemark = getMthodRemark(point);  
    94.         String monthName = point.getSignature().getName();  
    95.         String packages = point.getThis().getClass().getName();  
    96.         if (packages.indexOf("$$EnhancerByCGLIB$$") > -1) { // 如果是CGLIB动态生成的类  
    97.             try {  
    98.                 packages = packages.substring(0, packages.indexOf("$$"));  
    99.             } catch (Exception ex) {  
    100.                 ex.printStackTrace();  
    101.             }  
    102.         }  
    103.   
    104.         String operatingcontent = "";  
    105.         Object[] method_param = null;  
    106.   
    107.         Object object;  
    108.         try {  
    109.             method_param = point.getArgs(); //获取方法参数   
    110.             // String param=(String) point.proceed(point.getArgs());  
    111.             object = point.proceed();  
    112.         } catch (Exception e) {  
    113.             // 异常处理记录日志..log.error(e);  
    114.             throw e;  
    115.         }  
    116.         Syslog sysLog = new Syslog();  
    117.         sysLog.setIpAddress(ip);  
    118.         sysLog.setLoginName(loginName);  
    119.         sysLog.setMethodName(packages + "." + monthName);  
    120.         sysLog.setMethodRemark(monthRemark);  
    121.         //这里有点纠结 就是不好判断第一个object元素的类型 只好通过  方法描述来 做一一  转型感觉 这里 有点麻烦 可能是我对 aop不太了解  希望懂的高手在回复评论里给予我指点  
    122.         //有没有更好的办法来记录操作参数  因为参数会有 实体类 或者javabean这种参数怎么把它里面的数据都解析出来?  
    123.         if (StringUtil.stringIsNull(monthRemark).equals("会员新增")) {  
    124.             PusFrontUser pfu = (PusFrontUser) method_param[0];  
    125.             sysLog.setOperatingcontent("新增会员:" + pfu.getAccount());  
    126.         } else if (StringUtil.stringIsNull(monthRemark).equals("新增角色")) {  
    127.             PusRole pr = (PusRole) method_param[0];  
    128.             sysLog.setOperatingcontent("新增角色:" + pr.getName());  
    129.         } else if (StringUtil.stringIsNull(monthRemark).equals("用户登录")) {  
    130.             PusSysUser currUser = (PusSysUser) method_param[0];  
    131.             sysLog.setOperatingcontent("登录帐号:" + currUser.getAccount());  
    132.         } else if (StringUtil.stringIsNull(monthRemark).equals("用户退出")) {  
    133.             sysLog.setOperatingcontent("具体请查看用户登录日志");  
    134.         } else if (StringUtil.stringIsNull(monthRemark).equals("角色名称修改")) {  
    135.             PusRole pr = (PusRole) method_param[0];  
    136.             sysLog.setOperatingcontent("修改角色:" + pr.getName());  
    137.         } else if (StringUtil.stringIsNull(monthRemark).equals("新增后台用户")) {  
    138.             PusSysUser psu = (PusSysUser) method_param[0];  
    139.             sysLog.setOperatingcontent("新增后台用户:" + psu.getAccount());  
    140.         } else if (StringUtil.stringIsNull(monthRemark).equals("更新菜单")) {  
    141.             PusMenu pm = (PusMenu) method_param[0];  
    142.             sysLog.setOperatingcontent("更新菜单:" + pm.getName());  
    143.         } else if (StringUtil.stringIsNull(monthRemark).equals("保存菜单")) {  
    144.             PusMenu pm = (PusMenu) method_param[0];  
    145.             sysLog.setOperatingcontent("保存菜单:" + pm.getName());  
    146.         } else if (StringUtil.stringIsNull(monthRemark).equals("修改公司")) {  
    147.             ComPanyForm ciform = (ComPanyForm) method_param[0];  
    148.             sysLog.setOperatingcontent("修改公司:" + ciform.getName());  
    149.         } else if (StringUtil.stringIsNull(monthRemark).equals("联系人更新")) {  
    150.             Companycontacts ct = (Companycontacts) method_param[0];  
    151.             sysLog.setOperatingcontent("联系人更新:" + ct.getName());  
    152.         } else if (StringUtil.stringIsNull(monthRemark).equals("修改货物")) {  
    153.             GoodsForm goodsForm = (GoodsForm) method_param[0];  
    154.             sysLog.setOperatingcontent("修改货物(货物id/编号):" + goodsForm.getId());  
    155.         } else if (StringUtil.stringIsNull(monthRemark).equals("打印出库单")) {  
    156.             DeliverBean owh= (DeliverBean) method_param[0];  
    157.             sysLog.setOperatingcontent("出库单单号:" + owh.getCknum());  
    158.         } else if (StringUtil.stringIsNull(monthRemark).equals("打印提单")) {  
    159.             BolBean bol= (BolBean) method_param[0];  
    160.             sysLog.setOperatingcontent("提货单号:" + bol.getBolnum());  
    161.         } else if (StringUtil.stringIsNull(monthRemark).equals("系统左侧菜单查询")) {  
    162.             sysLog.setOperatingcontent("无");  
    163.         } else {  
    164.             sysLog.setOperatingcontent("操作参数:" + method_param[0]);  
    165.         }  
    166.   
    167.         syslogDao.save(sysLog);  
    168.         return object;  
    169.     }  
    170.   
    171.     // 方法运行出现异常时调用    
    172.     // @AfterThrowing(pointcut = "execution(* com.wssys.controller.*(..))",  
    173.     // throwing = "ex")  
    174.     public void afterThrowing(Exception ex) {  
    175.         System.out.println("afterThrowing");  
    176.         System.out.println(ex);  
    177.     }  
    178.   
    179.     // 获取方法的中文备注____用于记录用户的操作日志描述  
    180.     public static String getMthodRemark(ProceedingJoinPoint joinPoint)  
    181.             throws Exception {  
    182.         String targetName = joinPoint.getTarget().getClass().getName();  
    183.         String methodName = joinPoint.getSignature().getName();  
    184.         Object[] arguments = joinPoint.getArgs();  
    185.   
    186.         Class targetClass = Class.forName(targetName);  
    187.         Method[] method = targetClass.getMethods();  
    188.         String methode = "";  
    189.         for (Method m : method) {  
    190.             if (m.getName().equals(methodName)) {  
    191.                 Class[] tmpCs = m.getParameterTypes();  
    192.                 if (tmpCs.length == arguments.length) {  
    193.                     MethodLog methodCache = m.getAnnotation(MethodLog.class);  
    194.                     if (methodCache != null) {  
    195.                         methode = methodCache.remark();  
    196.                     }  
    197.                     break;  
    198.                 }  
    199.             }  
    200.         }  
    201.         return methode;  
    202.     }  
    203.   
    204.   
    205. }  




    spring application.xml配置: 

      <!-- aop --> 
      <bean id="logService" class="com.wssys.framework.LogService"></bean> 

       <!-- 启动对@AspectJ注解的支持  --> 
       <aop:aspectj-autoproxy proxy-target-class="true" /> 


    spring mvc controller层action的 
    设置 例如: 

    Java代码  收藏代码
    1. @RequestMapping(value = "/addFrontUser", method = RequestMethod.POST)  
    2. @MethodLog(remark = "会员新增")  
    3. public String saveFrontUserAction(@ModelAttribute("psu") PusFrontUser pfu,  
    4.         BindingResult result, SessionStatus status,  
    5.         HttpServletResponse response) {  
    6.     if (pusFrontUserDao.checkAccount(pfu.getAccount()) > 0) {  
    7.         PrintWriter out = null;  
    8.         try {  
    9.             out = response.getWriter();  
    10.         } catch (IOException e) {  
    11.             // TODO Auto-generated catch block  
    12.             e.printStackTrace();  
    13.         }  
    14.   
    15.         out.write("保存失败,会员帐号已经存在");  
    16.   
    17.         out.flush();  
    18.         return null;  
    19.     }  
    20.     // Timestamp now = new Timestamp(System.currentTimeMillis());// 获取系统当前时间  
    21.   
    22.     int saverec = 0;  
    23.   
    24.     pfu.setPwd(new Sha384Hash(pfu.getPwd()).toBase64());  
    25.     saverec = pusFrontUserDao.save(pfu);  
    26.   
    27.     PrintWriter out = null;  
    28.     try {  
    29.         out = response.getWriter();  
    30.     } catch (IOException e) {  
    31.         // TODO Auto-generated catch block  
    32.         e.printStackTrace();  
    33.     }  
    34.     if (saverec > 0) {  
    35.         out.write("保存成功,您可以继续保存或者关闭当前页面");  
    36.     } else {  
    37.         out.write("保存失败");  
    38.     }  
    39.   
    40.     out.flush();  
    41.     return null;  
    42. }  




    Java代码  收藏代码
    1. package com.wssys.framework;  
    2.   
    3. import java.lang.annotation.Documented;  
    4. import java.lang.annotation.ElementType;  
    5. import java.lang.annotation.Retention;  
    6. import java.lang.annotation.RetentionPolicy;  
    7. import java.lang.annotation.Target;  
    8.   
    9. /** 
    10.  * 表示对标记有xxx注解的类,做代理 注解@Retention可以用来修饰注解,是注解的注解,称为元注解。 
    11.  * Retention注解有一个属性value,是RetentionPolicy类型的,Enum RetentionPolicy是一个枚举类型, 
    12.  * 这个枚举决定了Retention注解应该如何去保持,也可理解为Rentention 搭配 
    13.  * RententionPolicy使用。RetentionPolicy有3个值:CLASS RUNTIME SOURCE 
    14.  * 用@Retention(RetentionPolicy 
    15.  * .CLASS)修饰的注解,表示注解的信息被保留在class文件(字节码文件)中当程序编译时,但不会被虚拟机读取在运行的时候; 
    16.  * 用@Retention(RetentionPolicy.SOURCE 
    17.  * )修饰的注解,表示注解的信息会被编译器抛弃,不会留在class文件中,注解的信息只会留在源文件中; 
    18.  * 用@Retention(RetentionPolicy.RUNTIME 
    19.  * )修饰的注解,表示注解的信息被保留在class文件(字节码文件)中当程序编译时,会被虚拟机保留在运行时, 
    20.  * 所以他们可以用反射的方式读取。RetentionPolicy.RUNTIME 
    21.  * 可以让你从JVM中读取Annotation注解的信息,以便在分析程序的时候使用. 
    22.  *  
    23.  * 类和方法的annotation缺省情况下是不出现在javadoc中的,为了加入这个性质我们用@Documented 
    24.  *  java用  @interface Annotation{ } 定义一个注解 @Annotation,一个注解是一个类。 
    25.  *  @interface是一个关键字,在设计annotations的时候必须把一个类型定义为@interface,而不能用class或interface关键字  
    26.  *  
    27.  * @author q 
    28.  *  
    29.  */  
    30.   
    31. @Target({ ElementType.METHOD, ElementType.TYPE })  
    32. @Retention(RetentionPolicy.RUNTIME)  
    33. @Documented  
    34. public @interface MethodLog {  
    35. String remark() default "";  
    36.     String operType() default "0";     
    37.    // String desc() default "";  
    38. }  


    日志 数据效果: 

    基本可以实现监控用户的数据操作,aop改变了传统的每个日志必须去一个个的方法里写的方式,直接通过反射得到所有数据一个类解决 ,

    开发不是一般的快 。
    展开全文
  • 这是在ssh框架基础上弄一个记录用户的操作代码 记录用户做了什么操作,以及操作的数据等,见附件 当访问到userAction时候会拦截下来进入到附件中方法,然后方法记录日志后,进入业务处理方法,此方法目前...
    gojava1
    这是在ssh框架的基础上弄的一个记录用户的操作代码

    记录用户做了什么操作,以及操作的数据等,见附件

    当访问到userAction的时候会拦截下来进入到附件中的方法,然后方法记录日志后,进入业务处理方法,此方法目前貌似只能在方法执行之前记录日志,不能在业务完成后记录,换句话说就是不能记录操作是否成功,只能记录用户做了哪些操作

    1、在struts-config.xml 中配置好action,如下是我的配置


    <form-beans>
    <form-bean name="userForm" type="com.esb.user.form.userForm"></form-bean>
    </form-beans>



    <action path="/userAction"
            type="com.esb.user.action.userAction"
            attribute="userForm"
            name="userForm"
            parameter="method"
            scope="request">
    <forward name="group" path="/jsp/view/user/group/uGroup.jsp" />
    <forward name="groupadd" path="/jsp/view/user/group/uGroupadd.jsp" />
    <forward name="groupgrant" path="/jsp/view/user/group/uGroupgrant.jsp" />
    <forward name="groupsysgrant" path="/jsp/view/user/group/uGroupgrantSys.jsp" />
    <forward name="groupedit" path="/jsp/view/user/group/uGroupedit.jsp" />
    <forward name="groupview" path="/jsp/view/user/group/uGroupview.jsp" />
    <forward name="result" redirect="true"  path="/jsp/view/user/group/result.jsp"  />
    <forward name="user" path="/jsp/view/user/infor/list.jsp" />
    <forward name="useradd" path="/jsp/view/user/infor/useradd.jsp" />
    <forward name="useredit" path="/jsp/view/user/infor/useredit.jsp" />
    <forward name="userview" path="/jsp/view/user/infor/userview.jsp" />
    <forward name="userresult" redirect="true"  path="/jsp/view/user/infor/result.jsp"  />
    <forward name="grant" path="/jsp/view/user/group/rs.jsp" />
    <forward name="su" path="/jsp/view/suorfail/sucess.jsp"></forward>
    </action>



    然后再spring的applicationContext.xml中加入这如下这段
    <!-- 注册了这个拦截器(1)     -->
      <bean name="logger"   class="ri.LoggingInterceptor"/> 
      <!-- 创建了一个 bean 名称自动代理,它描述如何应用拦截器。还有其他的方法定义拦截点,但是这种方法常见而简便。  -->
      <bean name="loggingAutoProxy"  class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">  
        <property name="beanNames">   
                <!-- 将 Struts 动作注册为将被拦截的 bean。如果您想要拦截其他的 Struts 动作,则只需要在 "beanNames" 下面创建附加的 <value> 标记。   -->
              <list>  
                  <value>/userAction</value>  
              </list>  
        </property>  
        <property name="interceptorNames">  
            <!-- 当拦截发生时,执行了在 (1) 处创建的拦截器 bean 的名称。这里列出的所有拦截器都应用于"beanNames"。 -->
            <list>  
              <value>logger</value>  
            </list>  
        </property>  
       </bean> 
      
      <!--  到这里,日志记录拦截器的准备工作都已经做好了,接下来看执行了Struts动作后会得到什么样的结果。  -->
    ri.rar
    展开全文
  • 程序因该:返回到一种安全状态,并能够让用户执行一些其他命令允许用户保存所有操作的结果,并以适当方式终止程序需要关注问题:用户输入错误设备错误物理限制代码错误当某个方法不能够采用正常路径完成它...

    处理错误

    由于出现错误而使得某些操作没有完成,程序因该:

    返回到一种安全状态,并能够让用户执行一些其他命令

    允许用户保存所有操作的结果,并以适当的方式终止程序

    需要关注的问题:

    用户输入错误

    设备错误

    物理限制

    代码错误

    当某个方法不能够采用正常的路径完成它的任务,就可以通过另外一个一个路径退出方法。这种情况下,方法并不返回任何值,而是抛出(throw)一个封装了错误信息的对象。要注意这个方法将会立刻退出,并不返回任何值。调用这个方法的代码也将无法继续执行,异常处理机制开始搜索能够处理这种异常状况的异常处理器(exception handler)。

    异常分类

    全都派生于 Throwable 类,分解为两个分支层次结构:Error 和 Exception

    Error 类层次结构描述 Java 运行时系统的内部错误和资源耗尽错误。应用程序不该抛出这种错误。

    Exception 类层次结构分为两个分支。

    派生于 RuntimeException 异常,由程序错误导致的异常。

    其他不是程序导致的异常。

    派生于 RuntimeException 异常的几种情况:

    错误的类型转换

    数组访问越界,ArrayIndexOutOfBoundsException异常

    访问空指针,NullPointerException异常

    其他异常的几种情况:

    试图在文件尾部后面读取数据

    试图打开一个不存在的文件

    试图根据给定的字符串查找 Class 对象,而这个字符串表示的类并不存在

    Java 将派生于 Error 类或 RuntieException 类额所有异常成为非受查异常,其他的异常成为受查异常。

    声明受查异常

    一个方法不仅要告诉编译器要返回什么值,还要告诉编译器可能发生什么错误。

    例子:

    public FileInputStream(String name) throws FileNotFoundException {

    ...

    }

    这个声明表示可能抛出异常,如果发生了这个异常构造器将不会初始化一个新的 FileInputStream 对象,而是抛出一个 FileNotFoundException 类对象。抛出异常类对象后,运行时系统就会搜索异常处理器,以便指定如何处理 FileNotFoundException 对象。

    需要抛出异常的情况:

    调用一个抛出受查异常的方法。

    程序运行过程中发现错误,利用 throw 语句抛出一个受查异常。

    程序出现错误,一些非受查对象。

    Java 虚拟机和运行时库出现的内部错误。

    前两种情况,必须告诉调用这个方法的程序员有可能抛出异常。防止程序遇到异常停止线程。

    根据异常规范在方法首部声明这个方法可能抛出的异常,多个受查异常用逗号隔开:

    class MyAnimation{

    ...

    public Image loadImage(String s) throws IOException, FileNotFoundException {

    ...

    }

    }

    如果方法没有声明受查异常,编译器会发出一个错误信息。

    除了声明异常外,还可以捕获异常,抛出让异常处理器处理。

    另外:声明一个异常,可能抛出这个异常的子类异常。

    抛出异常

    抛出异常的语句:

    throw new EOFException();

    String readData(Scanner in) throws EOFException {

    ...

    while (...) {

    if (!in.hasNext()) { //EOF encountered

    if(n < len) throw new EOFException();

    }

    }

    }

    抛出以存在的异常类:

    找到一个合适的异常类

    创建这个类的一个对象

    将对象抛出

    一旦方法抛出了异常,这个方法就不可能返回到调用者。

    创建异常类

    标准异常无法充分的描述清楚问题,可以创建自己的异常类:

    class FileFormatException extends IOException {

    public FileFormatException(){}

    public FileFormatException(String gripe){

    super(gripe);//构造一个带描述信息的异常

    }

    }

    //抛出自己定义的异常类型

    String readDate(BufferedReader in) throws FileFormatException {

    ...

    while (...) {

    if (ch == -1) { //EOF encounteered

    if (n < len) throw new FileFormatException();

    }

    ...

    }

    return s;

    }

    api:

    //java.lang.Throwable

    Throwable() 构造一个 Throwable 对象,没有描述信息。

    Throwable(String message) 构造一个 Throwable 对象,带描述信息。

    String getMessage() 获取描述信息。

    捕获异常

    捕获异常

    异常发生,没有捕获,程序就会终止执行,在控制台打印异常信息。

    捕获一行,必须设置 try/catch 语句块:

    try {

    code

    more code

    } catch (ExceptionType e) {

    handler for this type

    }

    如果 try 内有代码抛出了 catch 中定义的异常:

    程序将跳过 try 语句块的其余代码。

    程序将执行 catch 子句中的处理器代码。

    注意:如果 try 内的异常 catch 中没有,则程序终止。

    将异常传递给调用者:

    public void read(String filename) throws IOException {...}

    将不知道怎样处理的异常继续进行传递,传递异常使用 throws 说明符,告知调用者这个方法可能出现异常。

    例外:如果编写一个覆盖超类的方法,这个方法没有抛出异常,那么这个方法必须捕获方法代码中出现的每一个受查异常。不允许在子类的 throws 说明符中出现超过超类方法所列出的异常类范围。

    捕获多个异常

    有两种方式,第一种方式为每个异常类使用单独的 catch 子句。

    try {

    code;

    } catch (FileNotFoundException e) {

    emergency action;

    } catch (UnknownHostException e) {

    emergency action;

    } catch (IOException e) {

    emergency action;

    }

    第二种方式可以对动机一样的异常进行合并 catch 子句。

    try {

    code;

    } catch (FileNotFoundException | UnknownHostException | IOException e) {

    emergency action;

    }

    获得对象的更多信息,可以:

    e.getMessage();

    e.getClass().getName();

    注意:捕获多个异常时,异常变量隐含为 final 变量,不可修改。

    再次抛出异常与异常链

    有些异常我们并不想指定发送错误的细节原因,但希望明确的指定它是否有问题:

    try {

    access the database

    } catch (SQLException e) {

    throw new ServletException("database error:" + e.getMessage());

    }

    //更好的方法,将原始异常设置为新异常的“原因”

    try {

    access the database

    } catch (SQLException e) {

    Throwable se = new ServletException("database error");

    se.initCause(e);

    throw se;

    }

    //重新得到原始异常

    Throwable e = se.getCause();

    这个受查异常,不允许抛出它,包装技术十分有用,可以捕获这个受查异常,把它包装成一个运行时异常。

    finally 子句

    不管是否有异常被捕获,finally 子句中的代码都被执行:

    InputStream in = new FileInputStream(...);

    try {

    core 1;

    core 2;

    } catch (IOException e) {

    core 3;

    } finally {

    core 4;

    }

    会遇到3种情况:

    代码没有异常。执行完 try 块,然后执行 finally 块。

    抛出一个异常。执行 try 块知道异常为止,跳过剩余 try 代码,转去执行与异常匹配的 catch 子句中的代码,最后执行 finally 子句中的代码。

    代码抛出异常,但是 catch 没有匹配的异常。执行 try 块知道异常为止,跳过剩余 try 代码,转去执行 finally 子句中的代码,并将异常抛给这个方法的调用者。

    解耦合try/catch和try/finally,提高代码的清晰度:

    try {

    try {

    code;

    } finally {

    in.close();

    }

    } catch (IOException e) {

    show error message;

    }

    内层确保关闭输入流;外层确保报告出现的错误。外层也会报告 finally 子句中出现的错误。

    return的各种场景:

    return 在 try 块中时,方法返回前 finally 子句的内容将被执行。

    return 在 try 块 finally 子句中都存在时,finally 子句中的返回值将会覆盖原始的返回值。

    finally子句的坏处

    try {

    code 1;

    } finally {

    in.close();

    }

    如果 try 语句抛出了一些非 IOEception 的异常,这些异常只有调用者才能处理。执行 finally 语句块,并调用 close 方法,有可能抛出 IOException 异常。有这种情况时,原始的异常将会丢失,转而抛出 close 方法的异常。

    带资源的 try 语句

    资源属于实现了 AutoCloseable 接口的类时:

    //接口的一个方法

    void close() throws Exception

    //最简形式

    try (Resource res = ...) {

    work with res;

    }

    try 块退出时,会自动调用 res.close() 。并且可以指定多个资源。

    分析堆栈轨迹元素

    堆栈轨迹元素是一个方法调用过程的列表,包含了程序执行过程中方法调用的特定位置。

    调用 Throwable 类的 printStackTrace 方法访问堆栈轨迹的文本描述信息。

    使用异常机制的技巧

    异常处理不能代替简单的测试

    不要过分地细化异常

    利用异常层次结构

    不要压制异常

    在检测错误时,“苛刻”要比放任更好

    不要羞于传递异常

    使用断言

    断言的概念

    断言机制允许在测试期间向代码插入一些检查语句。当代码发布时,这些插入的检测语句会被自动地移走。

    assert 条件;

    assert 条件 : 表达式;

    这两种形式都会对条件进行检测, 如果结果为 false,则抛出一个 AssertionError 异常。 在第二种形式中,表达式将被传人 AssertionError 的构造器,并转换成一个消息字符串。 表达式部分的目的是产生一个消息字符串。

    例子,断言 x 是一个非负数值:

    assert x >= 0;

    assert x >= 0 : x;

    启用和禁用断言

    启用:java -enableassertions MyApp

    启用某个类中的断言:java -ea:MyClass -ea:com.mycompany.mylib... MyApp

    禁用特定类和包的断言:java -ea:... -da:MyClass MyApp

    不能应用没有类加载器的系统类上,要使用:-enablesystemassertions/-esa

    使用断言完成参数检查

    使用断言的场景:

    断言失败是致命的、不可恢复的错误

    断言用于开发和测试阶段

    不可通告可恢复性的错误,不该作为程序向用户通告问题的手段。

    不允许用 null 数组调用这个方法,并在这个方法的开头使用断言:assert a != null;

    为文档假设使用断言

    if (i % 3 == 0) ...

    else if (i % 3 == 1) ...

    else //i % 3 ==2

    assert i >= 0;

    if (i % 3 == 0) ...

    else if (i % 3 == 1) ...

    else assert i % 3 ==2;

    记录日志

    基本日志

    使用全局日志记录器并调用 info 方法:

    Logger.getGlobal().info("File->Open menu item selected");

    内容:

    May 10, 2013 10:23:43 PM LoggingImageViewer fileOpen

    INFO: File->Open menu item selected

    在适当的地方(如 main 开始)以下将会取消所有日志:

    Logger.getGlobal().setLevel(Level.OFF);

    调试技巧

    打印任意变量的值:System.out.println("x=" + x);

    在每个类中放置一个单独的 main 方法,做单元测试。

    可以使用 JUnit 单元测试框架。

    展开全文
  • 在应用程序中输出日志有有三个目的:(1)监视代码中变量变化情况,把数据周期性地记录到文件中供其他应用进行统计分析工作。(2)跟踪代码运行进轨迹,作为日后审计依据。(3)担当集成开发环境中调试器,向文件或...

    在应用程序中输出日志有有三个目的:

    (1)监视代码中变量的变化情况,把数据周期性地记录到文件中供其他应用进行统计分析工作。

    (2)跟踪代码运行进轨迹,作为日后审计的依据。

    (3)担当集成开发环境中的调试器,向文件或控制台打印代码的调试信息。

    Apache能用日志包(Commons Logging Package)是Apache的一个开放源代码项目,它提供了一组通用的日志接口,用户可以自由地选择实现日志接口的第三方软件。通用日志包目前支持以下日志实现:

    JDK1.4 Logging日志器(JDK1.4自带)

    SimpleLog日志器(把日志消息输出到标准系统错误流System.err)

    NoOpLog(不输出任何日志信息)

    通用日志包中的两个常用接口:LogFactory和Log,分别介绍如下:

    Log接口

    通用日志包把消息分为6个级别:FATAL、ERROR、WARN、INFO、DEBUG和TRACE。其中FATAL级别最高,TRACE级别最低。Log接口提供输出不同级别消息的方法:

    fatal(Object message)-------输出FATAL级别的消息。

    error(Object message)-------输出ERROR级别的消息。

    warn(Object message)-------输出WARN级别的消息。

    info(Object message)-------输出INFO级别的消息。

    debug(Object message)-------输出DEBUG级别的消息。

    trace(Object message)-------输出TRACE级别的消息。

    注:只有当输出日志的级别大于或等于为日志配置器配置的日志级别时,这个方法才会执行。

    如何指定日志器的日志级别,不同的日志器实现会有不同的实现方案。

    LogFactory接口

    LogFactory接口提供了获得日志器实例的两个静态方法:

    public static Log getLog(String name) throws LogConfigurationException;

    public static Log getLog(Class class) throws LogConfigurationException;

    注:name参数作为日志器的名字;class参数指定类名作为日志器名字。

    以下介绍最常用的一个日志实现--------Log4J

    Log4j是Apache的一个开放源代码项目,它是一个日志操作包。通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

    此外,通过Log4j其他语言接口,您可以在C、C++、.Net、PL/SQL程序中使用Log4j,其语法和用法与在Java程序中一样,使得多语言分布式系统得到一个统一一致的日志组件模块。而且,通过使用各种第三方扩展,您可以很方便地将Log4j集成到J2EE、JINI甚至是SNMP应用中。

    Log4J主要由三大组件构成:

    Logger:负责生成日志,并能根据配置的日志级别来决定什么日志消息应该被输出,什么日志消息应该被忽略。

    Appender:定义日志消息输出的目的地,指定日志消息应该被输出到什么地方,这些地方可以是控制台、文件和网络设备等。

    Layout:指定日志消息的输出格式。

    这三个组件协同工作,使得开发者能够依据日志消息类别来输出日志,并能够在程序运行期间,控制日志消息的输出格式以及日志存放地点。

    Log4J的配置

    配置Log4J,需要分别配置它的Logger、Appender和Layout属性。配置文件一般为log4j.properties。当然也可以以XML文件来配置,这里介绍以属性文件配置。

    配置Logger组件

    Logger组件支持继承关系,所有的Logger组件都直接或间接继承rootLogger。配置rootLogger的语法为:

    log4j.rootLogger=[priority],appenderName,appenderName,......

    priority是如前所述的日志级别;

    appenderName指定Appender组件,用户可以同时指定多个Appender组件,以与逗号分隔。

    配置Appender组件

    配置日志消息输出目的地Appender,语法为:

    log4j.appender.appenderName=

    log4j.appender.appenderName.option1=value1

    log4j.appender.appenderName.option2=value2

    ...

    Log4J共有以下几种Appender:

    org.apache.log4j.ConsoleAppender(控制台)

    org.apache.log4j.FileAppender(文件)

    org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)

    org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)

    org.apache.log4j.WriterAppender(将日志消息以流格式发送到任意指定的地方)

    配置Layout组件

    语法:

    log4j.appender.appenderName.layout=

    log4j.appender.appenderName.layout.option1=value1

    log4j.appender.appenderName.layout.option2=value2

    ...

    Log4J提供以下几种Layout:

    org.apache.log4j.HTMLLayout(以HTML表格形式布局)

    org.apache.log4j.PatternLayout(可以灵活地指定布局模式)

    org.apache.log4j.SimpleLayout(包含日志消息的级别和信息字符串)

    org.apache.log4j.TTCCLayout(包含日志产生的时间、线程和类别等信息)

    通过设置PatternLayout的ConversionPattern属性来指定输出格式

    ConversionPattern的格式如下表所示:

    格式名      含义

    %c       输出日志信息所属的类的全名

    %d      输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:

    %d{yyy-MM-dd HH:mm:ss },输出类似:2002-10-18- 22:10:28

    %f       输出日志信息所属的类的类名

    %l       输出日志事件的发生位置,即输出日志信息的语句处于它所在的类的第几行

    %m        输出代码中指定的信息,如log(message)中的message

    %n      输出一个回车换行符,Windows平台为“/r/n”,Unix平台为“/n”

    %p      输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL。如果是调用debug()输出的,则为DEBUG,依此类推

    %r      输出自应用启动到输出该日志信息所耗费的毫秒数

    %t      输出产生该日志事件的线程名

    示例:log4j.appender.file.layout=org.apache.log4j.PatternLayout

    log4j.appender.file.layout.ConversionPattern=%t %p- %m%n

    Log4J对应用性能的影响

    如果在程序运行中输出大量日志,显然会对应用的性能造成一定的影响。Log4J对性能的影响取决于以下因素:

    日志输出目的地:输出到控制台的速度和输出到文件系统的速度是不一样的。

    日志输出格式:格式简单,速度也更快。

    日志级别:日志级别设置的越低,输出的日志内容越多,对性能的影响也越大。

    展开全文
  • 日志论在应用程序中输出日志有有三个目的:(1)监视代码中变量变化情况,把数据周期性地记录到文件中供其他应用进行统计分析工作。(2)跟踪代码运行进轨迹,作为日后审计依据。(3)担当集成开发环境中调试器,向...
  • 日志记录器: 个人总结:就是要记录一下代码运行,记录一下重要的过程。特别是异常。比如:一个项目有些错误很长时间发生一次,我们就...控制日志的输出级别 控制日志信息输送的目的地是控制台、文件等 控制每一条日志
  • java日志操作之Log4j

    2010-11-30 10:37:00
    <br /> 在应用程序中输出日志有有三个目的: (1)监视代码中变量变化情况,把数据周期性地记录到文件中供其他应用进行统计分析工作。 (2)跟踪代码运行进轨迹,作为日后审计依据。 (3...
  • 守护线程主要用于后台记录操作日志,监控内存,垃圾回收等功能。通过setDaemon(true)可以将线程设置守护线程。 示例代码 这里启动一个守护线程和一个用户线程,运行代码可以看到,在用户线程运行结束后,程序会中止...
  • 例如, 我们有一个已经投入运行项目中有一个用户DAO类UserDao用来对User对象进行数据库增删改查操作,但是有一天,要求在对用户的增删改查操作记录相应的日志,这是怎么办呢?难道我们去直接修改UserDao源...
  • 执行代码 ``` HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); SsOperLog ssOperLogEntity = new SsOperLog(); ssOperLogEntity....
  • Tcp服务端与客户端的JAVA实例源代码 2个目标文件 摘要:Java源码,文件操作,TCP,服务器 Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端程序,两者互相配合可以开发出超多...
  • aop 实现Java日志功能

    2020-12-03 09:35:48
    aop 是一个强大的..,思路很...1.第一步 自定义一个@Log注解,标记到你要记录日志的controller上面。我的注解有三个参数,分别是事件类型,操作类型,描述。可以在切面里面获取到他们分别标记在控制层上面的值。 im.
  • Java核心技术 卷Ⅰ》 第7章 异常、断言和日志 处理错误 捕获异常 使用异常机制技巧 记录日志 处理错误 如果由于出现错误而是某些操作没有完成,程序应该: 返回到一种安全状态,并让用户执行一些其他操作;...
  • java开发中日志的管理有很多种, 在这里推荐Spring 的Aop思想将每一次请求记录 ,并且保存到数据库表中。 通常情况下,我们将项目部署到服务器后,如果接口出现了bug,那么我们就可以通过查看数据库表中记录的信息...
  • 鉴于此,现在系统已经完成了所有功能开发,我们需要把系统的操作日志记录起来,以方便查看某人某时执行了哪一些操作。Spring AOP可以方便查看到某人某时执行了哪一些类哪一些方法,以及对应参数。但是大...
  • 在日常开发中,我们经常需要对接接口数据,日志记录用户操作,如果单纯使用手动记录话不仅会让代码看起来不美观还增加了很多工作量。但是如果使用aop切面在不影响业务情况下进行日志访问记录话就省事多了。 ...
  • 题主想知道是怎么讲java的异常应用到实际项目中吧举...其中getPen 方法返回结果信息给用户有2次数据库操作返回信息是boolean, 但是在实际写代码是我们能知道,如果返回false ,虽然告诉了操作失败,但是失败原因可能...
  • xml方式---springAOP拦截用户操作

    千次阅读 2013-03-13 11:40:40
    需要日志记录,将所有的web操作记录到数据库中,使用aop来记录日志,当然是一个好的选择,spring中集成aop记录日志的方式有多种(aop的配置方式有多种,注解、xml配置),这里只说一个xml配置的例子。  1、编写...
  • 1、主要实现用户在进行某项操作时,多数据库更新、插入和删除详细信息。记录操作请求信息。2、在进入Controller时,生成一个事物ID,在这个Controller中进行所有DAO操作都绑定该事物ID。并进行记录日志信息...
  • [myLog4jTest]log4j使用实例-----记录日志 [myMailWeb]网站注册-QQ邮箱发送激活邮箱,点击注册-实例 [myOnlinesWeb]网站在线用户信息,网站访问量... [myOnlinesWeb2]网站在线用户信息,网站访问量以及管理员踢出...
  • Java之手写异步任务

    万次阅读 2020-04-03 09:47:28
    比如在用户操作软件时候需要记录一些操作日志,频繁写入db操作会影响用户体验。 实现思路: 首先创建一个AbstractQueue类,用于存放任务队列。然后创建一个AbstractAsynTask类,用于管理AbstractQueue队列。 ...
  • Java项目开发全程实录》这一本书从开发背景、需求分析、系统功能分析、数据库分析、数据库建模、网站开发和网站发布或者程序打包与运行,每一过程都进行了详细介绍。 目 录 第1章 进销存管理系统(Swing+SQL ...
  • java开源包1

    千次下载 热门讨论 2013-06-28 09:14:34
    J2C 将 Java 代码转成 C++ 代码,这是源码级别的转换,输出的 C++ 代码是有效的代码。 OSGi 分布式通讯组件 R-OSGi R-OSGi 是一套适用于任意满足 OSGi 架构的分布式通讯组件。它以 jar 的形式发布,部署容易,使用...

空空如也

空空如也

1 2 3 4 5 ... 9
收藏数 163
精华内容 65
关键字:

java记录用户操作日志的代码

java 订阅