通过反射获取上传文件方法参数中的文件名

122 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第12天,点击查看活动详情

最近系统在做安全测评,要求所有数据操作都要保留操作痕迹,于是PM要求所有接口按照增加、修改、查询、删除、导出、导入、审批、文件上传下载删除这几大操作类型统一增加日志。

这一需求的典型实现方法是给Controller层的接口加上自定义注解,通过AOP拦截所有方法来实现。 注解实现类中加了

@Target({ElementType.PARAMETER, ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

@Documented 这三个注解,这里不再赘述这三个注解的用法了,只描述一下具体实现逻辑:

我实现的这个自定义注解传入的参数有menu菜单名、title操作数据说明及操作类型,记录格式一般是:用户名+操作类型+菜单+操作数据说明+获取的参数信息。下面简单说一下其中的逻辑。

  • 1.增加:单条新增数据的方法统一返回新增记录id,根据拦截到的方法返回值获取id记录
  • 2.删除:循环request中的参数获取到id并记录
    Enumeration enu=request.getParameterNames();
    while(enu.hasMoreElements()){
        String paraName=(String)enu.nextElement();
        Object paramVal1 = request.getParameter(paraName); 
        if(paramVal1 != null && !"".equals(paramVal1.toString())){     
            sb.append(paraName+"为"+paramVal1+";");  
        }
    }

  • 3.查询:一般是GET请求也是循环request中的参数获取查询条件,这里注意参数有的放在request里,有的是如queryXXX/id 这种直接放在请求路径上的
String paraName=(String)enu.nextElement(); 
// 解析查询路径传参的情况,如 url/id 
if ("_".equals(paraName)){ 
    Map pathVariables = (Map) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); 
    String idInPath = (String) pathVariables.get("id"); 
    if (idInPath != null) { 
    sb.append("id为"+idInPath+";"); 
    } 
}
  • 4.修改/导出操作:默认也是根据request获取信息,但是我的POST请求类型是通过joinPoint.getArgs()获取的

StringBuffer exportStr = new StringBuffer(); 
String title = operLog.getTitle(); // 统计报表专用(因为所有统计报表公用一个导出接口) Object[] args = joinPoint.getArgs(); 
if ("统计报表".equals(controllerLog.menu()) && args.length>0){ 
    Map arguMap = (Map) args[0]; 
    title = arguMap.get("reportName")+"穿透"; 
    exportStr.append("tn为").append(arguMap.get("tn")) .append("exportMode为").append(arguMap.get("exportMode")); 
}
  • 5.文件上传、下载、删除
    我的文件上传是通过WebUploader组件实现的,上传文件记录了文件名,而下载和删除文件都只记录了文件id。注意这里有个小坑,Controller中获取文件名是直接将HttpServletRequest请求映射为MultipartHttpRequest实现的:
    MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
    通过反射获取到request之后再这样写就报错:cannot be cast to org.springframeworkweb.multipart.MultipartHttpServletRequest
    于是查了一下发现需要通过MultipartResolver转一下:
MultipartResolver resolver = new StandardServletMultipartResolver(); 
MultipartHttpServletRequest multiRequest = resolver.resolveMultipart(request);

这个具体原理大家可以查询,其他方式实现的文件上传不一定适用此方法。感兴趣的朋友可以留言跟我要相关代码及数据表。