Springboot通過自定義注解綁定Filter與Handler
- 簡介
-
- 使用步驟(示例)
-
- 定義名稱注解@Authorization
- 定義 Filter實作使用者權限認證
- 為資源開啟使用者認證
- 測試
- 源碼
- 下載下傳
簡介
利用Jersey架構開發Restful Web服務時,對于過濾器元件, Jersey提供名稱綁定的方式,我們可以靈活的配置過濾器。通過在過濾器和資源上添加同樣的自定義名稱注解,來綁定過濾器和特定資源,友善直覺。
在Springboot中,隻能在注冊過濾器時指定需要過濾或者不需要過濾的請求位址的方式來過濾特定資源,或者在過濾器的實作中通過寫死的方式實作更複雜的過濾規則,例如過濾POST請求,放行GET請求等。但是這種方式不夠直覺,更新過濾規則需要修改代碼,也很不友善。
本文主要是在Springboot中提供實作類似的名稱綁定方案。類名稱大都沿用javax.ws.rs中相同的名稱,實作的不夠全面,而且隻提供請求過濾的實作,但是基本可以滿足大多數應用場合。使用者也可以自行進行修改完善。文末提供源碼下載下傳連結,同時提供了具體的應用項目示例。
使用步驟(示例)
定義名稱注解@Authorization
使用Java标準的注解定義方式,定義一個運作時的、可以作用于方法和類上的注解。
@NameBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface Authorization {
}
定義 Filter實作使用者權限認證
通過實作接口ContainerRequestFilter實作@Authorization注解的具體功能。
- 在Springboot架構中注冊為Bean執行個體@Component;
- 綁定名稱注解@Authorization
@Component
@Authorization
public class LoginFilter implements ContainerRequestFilter
{
protected static String TOKEN ="123456"; //only for test
@Override
public boolean filter(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException
{
// TODO Auto-generated method stub
System.out.println("LoginFilter in!!!!!");
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse rsp = (HttpServletResponse) servletResponse;
rsp.setCharacterEncoding("UTF-8");
rsp.setContentType("application/json; charset=utf-8");
String token = req.getParameter("token");//attach token with query parameter
GeneralWebRsp gRsp=new GeneralWebRsp();
gRsp.setCode(4000);
gRsp.setMessage("認證失敗");
if(token!=null)
{
if(TOKEN.equals(token))
{
gRsp.setCode(200);
gRsp.setMessage("認證通過");
}
}
if (gRsp.getCode() !=200)
{// 驗證失敗
PrintWriter writer = null;
OutputStreamWriter osw = null;
osw = new OutputStreamWriter(servletResponse.getOutputStream(),
"UTF-8");
writer = new PrintWriter(osw, true);
ObjectMapper objectMapper = new ObjectMapper();
String jsonStr = objectMapper.writeValueAsString(gRsp);
writer.write(jsonStr);
writer.flush();
writer.close();
osw.close();
return false;
}
return true;
}
}
-
filter傳回值
true :通過過濾條件,将進入後續的過濾器鍊
false :未通過過濾條件,傳回響應,将中斷後續的過濾器鍊
為資源開啟使用者認證
為資源對應的Controller或者具體的處理方法添加注解@Authorization。
@RequestMapping(value="/openapi/getUserList",method=RequestMethod.GET)
@ResponseBody
@Authorization //In such case name-bound filters bound by @Authorization
//will be applied to this handler method
public GeneralWebRsp<List<User>> getUserList()
{
GeneralWebRsp<List<User>> grsp=new GeneralWebRsp<>();
List<User> users=new ArrayList<>();
User user= new User();
user.setAge(8);
user.setSex("男");
user.setName("王二小");
users.add(user);
user= new User();
user.setAge(16);
user.setSex("女");
user.setName("劉胡蘭");
users.add(user);
grsp.setCode(200);
grsp.setMessage("操作成功");
grsp.setData(users);
return grsp;
}
注:也可以将@Authorization作用于Controller,這樣可以為Controller中的所有方法開啟使用者認證過濾。
測試
- 在浏覽器中直接通路http://localhost:8080/openapi/getUserList,傳回
{"code":4000,"message":"認證失敗","data":null}
- 在浏覽器中直接通路http://localhost:8080/openapi/getUserList?token=123456,傳回
{"code":200,"message":"操作成功","data":[{"name":"王二小","sex":"男","age":8},{"name":"劉胡蘭","sex":"女","age":16}]}