自定义struts框架(不含拦截器的实现)

首先弄清楚 发送请求 都会被 filter 拦截,由 filter 处理,具体实现步骤:

  • 1、自定义一个 MyAction的接口,之后的Action 实现这个类和其中的execute方法
  • 2、仿造 struts2 在 web.xml中配置一个filter
        <filter>
            <filter-name>struts2</filter-name>
            <filter-class>com.rindy.framework.mystruts.filter.MyStrutsPrepareAndExecuteFilter</filter-class>
        </filter>

        <filter-mapping>
            <filter-name>struts2</filter-name>
            <url-pattern>*</url-pattern>
        </filter-mapping>
  • 3、自定义一个Filter ,实现里面的 int 和 doFilter 方法,这个类实现框架主要的功能
package com.rindy.framework.mystruts.filter;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.rindy.framework.mystruts.MyAction;
import com.rindy.framework.mystruts.wrapper.ActionWrapper;
import com.rindy.framework.mystruts.wrapper.PackageWrapper;
import com.rindy.framework.mystruts.wrapper.ResultWrapper;
import com.rindy.framework.utils.Dom4j;

public class MyStrutsPrepareAndExecuteFilter implements Filter {
    private Map<String, PackageWrapper> packageMap;
    private HttpServletRequest request;

    public void destroy() {

    }

    public void doFilter(ServletRequest arg0, ServletResponse arg1,
            FilterChain chain) throws IOException, ServletException {

        // 1、解析请求 得到两个值: namespace 的值 、 action的名字
        request = (HttpServletRequest) arg0;
        HttpServletResponse response = (HttpServletResponse) arg1;

        // 使用 request.getServletPath() ,得到的路径不需要从中截取 namespace,而是
        // /xxx/yyy.action 的字符串
        String servletPath = request.getServletPath();


        //表示只处理  后缀名为  .action 的请求,拦截到的 其他 如 jsp等就不会处理
        if (servletPath.lastIndexOf(".action") == -1) {
            chain.doFilter(request, response);
        } else {

            try {

                int lastSlashIndex = servletPath.lastIndexOf("/");//取到最后一个 /  的位置, 将 namespace 和 xxx.action 取出

                String actionName = servletPath.substring(lastSlashIndex + 1);
                String namespaceName = servletPath.substring(0, lastSlashIndex);

                // 2、到map中找到这个 Action
                PackageWrapper packageWrapper =null;
                for( Map.Entry<String, PackageWrapper> entry: packageMap.entrySet()){
                    PackageWrapper pw=entry.getValue();
                    pw.getNamespace().equals(namespaceName);
                    packageWrapper=pw;
                    break;
                }

                //根据action 名字从packageWrapper 里面找出 ActionWrapper
                ActionWrapper aw = packageWrapper.getActionMap().get(actionName);

                // 3、反射Action
                String actionClassName = aw.getClassName();
                Class c = Class.forName(actionClassName);

                // 4、激活 相应的 方法
                // 5、得到返回的result String
                String result = invokeActionMethod(c, actionName, aw);

                // 6、从 map中找到这个 string 对应的result值
                ResultWrapper rw = aw.getResultWrapper().get(result);

                // 7、转发到这个 result对应的内容中
                String dispatcherType=rw.getType();
                String page=rw.getValue();

                //取出 result 属性的 type 是否有值
                if(dispatcherType!=null && !"".equals(dispatcherType)){
                    //有,而且等于 direct ,说明是需要重定向到 指定的页面
                    if("direct".equals(dispatcherType)){
                        String path = request.getContextPath();
                        String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path;
                        response.sendRedirect(basePath+page);
                    }
                }else{
                    request.getRequestDispatcher(page).forward(request, response);
                }

            } catch (Exception e) {
                e.printStackTrace();
                request.getSession().setAttribute("myStrutsException", e);
            }

        }
    }

    public void init(FilterConfig config) throws ServletException {
        String realPath = config.getServletContext().getRealPath("/");
        // 读取配置文件 struts.xml
        String filePath=getFilePath(realPath,"struts.xml");

        // 解析xml
        packageMap = parseStrutsXml(filePath);
    }

    private Map<String, PackageWrapper> parseStrutsXml( String filePath) {
        Dom4j dom4j = new Dom4j();
        Map<String, PackageWrapper> map = dom4j.getStrutsXML(filePath);
        return map;
    }

    private String getFilePath(String realPath,String configFileName) {
        //  struts.xml 配置文件的真正路径
        return realPath+"WEB-INF\\classes\\"+configFileName;
    }

    /**
     * @return 这个 action 执行完 的 字符串
     * @throws SecurityException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    private String invokeActionMethod(Class c, String requestActionName,
            ActionWrapper aw) throws NoSuchMethodException, SecurityException,
            IllegalAccessException, IllegalArgumentException,
            InvocationTargetException, InstantiationException {
        String requestResult = "";
        Object obj = c.newInstance();

        //注入参数的功能
        injectParamterToAction( request,obj,c);


        if (aw.getMethodName() == null || "".equals(aw.getMethodName())) {
            requestResult = ((MyAction) obj).execute();
        } else {
            String actionMethodname = aw.getMethodName();
            Method m = c.getMethod(actionMethodname, null);
            requestResult = (String) m.invoke(obj, null);
        }

        return requestResult;
    }

    private void injectParamterToAction(HttpServletRequest request2,
            Object obj, Class c) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        //基本类型的参数注入
        //1、从request 中取出 所有的键值对,转成  Map < setName, xxx>
        Map<String,String[]> map=pareseRequest(request2);new HashMap<String,String>();


        //2、从  c 中导出要注入的方法,上一步 的map 转化就是 方便这一步的查找
        Method[] ms=c.getMethods();
        for( Method m: ms){
            String methodName=m.getName();
            if( map.containsKey(methodName)){
                String[] values=map.get(methodName);
                if( values.length==1){
                    String s=values[0];
                    String paramterTypeName=m.getParameterTypes()[0].getName();

                    //3、反向激活方法,注入参数
                    if( paramterTypeName.equals("java.lang.Integer") || paramterTypeName.equals("int")){
                        m.invoke(obj, Integer.parseInt(s));
                        continue;
                    }else if(paramterTypeName.equals("java.lang.Double") || paramterTypeName.equals("double")){
                        m.invoke(obj, Double.parseDouble(s));
                        continue;
                    }else if(paramterTypeName.equals("java.lang.Float") || paramterTypeName.equals("float")){
                        m.invoke(obj, Float.parseFloat(s));
                        continue;
                    }else if(paramterTypeName.equals("java.lang.Boolean") || paramterTypeName.equals("boolean")){
                        m.invoke(obj, Boolean.parseBoolean(s));
                        continue;
                    }else if(paramterTypeName.equals("java.lang.Short") || paramterTypeName.equals("short")){
                        m.invoke(obj,Short.parseShort(s));
                        continue;
                    }else{
                        m.invoke(obj, s);
                        continue;
                    }
                }
            }
        }


    }

    private Map<String, String[]> pareseRequest(HttpServletRequest request) {
        Map<String,String[]> map=new HashMap<String,String[]>();
        Enumeration<String> enu=request.getParameterNames();
        while( enu.hasMoreElements()){
            String key=enu.nextElement();
            String methodName="set"+key.substring(0, 1).toUpperCase()+key.substring(1);
            String[] values=request.getParameterValues(key);
            map.put(methodName, values);
        }
        return map;
    }
}

4、自定义struts2 需要解析的struts.xml

<struts>


    <!--  配置包  通过 namespace 来规范访问这个包下的所有 action 的访问路径-->
    <package name="default" namespace="/" >

        <action name="user_add.action" class="com.rindy.action.UserAction" method="add">
            <result name="success" type="direct">
                /a.jsp
            </result>
         </action>
    </package>


</struts>

5、index.jsp中表单的内容

<form action="user_add.action" method="post">
        用户名:<input type="text" name="name"><br/>
        年龄:<input type="text" name="age"><br/>
        <input type="submit" value="提交"/>
    </form>

6、我们这里没有做其他的复杂处理,进入UserAction中的add(),返回success,查找result中的值,根据type设置的类型,转发或者重定向到具体的页面,初版的struts框架就形成了,功能也是比较简单的,。后续会慢慢完善,下面我们来看一下效果。截图只是展现了页面的内容,跳转看不到,大家可以根据本博客动手试试看。
这里写图片描述
这里写图片描述
参数其实已经接到了,只是我们并没有在action 进行处理,后期会加上,这里只是在后台打印看下效果的实现
这里写图片描述

struts自定义框架是在影哥的带领下完成的,一直都在强调理解底层实现的重要性,架构师和程序员的区别,大家还是好好努力吧。加油。校招顺利!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值