java拦截器原理

java拦截器的基本原理其实非常简单,说白了就是动态代理类。

  下面来看一个简单的例子

  首先,我建立一个拦截器的类InterceptorClass,这里的before()和after()方法是以后拦截器会执行的方法

  CODE清单一:

  Java代码

  <SPAN style="FONT-SIZE: small">//拦截器

  public class InterceptorClass {

  public void before() {

  System.out.println("拦截器InterceptorClass方法调用:before()!");

  }

  public void after() {

  System.out.println("拦截器InterceptorClass方法调用:after()!");

  }

  }</SPAN>

  我们模拟一个业务组件接口BusinessInterface,和一个业务组件实现类BusinessClass

  CODE清单二:

  Java代码

  <SPAN style="FONT-SIZE: small">/**

  * Created by IntelliJ IDEA.

  * User: Ming

  * Date: 2010-9-7

  * Time: 8:45:26

  */

  //业务组件接口

  public interface BusinessInterface {

  public void doSomething();

  }</SPAN>

  CODE清单三:

  Java代码

  <SPAN style="FONT-SIZE: small">/**

  * Created by IntelliJ IDEA.

  * User: Ming

  * Date: 2010-9-7

  * Time: 8:46:27

  */

  //业务组件实现类

  public class BusinessClass implements BusinessInterface {

  public void doSomething() {

  System.out.println("业务组件BusinessClass方法调用:doSomething()");

  }

  }</SPAN>

  然后,创建一个动态代理类DynamicProxyHandler,这个类是集成InvocationHandler接口的,动态类的原理实际上是使得当你执行一个动态方

  法的时候,他可以把这个动态方法dispatch到这个动态类上来。这样,你就可以在这个方法的前后嵌入自己的一些方法。

  CODE清单四:

  Java代码

  <SPAN style="FONT-SIZE: small">/**

  * Created by IntelliJ IDEA.

  * User: Ming

  * Date: 2010-9-7

  * Time: 8:50:35

  */

  /**

  * 动态代理类,实现InvocationHandler接口.

  * 包含了业务对象绑定动态代理类的处理

  */

  public class DynamicProxyHandler implementsInvocationHandler {

  private Object business;//被代理对象

  private InterceptorClass inceptor = newInterceptorClass();//拦截器

  public DynamicProxyHandler(Object business) {

  this.business = business;

  }</SPAN>

 

// 代理要调用的方法,并在方法调用前后调用连接器的方法

  Java代码

  <SPAN style="FONT-SIZE: small">/**

  * @param proxy    代理类对象

  * @param method   被代理的接口方法

  * @param args      被代理接口方法的参数

  * @return

  * @throws Throwable

  */

  public Object invoke(Object proxy, Method method,Object[] args) throws Throwable {

  Object result = null;

  inceptor.before();

  result = method.invoke(business, args);

  inceptor.after();

  return result;

  }</SPAN>

  OK,我们来写个类测试一下

  CODE清单五:

  Java代码

  <SPAN style="FONT-SIZE:small">    public static void main(String[] args) {

  //生成待测试的业务组件对象

  BusinessInterface business = new BusinessClass();

  //生成动态代理类实例

  DynamicProxyHandler handler = newDynamicProxyHandler(business);

  BusinessInterface businessProxy = (BusinessInterface)Proxy.newProxyInstance(

  //被代理类的ClassLoader

  business.getClass().getClassLoader(),

  //要被代理的接口,本方法返回对象会自动声称实现了这些接口

  business.getClass().getInterfaces(),

  //代理处理器对象

  handler);

  //用动态代理类调用方法

  businessProxy.doSomething();

  }</SPAN>

  来看看结果:

  近期struts2很流行,而且拦截器是struts2里面一个比较好的功能,下面举个例子说明一下拦截器在struts2中的用法。

  struts2对拦截器实现做了一个封装,使得我们在实现的时候比较简单。

  首先我们要建一个拦截器类

  CODE清单六:

  Java代码

  <SPAN style="FONT-SIZE: small">publicclass AuthorizationInterceptor extends AbstractInterceptor {

  @Override

  public String intercept(ActionInvocation invocation)throws Exception {

  Map session =invocation.getInvocationContext().getSession();

  String userName = (String)session.get("userName");

  if ( userName != null &&userName.equals("test")) {

  System.out.println("拦截器:合法用户登录---");

  return invocation.invoke();

  }

  else

  {

  System.out.println("拦截器:用户未登录---");

  return Action.LOGIN;

  }

  }

  }

  </SPAN>

  这个类是必须要继承struts2包中提供的AbstractInterceptor类,这个类有一个抽象方法intercept,这个方法是必须要实现的。

  那么经理在这个拦截器里面写了一个简单的实现,对url用户合法性做了一个限制。

  接下来比较关键的是过滤器在struts2中的配置,先看看代码

  CODE清单七:

  Java代码

  <SPAN style="FONT-SIZE:small"><package name="system"extends="struts-default">

  <interceptors>

  <!--  定义权限控制拦截器 -->

  <interceptor name="authority"

  class="com.sharesin.biz.common.intercepts.struts2.AuthorizationInterceptor"/>

  <!-- 定义一个包含权限控制的拦截器栈  -->

  <interceptor-stack name="mystack">

  <interceptor-refname="defaultStack"></interceptor-ref>

  <interceptor-refname="authority"></interceptor-ref>

  </interceptor-stack>

  </interceptors>

  <!--定义默认拦截器   -->

  <default-interceptor-ref name="mystack"/>

  <!--定义全局处理结果  -->

  <global-results>

  <resultname="login">index.jsp</result>

  </global-results>

  <action name="login_*"class="com.sharesin.biz.web.system.LoginAction"method="{1}">

  <resultname="success">system/homepage.jsp</result>

  </action>

  </package></SPAN>

  在interceptors节点里,我们可以定义多个拦截器,这里的名为authority的只是其中的一个。struts2的拦截器栈我是先执行struts2默认的拦

  截器defaultStack,然后再执行我的。然后只需要用default-interceptor-ref标签设置好这个system包中的默认拦截器为这个拦截器就OK了。

  struts2中引入了package这个概念,我觉得十分实用,当然这对struts2拦截器也是个实惠,我们可以根据不同的action来分包和不同的拦截器

  ok,来运行测试一下。

 

拦截器类 需要两个配合使用这里只有一个 @Configuration public class ServletContextConfig extends WebMvcConfigurerAdapter { public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/"); registry.addResourceHandler("/templates/**").addResourceLocations("classpath:/templates/"); super.addResourceHandlers(registry); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new HandlerMyInterceptorAdapter()).addPathPatterns("/**") .excludePathPatterns("/") // .excludePathPatterns("/expressions/getExpressionsList") .excludePathPatterns("/loginInfo/getCordByIsPhone") .excludePathPatterns("/loginInfo/login11") //token失效跳轉 .excludePathPatterns("/loginInfo/insertLoginInfo") //注册 .excludePathPatterns("/loginInfo/login") //登录 .excludePathPatterns("/upload") //上传文件 .excludePathPatterns("/uploadListen") //上传文件 .excludePathPatterns("/admin/user/goLogin") //后台跳转登录 .excludePathPatterns("/admin/user/login") //后台登录 .excludePathPatterns("/loginInfo/getLoginInfo") //忘记密码 .excludePathPatterns("/loginInfo/getCord") //短信验证码 .excludePathPatterns("/loginInfo/getIsLoginInfo") //判断验证码&&登录 .excludePathPatterns("/loginInfo/getIsLoginInfo1") //判断验证码 .excludePathPatterns("/loginInfo/setPassWord") //设置密码 ; } @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } } @Component public class HandlerMyInterceptorAdapter implements HandlerInterceptor { @Autowired private HeartbeatServiceImpl heartbeatService; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { String url = request.getRequestURI(); if (url.contains("admin")) { User user = (User) request.getSession().getAttribute("user"); try { if (user.equals(null)) { response.sendRedirect(serverConfig.SERVER + "admin/user/goLogin"); return false; } else { return true; } }catch (Exception e){ response.sendRedirect(serverConfig.SERVER + "admin/user/goLogin"); return false; } }else { String token = request.getHeader("token"); if (token != null) { Jedis jedis = new Jedis(com.sevenSteps.util.RedisConfig.HOST, RedisConfig.PORT); String s = jedis.get(token); if(token.equals(s)) { heartbeatService = SpringUtil.getBean(HeartbeatServiceImpl.class); return heartbeatService.setOutDate(token); }else { response.sendRedirect(serverConfig.SERVER + "loginInfo/login11"); return true; } }else { response.sendRedirect(serverConfig.SERVER + "loginInfo/login11"); return true; } } } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object o, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值