需求:我们需要在请求某些特定的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. 《Inside C#》笔记(五) 方法

    方法用来体现类的行为. 一 相关概念 a) ref和out 通常一个方法只能返回一个值,但如果确实需要返回多个值时,可以使用ref或out.如果方法的参数被标注为ref或out,在调用该方法时,会传递 ...

  2. 腾讯X5WebView集成及在移动端中使用

    工作中经常涉及H5网页的加载工作,最多使用的就是安卓系统控件WebView,但是当网页内容比较多的时候,需要等待很久才能加载完,加载完后用户才能看到网页中的内容,这样用户需要等很久,体验很差. 那能不 ...

  3. 消除TortoiseSVN 检出到(checkout)桌面上显示一堆问号

    之前不小心直接将版本库的内容检出到桌面,后才发现桌面上的文件图标都变成了问号,新建文件夹也同样如此. 为了解决这个问题,采用如下方法(任何一个检出文件夹均可这样操作): 1.删除桌面隐藏的.SVN文件 ...

  4. sql server 数据导出(入)方法总结

    我们都知道日常在面对数据需求时需要导出数据,比较少量的数据导出我们一般是通过查询后另存即可,当面对数据量比较大的时候我们应该怎么处理?我搜索总结一些几个方法:1.bcp 导出.2.数据库本身自带的导入 ...

  5. 谷歌浏览器javascript错误提示插件

    JavaScript-Errors-Notifier_v2.1.7 下载地址 安装方法: http://chromecj.com/utilities/2014-09/181.html 设置方式:

  6. CentOS7安装搭建.Net Core 2.0环境-详细步骤

    一.构建.Net core 2的应用程web发布 因为是用来测试centos上的core 环境,先直接用vs17自带的core实例. 二.部署CentOS7的core环境 1.连接并启动之前安装的虚拟 ...

  7. python redirect和render的区别

    render是渲染变量到模板中,而redirect是HTTP中1个跳转的函数,一般会生成302状态码.

  8. Orcale的NVL、NVL2函数和SQL Server的ISNULL函数

    Orcal 的 nvl函数 NVL(Expr1,Expr2)如果Expr1为NULL,返回Expr2的值,否则返回Expr1的值,Expr1,Expr2都为NULL则返回NULL NVL2(Expr1 ...

  9. MVC设计模式在网站中的应用

    MVC设计模式在网站中的应用 以淘宝的购物车为例 一.结合六个基本质量属性 可修改性 采用MVC设计模式的时候,可以将视图.模型.控制器分析,将用户动作.数据表示.应用数据分离开来,如果用户需要以不同 ...

  10. MySQL视图 索引 存储过程 触发器 函数

       视图: 也就是一个虚拟表(不是真实存在的),它的本质就是根据SQL语句获取动态的数据集,并为其命名.用户使用时只需要使用命名的视图即可获取结果集,并可以当做表来使用.它的作用就是方便查询操作,减 ...