模仿struts2做一个简单控制器,easycontroller

综述:1.在启动服务器的时候,执行SoFilter过滤器的init方法时 加载一个easyCotroller.properties 配置文件,然后解析这个配置文件,把所有的对象放到一个容器中,每个key值对应一个对象,这个key就是control层的访问类的classId,value就是这个访问类的实例,然后每次请求都是从容器中取。

         2.我在index.jsp 发送一个请求,然后经过过滤器, 在doFilter方法中从容器中找到我要访问的对象 然后通过反射调用对象的方法 完成页面的跳转

下面是具体流程:

新建一个javaweb项目,然后绑定到tomcat服务器上去,WebContent\WEB-INF配置如下

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>
        2013_0818easycontroller
    </display-name>
  <!--eayscontroller的核心控制器 所有的请求的经过这里 然后在这里进行调度  -->
  <filter>
      <filter-name>Sofilter</filter-name>
      <filter-class>cn.learnself.filter.SoFilter</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>Sofilter</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
  
  <!-- 做一个测试用的servler -->
  <servlet>
      <servlet-name>bs</servlet-name>
      <servlet-class>cn.learnself.servlet.BaseServlet</servlet-class>
  </servlet>
  <servlet-mapping>
     <servlet-name>bs</servlet-name>
     <url-pattern>/bs</url-pattern>
  </servlet-mapping>
  
  <!-- 项目默认首页 -->
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>
View Code

--------------------------------------------------------------------------

然后在src\cn\learnself\filter 包下有1个类和一个properties配置文件

package cn.learnself.filter;

import java.io.IOException;
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 cn.learnself.common.CallUtil;
import cn.learnself.common.CallUtil2;
import cn.learnself.common.CallUtil3;
import cn.learnself.common.FileUtil;

public class SoFilter implements Filter{

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

        System.out.println("dofilter");
        CallUtil callUtil = new CallUtil();
        CallUtil2 callUtil2 = new CallUtil2();
        CallUtil3  callUtil3 = new CallUtil3();
        
        HttpServletRequest request =(HttpServletRequest)arg0;
        HttpServletResponse response=(HttpServletResponse)arg1;
        
//        System.out.println(request.getRequestURI()); //2013_0818learnself/HelloWord/setName.so
//        System.out.println(request.getServletPath());//HelloWord/setName.so
        
        String url_str = request.getServletPath();//HelloWord/setName.so
        
         if(url_str.endsWith(".so")){
             
             url_str.substring(0, url_str.indexOf("!"));
                
             String class_name=url_str.substring(url_str.lastIndexOf("/")+1, url_str.indexOf("!"));//HelloWord
             
             String method_name= url_str.substring(url_str.indexOf("!")+1, url_str.indexOf(".so"));
             
//             System.out.println(class_name);
//             
//             System.out.println(method_name);
             
             try {
//                    Class cls = Class.forName("cn.learnself.test."+class_name);
//                    Object o = cls.newInstance();
//                    Method method = cls.getMethod("setName",String.class);
//                    method.invoke(o, "zhangsan");
//                    new CallUtil().deliver(request,response, "cn.learnself.test."+class_name, method_name); 最一开始做的
                 
                 
//                 callUtil.deliver(request,response, callUtil.getCompleteUrl(class_name), method_name);
//                 callUtil2.deliver(request,response, class_name, method_name);
                 
                 callUtil3.deliver(request,response, class_name, method_name);
                 
             } catch (Exception e) {
                
                e.printStackTrace();
            }
         }else{
             
             arg2.doFilter(arg0, arg1);
         }

    }

    public void init(FilterConfig arg0) throws ServletException {
        FileUtil.parseXml();
        System.out.println("init......");
        
    }
    
    public void destroy() {
        
    }

}
View Code

src\cn\learnself\filter\easycontroller.properties 这个配置文件有两句代码 key是control层每个访问类的ClassId value 就是这个类在项目下的全路径加类名

HelloWord=cn.learnself.test.HelloWord
RegisterUser=cn.learnself.control.RegisterUser

-------------------------------------------------------------------------

src\cn\learnself\common 这个包下有4个类

package cn.learnself.common;

import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.learnself.filter.SoFilter;
/**
 * @description:通过反射 完成对要访问的控制器实现类的调用,不足 每次访问一个类 到用 newInstance 加载进内存
 * @author  令狐冲之12
 * @date   2013-08-25
 * @mail 1055592535@qq.com
 * @version easy-controller-version201301
 */
public class CallUtil {
    
    public void deliver(HttpServletRequest re, HttpServletResponse rs,String class_name_complete,String method_name){
        
            try {
                
                Class cls = Class.forName(class_name_complete);
                
                Object o = cls.newInstance();
                
                Method method = cls.getMethod(method_name,WebContext.class);
                method.invoke(o, new WebContext(re,rs));
                
            } catch (Exception e) {
                
                e.printStackTrace();
            }

    }
    
    public String getCompleteUrl(String className){
        String complete_className="";
        Properties prop = new Properties();
        
        try {

            InputStream ips = SoFilter.class.getResourceAsStream("easycontroller.properties");
            
            prop.load(ips);
            ips.close();
            
            complete_className =    prop.getProperty(className);
            

        } catch (Exception e) {
            
            e.printStackTrace();
        }
        
        return complete_className;
    }
}
View Code
package cn.learnself.common;

import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.learnself.filter.SoFilter;
/**
 * @description: 通过容器获取要访问的 控制器对象  然后通过反射 完成 对方法的调用,
 *               好处:保证了 每次请求都始终使用一个对象 ,不足:页面跳转的时候 还需要在方法中做 转发或重定向,重复率太高        
 * @author 令狐冲之12
 * @date   2013-08-25
 * @mail 1055592535@qq.com
 * @version easy-controller-version201301
 */
public class CallUtil2 {
    
    public void deliver(HttpServletRequest re, HttpServletResponse rs,String class_name,String method_name){
        
            try {
                
//            FileUtil fu = new FileUtil();
//            Class cl = (Class)fu.classCoatainer.get(class_name); // 从容器中取出对象
            
            Map map    = FileUtil.classCoatainer;
             
            Object o = map.get(class_name); // 从容器中取出对象
                
            Method method = o.getClass().getMethod(method_name,WebContext.class);
            
            method.invoke(o, new WebContext(re,rs));
            
//            现在我要做的是 从容器中取出的对象是Object ,而我要把Object 转换成有用的实际对象,然后用这个对象来调用她的方法
            
//            我如何从一个对象 获取这个对象的类型呢
            
//            o.getClass().
            System.out.println("22222222"+o);
            } catch (Exception e) {
                
                e.printStackTrace();
            }

    }
    
    public String getCompleteUrl(String className){
        String complete_className="";
        Properties prop = new Properties();
        
        try {

            InputStream ips = SoFilter.class.getResourceAsStream("easycontroller.properties");
            
            prop.load(ips);
            ips.close();
            
            complete_className =    prop.getProperty(className);
            

        } catch (Exception e) {
            
            e.printStackTrace();
        }
        
        return complete_className;
    }
}
View Code
package cn.learnself.common;

import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Properties;

import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.learnself.filter.SoFilter;
/**
 * @description: 通过容器获取要访问的 控制器对象  然后通过反射 完成 对方法的调用,
 *               控制 转发在此类中完成, 不足:我控制器类方法返回的的必须jsp的全路径 可以改为返回url_id 然后在配置文件中读取全路径
 *               通过配置文件读取 有没有是转发还是重定向的标志   
 * @author 令狐冲之12
 * @date   2013-08-25
 * @mail 1055592535@qq.com
 * @version easy-controller-version201301
 */
public class CallUtil3 {
    
    public void deliver(HttpServletRequest re, HttpServletResponse rs,String class_name,String method_name){
        
            try {
                
            Map map    = FileUtil.classCoatainer;
             
            Object o = map.get(class_name); // 从容器中取出对象
                
            Method method = o.getClass().getMethod(method_name,WebContext.class);
            
            String url_str=(String)method.invoke(o, new WebContext(re,rs));

            System.out.println(url_str);
            
            if(url_str!=null&&!"".equals(url_str)){
                RequestDispatcher rd = 
                      re.getRequestDispatcher(url_str+".jsp");
                  rd.forward(re,rs);
            }

            } catch (Exception e) {
                
                e.printStackTrace();
            }

    }
    
    public String getCompleteUrl(String className){
        String complete_className="";
        Properties prop = new Properties();
        
        try {

            InputStream ips = SoFilter.class.getResourceAsStream("easycontroller.properties");
            
            prop.load(ips);
            ips.close();
            
            complete_className = prop.getProperty(className);
            

        } catch (Exception e) {
            
            e.printStackTrace();
        }
        
        return complete_className;
    }
}
View Code
package cn.learnself.common;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import cn.learnself.filter.SoFilter;

/**
 * @description: 用来解析配置文件的一个类 完后做一个容器 把多有对象都方里边去 在init方法中用到
 * @author 令狐冲之12
 * @date   2013-08-25
 * @mail 1055592535@qq.com
 * @version easy-controller-version201301
 */
public class FileUtil {
    
    public static Map classCoatainer = new HashMap();
    
    public static void parseXml(){
        
        String  classId="";
        String complete_className="";
        Properties prop = new Properties();
        
        try {
            InputStream ips = SoFilter.class.getResourceAsStream("easycontroller.properties");
            
            prop.load(ips);
            ips.close();
            
            // 然后开始解析这个.properties 文件 生成所有对象 放到容器中
            
            Set keySet=    prop.keySet();
            
            for(Object key: keySet){
                
//                System.out.println(key.toString());
                
                classId =key.toString();
                complete_className = prop.getProperty(classId);
                
                Class cls = Class.forName(complete_className);
                
                Object o = cls.newInstance();
                
                classCoatainer.put(classId, o);
                
//                classCoatainer.put(classId, cls);

            }
            
        } catch (Exception e) {
            
            e.printStackTrace();
        }
//        System.out.println(classCoatainer);
    }
    
}
View Code
package cn.learnself.common;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @description: 控制器中的参数对象 封装 request和response
 * @author 令狐冲之12
 * @date   2013-08-25
 * @mail 1055592535@qq.com
 * @version easy-controller-version201301
 */

public class WebContext {

    public HttpServletRequest request;
    
    public HttpServletResponse response;
    
    public WebContext(HttpServletRequest req, HttpServletResponse res){
        
        request=req;
        
        response=res;
    }
    
    
}
View Code

src\cn\learnself\control 包下有一个类

package cn.learnself.control;

import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.learnself.common.WebContext;
/**
 * @description: 控制器 测试用的 注册用户接收参数
 * @author 令狐冲之12
 * @date   2013-08-25
 * @mail 1055592535@qq.com
 */

public class RegisterUser {
    
    public void register(WebContext webc) throws Exception{
        
      HttpServletRequest request= webc.request;
      HttpServletResponse response= webc.response;

      
      String name = request.getParameter("name");

      System.out.println(name);
      
//      response.sendRedirect("HelloWord.jsp");
//      System.out.println(request.getRequestURI());
      
      request.setAttribute("name", name);

      //转发 最常用
      RequestDispatcher rd = 
           request.getRequestDispatcher("HelloWord.jsp");
      rd.forward(request,response);

    }
}
// 写在过滤器里边容易执行两次 ,而我的被url访问的类 记没有继承Servlet 也不是action ,如何做转发和重定向呢

// 写一个超类 用来做webc 的继承 2 动态代理, 不用这个过滤器来实现,使用动态代理,在我访问的时候 其实是访问的我的代理类,

// 如果用过滤器来实现 可能执行两次了 当

// 仔细学学spring 把spring 和项目结合起来,让spring 做类实例化

// 过滤器主要是判断用户有没有登录 有没有对应的权限 来访问路径
View Code

src\cn\learnself\servlet

package cn.learnself.servlet;

import java.io.IOException;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @description: 一个普通的servlet 重定向访问了两次 过滤器的doFilter
 *
 */
public class BaseServlet extends HttpServlet{
    
    public void doGet(HttpServletRequest re, HttpServletResponse rs){
        
        System.out.println("访问到了");
        try {
            rs.sendRedirect("BaseServlet.jsp");
        } catch (IOException e) {
            
            e.printStackTrace();
        }
        
    }

}
View Code

\src\cn\learnself\test

package cn.learnself.test;

import java.util.Map;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.learnself.common.FileUtil;
import cn.learnself.common.WebContext;

/**
 * @description: 控制器 测试页面的跳转 和反射是否成功
 * @author 令狐冲之12
 * @date   2013-08-25
 * @mail 1055592535@qq.com
 */
public class HelloWord {

    public void setName(WebContext webc) throws Exception{
        
      HttpServletRequest request= webc.request;
      HttpServletResponse response= webc.response;
      
//   如果使用重定向 则经过 两次过滤器的doFilter 第一次是我访问到request url Helloword!setName.so,
 
//   第二次是request 的url HelloWord.jsp 这是我在 这里定义的 ,所以在jsp中得不到这个name值,所以不常用重定向
      
//      如果用 转发  只发送一次请求,只访问了一次url Helloword!setName.so,HelloWord.jsp是转发过去的 不经过 过滤器的doFilter

//        使用重定向控制页面跳转
//      response.sendRedirect("HelloWord.jsp"); 
//      System.out.println(request.getRequestURI());
     
        Map map    = FileUtil.classCoatainer;
         
        Object o = map.get("HelloWord"); // 从容器中取出对象
      
        System.out.println("0000000000"+o); // 看内存地址和 Filter是否一样

        request.setAttribute("name", "qinyinglian");
        //转发 最常用
        RequestDispatcher rd = 
                   request.getRequestDispatcher("HelloWord.jsp");
        rd.forward(request,response);

    }

    public String setAge(WebContext webc) throws Exception{
          HttpServletRequest request= webc.request;
          HttpServletResponse response= webc.response;
          request.setAttribute("age", "26");
          return "HelloWord_setAge"; // 注意这个是全路径
    }

}
View Code

index.jsp         WebContent\index.jsp    

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<body>
<!-- 可以看出 当我的请求要访问 bs 的Servlet 的时候  是先经过了过滤器 ,
            我用了重定向 到BaseServlet.jsp 重新发送请求又经过了一次过滤器
    -->
    <a href="bs">测试访问BaseServlet类是否经过过滤器</a>
    <br/><br/>
    <a href="HelloWord!setName.so">访问HelloWord类setName方法</a>
    
    <br/><br/>
    <table><tr><td>测试get请求 访问RegisterUser类register方法:</td></tr> 
    <tr><td>
    <form action="RegisterUser!register.so">
    <input type="text" name="name" />
    <input type="submit" value="提交"/>
    </form></td></tr>
    </table>
    
    <br/><br/>
    <table><tr><td>测试post请求 访问RegisterUser类register方法::</td></tr> 
    <tr><td>
    <form action="RegisterUser!register.so" method="post">
    <input type="text" name="name" />
    <input type="submit" value="提交"/>
    </form>
    </td></tr>
    </table>
    
    <br/>
    <br/>
    <a href="HelloWord!setAge.so">访问控制器的类的一个方法,方法有返回值 是字符串url</a>
</body>
View Code

HelloWord.jsp  路径 WebContent\HelloWord.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<html>    
<body>
helloword.jsp <br>

<%
    String name=(String)request.getAttribute("name");
%>
<input type="text" name="name" value="<%=name%>" />
</body>
</html>
View Code

WebContent\HelloWord_setAge.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<html>    
<body>
helloword_setAge.jsp <br>

<%
    String age=(String)request.getAttribute("age");
%>
<input type="text" name="name" value="<%=age%>" />
</body>
</html>
View Code

BaseServlet.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<body>
baseservlet.jsp
</body>
    
View Code

 备注,需要一个servelt的包,其他包不需要

posted @ 2013-08-25 15:28  令狐冲之12  阅读(328)  评论(0)    收藏  举报