基于Struts2框架思想的小项目(二)

我们已经解决了解析XML文件的问题,并把所有数据都封装到了我们所需要的类中,接下来,我们需要根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象)
据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是
(“name”=”test” , “password”=”1234”) , 那就应该调用setName和setPassword方法。
要想能调用set方法,首先得实例化我们所需要的JavaBean,然后调用实例化JavaBean内部的Set方法,把我们想要传进去的数据封装到这个JavaBean内部,我们自己做得javaBean如下:

package com.coderising.litestruts;
public class LoginAction{
    private String name ;
    private String password;
    private String message;

    public String getName() {
        return name;
    }

    public String getPassword() {
        return password;
    }

    public String execute(){
            if("test".equals(name) && "1234".equals(password)){
                this.message = "login successful";
                return "success";
            }
            this.message = "login failed,please check your user/pwd";
            return "fail";
    }

    public void setName(String name){
        this.name = name;
    }
    public void setPassword(String password){
        this.password = password;
    }
    public String getMessage(){
        return this.message;
    }
}

我们可以编写测试用例,测试用我们的方法能否获得set方法

public void testGetSetterMethod() throws Exception {

        String name = "com.coderising.litestruts.LoginAction";
        Class<?> clz = Class.forName(name);
        List<Method> methods = ReflectionUtil.getSetterMethods(clz);

        Assert.assertEquals(2, methods.size());

        List<String> expectedNames = new ArrayList<>();
        expectedNames.add("setName");
        expectedNames.add("setPassword");

        Set<String> acctualNames = new HashSet<>();
        for(Method m : methods){
            acctualNames.add(m.getName());
        }

        Assert.assertTrue(acctualNames.containsAll(expectedNames));
    }

在测试用例的驱动下,我们编写的第一个方法如下,这样我们就实现了获取set的方法:

public static List<Method> getSetterMethods(Class clz) {

        return getMethods(clz,"set");

    }
    private static List<Method> getMethods(Class<?> clz, String startWithName){

        List<Method> methods = new ArrayList<>();

        for(Method m : clz.getDeclaredMethods()){

//判断方法是否以指定的字幕开始
            if(m.getName().startsWith(startWith
Name)){

                methods.add(m);

            }

        }

        return met
ho
ds;
}

紧接着,我们就需要将我们的name和password封装到对应的类,这样的话,我们可以继续编写一个测试用例,测试能否通过我们的方法,将目标值封装起来:

    public void testSetParameters() throws Exception{

        String name = "com.coderising.litestruts.LoginAction";
        Class<?> clz = Class.forName(name);
        Object o = clz.newInstance();

        Map<String,String> params = new HashMap<String,String>();
        params.put("name","test");
        params.put("password","1234");

        ReflectionUtil.setParameters(o,params);


        //实例化域,将需要的域反射到f这个对象中
        Field f = clz.getDeclaredField("name");
        //由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的
        f.setAccessible(true);
        //其值为obj域的当前值
        ssert.assertEquals("test", f.get(o));

        f = clz.getDeclaredField("password");
        f.setAccs ible(true);
        Assert.assertEquals("1234", f.get(o));
    }

这样,我们就可以集中编写setParameter这个方法,通过这个方法,实现将我们的数据封装到实例化的类中。

public static void setParameters(Object o, Map<String, String> params) {
        //将所有的setmethod方法放到一个集合中
        List<Method> methods  =  getSetterMethods(o.getClass());
        //遍历传入的map,获取所有的key值
        for(String name : params.keySet() ){
            //获得method方法名称
            String methodName = "set" + name;
            //遍历所有的方法
            for(Method m: methods){
                //判断遍历的方法名称是否与设置的方法名称一致
                if(m.getName().equalsIgnoreCase(methodName)){
                    try {
                        //如果一致,则调用该方法,并把值传入
                        m.invoke(o, params.get(name));
                    } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

    }

set方法测试好了,接下来需要我们测试get方法,首先需要满足的测试用例是:

public void testGetGetterMethod() throws Exception{
        String name = "com.coderising.litestruts.LoginAction";
        Class<?> clz = Class.forName(name);
        List<Method> methods = ReflectionUtil.getGetterMethods(clz);

        Assert.assertEquals(3, methods.size());

        List<String> expectedNames = new ArrayList<>();
        expectedNames.add("getMessage");        
        expectedNames.add("getName");
        expectedNames.add("getPassword");

        Set<String> acctualNames = new HashSet<>();
        for(Method m : methods){
            acctualNames.add(m.getName());
        }

        Assert.assertTrue(acctualNames.containsAll(expectedNames));
    }

跟获得set方法的名称一样,调用getMethods方法即可:

public static List<Method> getGetterMethods(Class<?> clz) {
        return getMethods(clz,"get");
    }

然后设计测试用例,取得我们想要的值,通过反射找到对象的所有getter方法(例如 getMessage),
通过反射来调用, 把值和属性形成一个HashMap , 例如 {“message”: “登录成功”} ,
放到View对象的parameters:

public void testGetParamters() throws Exception{
        String name = "com.coderising.litestruts.LoginAction";
        Class<?> clz = Class.forName(name);
        LoginAction action = (LoginAction)clz.newInstance();
        action.setName("test");
        action.setPassword("123456");




        Map<String,Object> params = ReflectionUtil.getParamterMap(action);

        Assert.assertEquals(3, params.size());

        Assert.assertEquals(null, params.get("messaage") );
        Assert.assertEquals("test", params.get("name") );
        Assert.assertEquals("123456", params.get("password") );
    }

接下来,我们编写实现这个测试的工具类:

public static Map<String, Object> getParamterMap(Object o) {

        Map<String ,Object> params = new HashMap<>();
        //将javabean所有的get方法形成一个集合
        List<Method> methods = getGetterMethods(o.getClass());
        //遍历所有的方法
        for(Method m : methods){
            //定义方法名
            String methodName = m.getName();
            //去掉get方法前的get,形成name
            String name = methodName.replaceFirst("get", "").toLowerCase();
            try {
                //调用这个方法
                Object value = m.invoke(o);
                //形成键值对,返回我们封装的数据
                params.put(name, value);
            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {

                e.printStackTrace();
            } 
        }

        return params;
    }
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值