001/** 002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package io.jboot.components.limiter; 017 018import com.jfinal.aop.Invocation; 019import com.jfinal.core.Controller; 020import io.jboot.Jboot; 021import io.jboot.exception.JbootException; 022import io.jboot.utils.ClassUtil; 023import io.jboot.utils.RequestUtil; 024import io.jboot.utils.StrUtil; 025 026import java.lang.reflect.Method; 027 028/** 029 * 默认的限流处理器 030 */ 031public class LimitFallbackProcesserDefault implements LimitFallbackProcesser { 032 033 protected LimitConfig config = Jboot.config(LimitConfig.class); 034 035 @Override 036 public void process(String resource, String fallback, Invocation inv) { 037 038 if (StrUtil.isNotBlank(fallback)) { 039 doProcessFallback(fallback, inv); 040 return; 041 } 042 043 if (inv.isActionInvocation()) { 044 doProcessWebLimit(resource, inv); 045 } else { 046 doProcessServiceLimit(resource, inv); 047 } 048 } 049 050 protected void doProcessFallback(String fallback, Invocation inv) { 051 Method method = getMethodByName(fallback, inv); 052 if (method == null) { 053 throw new JbootException("can not find method[" + fallback + "] in class " + 054 ClassUtil.getUsefulClass(inv.getTarget().getClass())); 055 } 056 057 try { 058 method.setAccessible(true); 059 Object invokeValue = method.getParameterCount() == 0 060 ? method.invoke(inv.getTarget()) 061 : method.invoke(inv.getTarget(), inv.getArgs()); 062 inv.setReturnValue(invokeValue); 063 } catch (Exception e) { 064 e.printStackTrace(); 065 } 066 } 067 068 069 protected Method getMethodByName(String methodName, Invocation inv) { 070 Class clazz = ClassUtil.getUsefulClass(inv.getTarget().getClass()); 071 Method[] methods = clazz.getMethods(); 072 for (Method m : methods) { 073 if (methodName.equals(m.getName())) { 074 return m; 075 } 076 } 077 return null; 078 } 079 080 081 /** 082 * 处理 Controller 的限流 083 * 084 * @param resource 085 * @param inv 086 */ 087 protected void doProcessWebLimit(String resource, Invocation inv) { 088 089 Controller controller = inv.getController(); 090 controller.getResponse().setStatus(config.getDefaultHttpCode()); 091 092 if (RequestUtil.isAjaxRequest(controller.getRequest())) { 093 controller.renderJson(config.getDefaultAjaxContent()); 094 } 095 //非ajax的正常请求 096 else { 097 String limitView = config.getDefaultHtmlView(); 098 if (limitView != null) { 099 controller.render(limitView); 100 } else { 101 controller.renderText("reqeust limit."); 102 } 103 } 104 } 105 106 /** 107 * 处理 Service 层的限流 108 * 109 * @param resource 110 * @param inv 111 */ 112 protected void doProcessServiceLimit(String resource, Invocation inv) { 113 if (Jboot.isDevMode()) { 114 System.err.println(resource + " is limited by LimitFallbackProcesser, return null"); 115 } 116 } 117}