需求:我们需要在请求某些特定的URL(URL格式为Restful格式)时添加拦截器,以实现进行权限控制。

如:/ResourcePlan/projectCode/P1503127828/PROJECT_TYPE_MSMS/2052/00018785

前台的Controller:

     @ApiOperation("获取单个项目的****信息")
@ApiImplicitParams({
@ApiImplicitParam(paramType="path",name="projectCode",dataType="String",required=true,value="项目编码"),
@ApiImplicitParam(paramType="path",name="projectType",dataType="String",required=true,value="项目类型"),
@ApiImplicitParam(paramType="path",name="cultureNo",dataType="String",required=false,defaultValue="2052",value="语言类型"),
@ApiImplicitParam(paramType="path",name="empIdUi",dataType="String",required=true,value="人员工号")
})
@ApiResponses({
@ApiResponse(code=400,message="请求参数没填好"),
@ApiResponse(code=404,message="请求路径没有或页面跳转路径不对")
})
@RequestMapping(value="/projectCode/{projectCode}/{projectType}/{cultureNo}/{empIdUi}",method= RequestMethod.GET)
@ResponseBody
//@UrlPattern(value="^/ResourcePlan/projectCode/([a-zA-z0-9]{1,})/([a-zA-z0-9]{1,})/([0-9]{1,4})/([0-9]{1,})")
public ServiceData<ResourcePlan> getResourcePlan(@PathVariable("projectCode") String projectCode,
@PathVariable("projectType") String projectType,
@PathVariable("cultureNo") String cultureNo,
@PathVariable("empIdUi") String empIdUi){
ServiceData<ResourcePlan> ret = new ServiceData<ResourcePlan>();
try {
ResourcePlan resourcePlan= rps.getResourcePlan(projectCode, projectType, cultureNo);
ret.setBo(resourcePlan);
} catch (Exception e) {
RetCode code =RetCode.BusinessError;
ret.setCode(code,e.getMessage());
}
return ret;
}

为了拦截这个URL,将拦截器注册到拦截器配置器,代码如下:

 1 @Configuration
2 public class UrlInterceptConfig extends WebMvcConfigurerAdapter {
3
4 @Override
5 public void addInterceptors(InterceptorRegistry registry) {
6 System.out.println("进入拦截器配置器");
7
8 //注册拦截器
9 InterceptorRegistration iRegistration=registry.addInterceptor(new ProjectAuthInterceptor());
10 iRegistration.addPathPatterns("/ResourcePlan/projectCode/**");
11 //super.addInterceptors(registry);
12 }
13 }

拦截到这个格式的URL以后,我们实现了以下的拦截器来做业务控制:

 public class ProjectAuthInterceptor implements HandlerInterceptor {

     @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception { } @Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub } @Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception { } }

我们需要在拦截器中解析出Restful格式的URL中相应的参数,preHandle的第3个参数指的是拦截的那相方法的相应信息,可以得到这个方法的签名,但得不到相应传递进来的参数值。

因而,要想得到相应的参数值,我们必须得另想办法。

我实现的思路是

1、使用正则表达式来匹配URL,为了项目的更易维护,我决定把正则表达式通过注解的方式放在Controller的上面,就如第一段代码注释掉的那一行。

注解如下:

 @Retention(RetentionPolicy.RUNTIME)
@Target({ java.lang.annotation.ElementType.METHOD })
public @interface UrlPattern { String value(); }

正则如下

@UrlPattern(value="^/ResourcePlan/projectCode/([a-zA-z0-9]{1,})/([a-zA-z0-9]{1,})/([0-9]{1,4})/([0-9]{1,})")

2、通过正则将所有的参数都匹配出来,然后进行业务逻辑判断,下面是实现preHandle的代码

     @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("开始校验****权限");

//根据正则从URL中提取参数值
HandlerMethod method= ((HandlerMethod)handler);
UrlPattern urlPatternAnno= method.getMethodAnnotation(UrlPattern.class);
String urlPattern=urlPatternAnno.value();
ApplicationConfig app= (ApplicationConfig)SpringContextUtil.getBean("applicationConfig");
String urlRequest=request.getRequestURI();
if(request.getRequestURI().indexOf(app.getContext())>) {
urlRequest=request.getRequestURI().substring(app.getContext().length());
}
Matcher mathcer = Pattern.compile(urlPattern).matcher(urlRequest);
List<String> paraValue=new ArrayList<String>();
if (mathcer.find()) {
for (int i = ; i <= mathcer.groupCount(); i++) {
paraValue.add(mathcer.group(i));
}
}

//获取参数名称
MethodParameter[] methodParameters= method.getMethodParameters();
if(paraValue.size()!=methodParameters.length) {
throw new Exception("参数个数不匹配");
} //整理参数名&参数值的键值对
Dictionary<String, String> params=new Hashtable<>() ;
for (int i = ; i < methodParameters.length; i++) {
params.put(methodParameters[i].getParameterName(), paraValue.get(i));
}

//业务上校验业务逻辑
String projectCode=params.get("projectCode");
String projectType=params.get("projectType");
String empIdUi=params.get("empIdUi");
AuthService authService= (AuthService)SpringContextUtil.getBean("authService");
boolean hasRight= authService.checkAuth(projectCode, projectType, empIdUi);
if(!hasRight) {
throw new Exception("没有*****的权限!");
}
return hasRight;
}

这里还需要在Controller上配置注解,其实更简单的方法是直接分析@RequestMapping这个注解,这样就不用配置自定义注解了,而且也不用编写正则表达式了,感兴趣的同学可以自己尝试下。

参考文档

http://blog.csdn.net/linzhiqiang0316/article/details/52671709  //实现了postHandle

http://blog.csdn.net/Jalon2015/article/details/71423974

在SpringMVC中使用HandlerInterceptor来实现拦截器功能的更多相关文章

  1. SSM框架之SpringMVC(6)异常处理及拦截器

    SpringMVC(6)异常处理及拦截器 1.异常处理 1.1.异常处理的思路 ​ 系统中异常包括两类:预期异常和运行时异常 RuntimeException,前者通过捕获异常从而获取异常信息,后者主 ...

  2. SpringBoot中过滤器、监听器以及拦截器

    属于javax.servlet所提供的Api 拦截器原理 简单来讲是通过动态代理实现,被访问的目标方法通过代理类(方法)来执行,这样我们就可以在真正要执行的方法执行前.后做一些处理: 通过拦截器这种方 ...

  3. SpringMVC源码情操陶冶-InterceptorsBeanDefinitionParser拦截器解析器

    解析mvc:interceptors节点 观察下InterceptorsBeanDefinitionParser的源码备注 /** * {@link org.springframework.beans ...

  4. SpringMVC初写(五)拦截器

    在系统开发过程中,拦截器的使用可以使我们实现一些需求.如:登录认证,权限管理等,拦截器的工作核心就是将一些工作流程进行统一处理 拦截器和过滤器的区别: 过滤器过滤的是请求路径,拦截器拦截的各层方法的映 ...

  5. 【SpringMVC配置失效】Springboot2.x拦截器配置不无生效

    一.环境 maven springboot版本2.x <parent> <groupId>org.springframework.boot</groupId> &l ...

  6. SpringMVC归纳-2(Session会话、拦截器)

    要点: 1.HttpSession:一个session的建立是从一个用户向服务器发第一个请求开始,而以用户显式结束或session超时为结束,借助session能在一定时间内记录用户状态. 2.Mod ...

  7. springMVC整理04--文件上传 & 拦截器 & 异常处理

    1.  文件上传 SpringMVC 的文件上传非常简便,首先导入文件上传依赖的 jar: <!-- 文件上传所依赖的 jar 包 --> <dependency> <g ...

  8. Java 中的过滤器Filter 和拦截器 Interceptor

    1.先说拦截器 Interceptor 本项目以springboot为例: 新建 InterceptorConfig package com.opendev.mystudy.MyInterceptor ...

  9. java中过滤器、监听器、拦截器的区别

    1.过滤器:所谓过滤器顾名思义是用来过滤的,在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的actio ...

随机推荐

  1. 传统BI还是自助式BI---BI与数据分析 ZT

    自助式BI或者自助式数据分析是最近几年兴起的一个概念.根据Gartner发布的信息,Self Service Business Intelligence(SSBI)被定义为“终端用户在被批准和支持的平 ...

  2. Python 基于python实现单例模式

    基于python实现单例模式 by:授客 QQ:1033553122   概念 简单说,单例模式(也叫单件模式)的作用就是保证在整个应用程序的生命周期中,任何一个时刻,单例类的实例都只存在一个(当然也 ...

  3. Linux profile1,bashrc,.bash_profile,.bash_login,.profile,.bashrc,.bash_logout浅析 Part1

    profile,bashrc,.bash_profile,.bash_login,.profile,.bashrc,.bash_logout浅析 Part 1   by:授客 QQ:103355312 ...

  4. Linux 学习笔记之超详细基础linux命令 Part 14

    Linux学习笔记之超详细基础linux命令 by:授客 QQ:1033553122 ---------------------------------接Part 13---------------- ...

  5. loadrunner 场景设计-手工场景方案(Schedule)设计

    场景设计-手工场景方案(Schedule)设计 by:授客 QQ:1033553122 A.   定义方案schedule 在 Scenario Schedule面板中,选择一个方案schedule, ...

  6. BeanFactory和ApplicationContext的比较

    1.BeanFactory实例化后,不会马上实例化Bean:ApplicationContext在实例化后紧跟着就会实例化Bean 2.ApplicationContext还实现了ResourceLo ...

  7. 使用katalon自带Spy功能获取/验证控件Selector、XPath

    背景 最近刚接手一个katalon编写的UI自动化项目,页面最近刚改版,已有用例很多查找元素失败.了解到katalon元素定位支持xpath,所以直接使用chrome开发者工具打开目标页面+获取xpa ...

  8. 性能测试—JMeter 常用元件(四)

    <零成本web性能测试>第三章 Web性能测试脚本录制与开发中JMeter常用测试元件 测试计划描述了JMeter运行时将会执行的一系列步骤,一个完整的测试计划包含一个或多个线程组.逻辑控 ...

  9. 分布式文件系统(HDFS)与 linux系统文件系统 对比

    初次接触分布式文件系统,有很多迷惑.通过参考网络文章,这里进行对比一下Hadoop 分布式文件系统(HDFS)与 传统文件系统之间的关系:   Linux 文件系统 分布式文件系统 块 块对应物理磁盘 ...

  10. httpd的一些知识点

    一.httpd持久化连接:使用httpd之telnet测试其keepalive连接状态 作用:连接建立后,每个资源获取结束不会断开连接,而继续等待其他资源请求并完成传输. 1.KeepAlive  O ...