JSP里EL表达式调用Java静态方法

2021-01-04 20点热度 0人点赞 0条评论

首先看下怎么在JSP里使用:

  1. JSP头部增加:
    <%
        request.setAttribute("call", new Call());
    %>
  2. 需要调用的静态方法,如Utils.java
    package com.terrynow.test.utils
    
    public class Utils {
        public static String testMethod(String args, String arg2) {
            //省略
            return "xxxx"
        }
    }
  3. JSP的代码里这样调用:
    <%-- 带参数arg1 arg2这种这样使用--%>
    ${call["com.terrynow.test.utils.Utils.testMethod"]["arg1"][arg2]}
    
    <%-- 不带参数这样使用--%>
    ${call["com.terrynow.test.utils.Utils.testMethod"]}

看下需要准备的文件:

新建Call.java
/*
 * Copyright (c) 2015.
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.terrynow.test.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * This class lets you call static methods from EL
 * 
 * Step 1) Create an instance of this class and bind it to the "call" variable
 * in your EL. For example, in a JSP do the following:
 * request.setAttribute("call", new Call());
 * 
 * Step 2) Call any static method as follows:
 * 
 * ${call["some.package.SomeClass.methodName"]["arg1"][arg2]}
 * 
 * The first argument is the fully qualified class and method name. The
 * remaining arguments are arguments to the method that you are calling.
 * 
 * Note: method overloading not supported
 * 
 * Note: method must be static
 * 
 * @author Vineet Manohar
 */
public class Call extends HashMap<String, Object> {
    private static final long serialVersionUID = 1L;

    @Override
    public Object get(Object key) {
        String fullyQualifiedMethodName = (String) key;

        // format of key is package.Class.method
        Pattern pattern = Pattern.compile("(.+)\\.([^\\.]+)");
        Matcher m = pattern.matcher(fullyQualifiedMethodName);
        if (m.matches()) {
            String fqClassName = m.group(1);
            String methodName = m.group(2);
            Class<Object> clazz;
            try {
                clazz = (Class<Object>) Class.forName(fqClassName);
            } catch (ClassNotFoundException e) {
                throw new IllegalArgumentException("Invalid method name: "
                        + key, e);
            }
            Method[] methods = clazz.getMethods();
            for (final Method method : methods) {
                if ((method.getModifiers() & Modifier.STATIC) == 0) {
                    continue;
                }

                if (method.getName().equals(methodName)) {
                    // return the first method found
                    int numParameters = method.getParameterTypes().length;

                    if (numParameters == 0) {
                        return invokeMethod(method);
                    }

                    return new ELMethod(numParameters) {
                        @Override
                        public Object result(Object[] args) {
                            return invokeMethod(method, args);
                        }
                    };
                }
            }
        }

        throw new IllegalArgumentException("Invalid method name: " + key
                + ". Must be a fully qualified class and method name");
    }

    private Object invokeMethod(final Method method, Object... args) {
        try {
            return method.invoke(null, args);
        } catch (IllegalArgumentException e) {
            throw new RuntimeException("Exception while executing method", e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("Exception while executing method", e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException("Exception while executing method", e);
        }
    }
}
新建ELMethod.java
/*
 * Copyright (c) 2015.
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.terrynow.test.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * Extend this class to implement a server side method that takes arguments that
 * you would like to call via expression language.
 * 
 * @author Vineet Manohar
 */
public abstract class ELMethod extends HashMap<Object, Object> {
    private static final long serialVersionUID = 1L;

    private final int numArgs;

    /**
     * @param numArgs
     *            number of arguments this method takes
     */
    protected ELMethod(int numArgs) {
        this.numArgs = numArgs;
    }

    @Override
    public Object get(Object key) {
        // if exactly one argument, call the result() method
        if (numArgs == 1) {
            return result(new Object[] {key});
        }

        // if more tha one argument
        return new Arg(this, key);
    }

    public int getNumArgs() {
        return numArgs;
    }

    /**
     * 1) Implement this method in the child class. This method becomes
     * accesible via expression language.
     * 
     * 2) Call this method using map syntax, by treating the instance of the
     * child class as a map of map of maps...
     * 
     * For example, you could extends this class and create a class called
     * FormatDate. In that class, the result method would expect 2 arguments,
     * format string and date object.
     * 
     * ${FormatDate["MMM dd"][user.creationDate]}, where dateFormat is an
     * instance of the child class.
     * 
     * @param args
     * @return
     */
    public abstract Object result(Object[] args);
    
    public static class Arg extends HashMap<Object, Object> {
        private static final long serialVersionUID = 1L;
        private List<Object> args = new ArrayList<Object>();
        private ELMethod parent;

        public Arg(ELMethod eLMethod, Object key) {
            this.parent = eLMethod;
            this.args.add(key);
        }

        @Override
        public Object get(Object key) {
            this.args.add(key);

            // if all the arguments have been received, invoke the result method
            if (args.size() == parent.getNumArgs()) {
                Object retVal = parent.result(args.toArray());

                return retVal;
            }

            return this;
        }
    }
}

 

Terry

文章评论

*

code