需求:我們需要在請求某些特定的URL(URL格式為Restful格式)時添加攔截器,以實現進行權限控制。
如:/ResourcePlan/projectCode/P1503127828/PROJECT_TYPE_MSMS/2052/00018785
前台的Controller:
1 @ApiOperation("獲取單個項目的****信息") 2 @ApiImplicitParams({ 3 @ApiImplicitParam(paramType="path",name="projectCode",dataType="String",required=true,value="項目編碼"), 4 @ApiImplicitParam(paramType="path",name="projectType",dataType="String",required=true,value="項目類型"), 5 @ApiImplicitParam(paramType="path",name="cultureNo",dataType="String",required=false,defaultValue="2052",value="語言類型"), 6 @ApiImplicitParam(paramType="path",name="empIdUi",dataType="String",required=true,value="人員工號") 7 }) 8 @ApiResponses({ 9 @ApiResponse(code=400,message="請求參數沒填好"), 10 @ApiResponse(code=404,message="請求路徑沒有或頁面跳轉路徑不對") 11 }) 12 @RequestMapping(value="/projectCode/{projectCode}/{projectType}/{cultureNo}/{empIdUi}",method= RequestMethod.GET) 13 @ResponseBody 14 //@UrlPattern(value="^/ResourcePlan/projectCode/([a-zA-z0-9]{1,})/([a-zA-z0-9]{1,})/([0-9]{1,4})/([0-9]{1,})")
15 public ServiceData<ResourcePlan> getResourcePlan(@PathVariable("projectCode") String projectCode, 16 @PathVariable("projectType") String projectType, 17 @PathVariable("cultureNo") String cultureNo, 18 @PathVariable("empIdUi") String empIdUi){ 19 ServiceData<ResourcePlan> ret = new ServiceData<ResourcePlan>(); 20 try { 21 ResourcePlan resourcePlan= rps.getResourcePlan(projectCode, projectType, cultureNo); 22 ret.setBo(resourcePlan); 23 } catch (Exception e) { 24 RetCode code =RetCode.BusinessError; 25 ret.setCode(code,e.getMessage()); 26 } 27 return ret; 28 }
為了攔截這個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以后,我們實現了以下的攔截器來做業務控制:
1 public class ProjectAuthInterceptor implements HandlerInterceptor { 2
3 @Override 4 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 5 throws Exception { 6
7 } 8
9 @Override 10 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, 11 ModelAndView modelAndView) throws Exception { 12 // TODO Auto-generated method stub
13
14 } 15
16 @Override 17 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) 18 throws Exception { 19
20
21 } 22
23 }
我們需要在攔截器中解析出Restful格式的URL中相應的參數,preHandle的第3個參數指的是攔截的那相方法的相應信息,可以得到這個方法的簽名,但得不到相應傳遞進來的參數值。
因而,要想得到相應的參數值,我們必須得另想辦法。
我實現的思路是
1、使用正則表達式來匹配URL,為了項目的更易維護,我決定把正則表達式通過注解的方式放在Controller的上面,就如第一段代碼注釋掉的那一行。
注解如下:
1 @Retention(RetentionPolicy.RUNTIME) 2 @Target({ java.lang.annotation.ElementType.METHOD }) 3 public @interface UrlPattern { 4
5 String value(); 6
7 }
正則如下
@UrlPattern(value="^/ResourcePlan/projectCode/([a-zA-z0-9]{1,})/([a-zA-z0-9]{1,})/([0-9]{1,4})/([0-9]{1,})")
2、通過正則將所有的參數都匹配出來,然后進行業務邏輯判斷,下面是實現preHandle的代碼
1 @Override 2 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 3 throws Exception { 4 System.out.println("開始校驗****權限"); 5
//根據正則從URL中提取參數值 6 HandlerMethod method= ((HandlerMethod)handler); 7 UrlPattern urlPatternAnno= method.getMethodAnnotation(UrlPattern.class); 8 String urlPattern=urlPatternAnno.value(); 9 ApplicationConfig app= (ApplicationConfig)SpringContextUtil.getBean("applicationConfig"); 10 String urlRequest=request.getRequestURI(); 11 if(request.getRequestURI().indexOf(app.getContext())>0) { 12 urlRequest=request.getRequestURI().substring(app.getContext().length()); 13 } 14 Matcher mathcer = Pattern.compile(urlPattern).matcher(urlRequest); 15 List<String> paraValue=new ArrayList<String>(); 16 if (mathcer.find()) { 17 for (int i = 1; i <= mathcer.groupCount(); i++) { 18 paraValue.add(mathcer.group(i)); 19 } 20 } 21
//獲取參數名稱 22 MethodParameter[] methodParameters= method.getMethodParameters(); 23 if(paraValue.size()!=methodParameters.length) { 24 throw new Exception("參數個數不匹配"); 25 }
//整理參數名&參數值的鍵值對 26 Dictionary<String, String> params=new Hashtable<>() ; 27 for (int i = 0; i < methodParameters.length; i++) { 28 params.put(methodParameters[i].getParameterName(), paraValue.get(i)); 29 } 30
//業務上校驗業務邏輯 31 String projectCode=params.get("projectCode"); 32 String projectType=params.get("projectType"); 33 String empIdUi=params.get("empIdUi"); 34 AuthService authService= (AuthService)SpringContextUtil.getBean("authService"); 35 boolean hasRight= authService.checkAuth(projectCode, projectType, empIdUi); 36 if(!hasRight) { 37 throw new Exception("沒有*****的權限!"); 38 } 39 return hasRight; 40 }
這里還需要在Controller上配置注解,其實更簡單的方法是直接分析@RequestMapping這個注解,這樣就不用配置自定義注解了,而且也不用編寫正則表達式了,感興趣的同學可以自己嘗試下。
參考文檔
http://blog.csdn.net/linzhiqiang0316/article/details/52671709 //實現了postHandle
http://blog.csdn.net/Jalon2015/article/details/71423974