`
z276356445t
  • 浏览: 152128 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类
最新评论

利用java反射模拟struts2工作(二)

阅读更多
上一篇文章模拟struts2的工作机制,上一篇主要是对配置文件的编写以及解析,接着是使用servlet来控制对action的访问以及result返回的处理。由servlet来充当Control层,首先来看一下web.xml的配置。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
	<servlet>
		<servlet-name>baseServlet</servlet-name>
		<servlet-class>blog.base.servlet.BaseServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>baseServlet</servlet-name>
		<url-pattern>*.action</url-pattern>
	</servlet-mapping>
	<login-config>
		<auth-method>BASIC</auth-method>
	</login-config>
</web-app>


再来看一下对url请求处理。
/**
 * 
 */
package blog.base.servlet;

/**
 * @author 张廷 2011-4-19下午04:54:41
 * 
 */
public class UrlParameter {
	private String reqURI;
	private String action;
	private String method;

	public UrlParameter(String _reqURI) {
		reqURI = _reqURI;
		urlHandler();
	}

	public void urlHandler() {
		// 取得请求的action
		String reqAction = reqURI.substring(reqURI.lastIndexOf('/') + 1, reqURI.length());
		// 如果有指定访问的方法这样处理
		if (reqAction.indexOf('!') >= 0) {
			action = reqAction.substring(0, reqAction.indexOf('!'));
			method = reqAction.substring(reqAction.indexOf('!') + 1, reqAction.indexOf(".action"));
		} else {
			action = reqAction.substring(0, reqAction.indexOf(".action"));
			method = "";
		}
	}

	public String getAction() {
		return action;
	}

	public String getMethod() {
		return method;
	}
}

UrlParameter.java 主要是将url请求中需要访问的action、method做了一个简单处理,再通过处理后的action、method来定位相应的Model层。
接下来是BaseConfig.java完成了什么工作。
/**
 * 
 */
package blog.base.servlet;

import java.util.Map;

import org.apache.log4j.Logger;

import blog.base.util.WebWorkXmlParser;
import blog.base.webwork.config.WebworkXmlConfig;

/**
 * @author 张廷 2011-4-18下午09:16:05
 * 
 */
public class BaseConfig {

	private Logger logger = Logger.getLogger(this.getClass());


	/**
	 * 装载webwork.xml配置文件
	 * 
	 * @param path
	 * @return
	 */
	public Map<String, WebworkXmlConfig> loadWebworkXmlConfig(String configLocation) {
		Map<String, WebworkXmlConfig> map = null;
		try {
			map = WebWorkXmlParser.readActions(configLocation);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			e.printStackTrace();
		}
		return map;
	}

	/**
	 * 获取访问的方法
	 * 
	 * @param urlParameter
	 * @param webworkXmlConfig
	 * @return
	 */
	public String getMethod(UrlParameter urlParameter, WebworkXmlConfig webworkXmlConfig) {
		if ("".equals(urlParameter.getMethod()))
			return webworkXmlConfig.getActionConfig().getMethod();
		else
			return urlParameter.getMethod();
	}
}

此类主要是处理webwork.xml文件的装载,以及取得被访问的真实方法名。接下来看一下servlet如何来控制action的访问以及View层的访问。
/**
 * 
 */
package blog.base.servlet;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.util.Map;

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

import org.apache.log4j.Logger;

import blog.base.state.result.ResultManager;
import blog.base.webwork.config.WebworkXmlConfig;

/**
 * @author 张廷 2011-5-26下午02:45:10
 * 
 */
public class BaseServlet extends HttpServlet {

	private static final long serialVersionUID = -7616647500213995842L;

	private Logger logger = Logger.getLogger(this.getClass());

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		execute(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		execute(req, resp);
	}

	private synchronized void execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 设置HTTP响应与请求编码方式
		setEncoding(req, resp);
		BaseConfig baseConfig = new BaseConfig();
		// 装载webwork.xml文件
		Map<String, WebworkXmlConfig> config = baseConfig.loadWebworkXmlConfig("webwork.xml");
		// 获取用户访问的URI
		UrlParameter urlParameter = new UrlParameter(req.getRequestURI());
		// 取出需要访问的action相关配置信息
		WebworkXmlConfig webworkXmlConfig = config.get(urlParameter.getAction());
		logger.info(" visited action is " + urlParameter.getAction());
		Object handler = webworkXmlConfig.getActionConfig().getActionClass();
		Method method = null;
		try {
			method = handler.getClass().getMethod(baseConfig.getMethod(urlParameter, webworkXmlConfig), new Class[] { HttpServletRequest.class, HttpServletResponse.class });
			String result = (String) method.invoke(handler, new Object[] { req, resp });
			ResultManager rm = new ResultManager();
			rm.doWork(req, resp, webworkXmlConfig, result);
		} catch (Exception e) {
			logger.error("not fount method " + baseConfig.getMethod(urlParameter, webworkXmlConfig), e);
			e.printStackTrace();
		}
	}

	/**
	 * 设置HTTP响应与请求编码方式
	 * 
	 * @param req
	 * @param resp
	 */
	private void setEncoding(HttpServletRequest req, HttpServletResponse resp) {
		try {
			req.setCharacterEncoding("utf-8");
			resp.setCharacterEncoding("utf-8");
		} catch (UnsupportedEncodingException e) {
			logger.warn(e.getMessage(), e);
			e.printStackTrace();
		}
	}

}

不管客户端是以get或post类型请求都将交给execute来处理,然而execute加了synchronized 关键字,主要是为了线程安全,为什么要在execute方法中每次都装载一次webwork.xml文件呢,这样设计的目的主要是为了有时需要改变webwork.xml中的逻辑时不需要再去重启服务器这样的麻烦事儿。
看一下方法执行后的结果交给了ResultManager类来处理,在返回值的处理使用了设计模式中的状态模式来处理,由于富应用的兴起,不能只是简单的视图跳转,所以可以通过状态模式来扩展自己想以各种各样的类型来返回数据给客户端,在这我只写了两个类型处理,分别是Jsp与Json状态类型。先来看一下两个状态的顶层接口。
package blog.base.state.result;

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

import org.apache.log4j.Logger;

import blog.base.webwork.config.ResultConfig;

/**
 * 
 * @author 张廷 2011-5-27下午07:55:13
 * 
 */
public interface ResultState {

	public Logger logger = Logger.getLogger(ResultState.class);

	/**
	 * 结果类型处理
	 * 
	 * @param req
	 * @param resp
	 * @param actionClass
	 * @param rc
	 */
	public void operate(HttpServletRequest req, HttpServletResponse resp, Object actionClass, ResultConfig rc);
}

下面是它的两个实现类。
/**
 * 
 */
package blog.base.state.result;

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

import blog.base.webwork.config.ResultConfig;

/**
 * @author 张廷 2011-5-27下午07:51:15
 * 
 */
public class JspResultState implements ResultState {
	/**
	 * 返回结果集为Jsp类型的处理方式
	 */
	public void operate(HttpServletRequest req, HttpServletResponse resp, Object actionClass, ResultConfig rc) {
		try {
			req.getRequestDispatcher(rc.getToUrl()).forward(req, resp);
		} catch (Exception e) {
			logger.fatal("Can not access this page!", e);
			e.printStackTrace();
		}
	}

}

JsonResultState.java
/**
 * 
 */
package blog.base.state.result;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;

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

import net.sf.json.JSONObject;
import blog.base.webwork.config.ParamConfig;
import blog.base.webwork.config.ResultConfig;

/**
 * @author 张廷 2011-5-27下午07:52:50
 * 
 */
public class JsonResultState implements ResultState {

	/**
	 * 返回结果集为Json类型的处理方式
	 */
	public void operate(HttpServletRequest req, HttpServletResponse resp, Object actionClass, ResultConfig rc) {
		resp.setContentType("application/json");
		PrintWriter writer = null;
		try {
			writer = resp.getWriter();
		} catch (IOException e) {
			e.printStackTrace();
		}
		for (ParamConfig pc : rc.getParamConfigs()) {
			if ("root".equals(pc.getParamName())) {
				JSONObject jsonObj = JSONObject.fromObject(getVaribleValue(actionClass, pc.getParamVarible()));
				writer.print(jsonObj);
			}
		}
		if (null != writer) {
			writer.flush();
			writer.close();
		}
	}

	/**
	 * 取得方法的返回值
	 * 
	 * @param actionClass
	 * @param varible
	 * @return
	 */
	private Object getVaribleValue(Object actionClass, String varible) {
		Class<? extends Object> clazz = actionClass.getClass();
		Object backResult = null;
		try {
			Method method = clazz.getMethod(getGetterMethod(varible), new Class[] {});
			backResult = method.invoke(actionClass, new Object[] {});
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("not found " + getGetterMethod(varible) + "  method", e);
		}
		return backResult;
	}

	/**
	 * 获取实例中的实例变量相应的getter方法名
	 * 
	 * @param varible
	 * @return
	 */
	private String getGetterMethod(String varible) {
		String firstWord = varible.substring(0, 1);
		firstWord = firstWord.toUpperCase();
		String methodName = "get" + firstWord + varible.substring(1, varible.length());
		return methodName;
	}

}

然后再来看一下ResultManager类如何来控制result类型的控制访问的。
/**
 * 
 */
package blog.base.state.result;

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

import blog.base.webwork.config.ResultConfig;
import blog.base.webwork.config.WebworkXmlConfig;

/**
 * @author 张廷 2011-5-27下午07:11:58
 * 
 */
public class ResultManager {

	private ResultState state;

	public void doWork(HttpServletRequest req, HttpServletResponse resp, WebworkXmlConfig wxc, String result) {
		String resultType = null;
		ResultConfig resultConfig = null;
		Object actionClass = wxc.getActionConfig().getActionClass();
		// 遍历当前action下的所有result
		for (ResultConfig rc : wxc.getResultConfigs()) {
			if (rc.getResultName().equals(result)) {
				resultType = rc.getResultType();
				resultConfig = rc;
				break;
			}
		}
		// 取得返回类型,采取相应的状态类来处理逻辑
		if ("".equals(resultType) || "jsp".equals(resultType))
			state = new JspResultState();
		else if ("json".equals(resultType)){
			state = new JsonResultState();
		}
		state.operate(req, resp, actionClass, resultConfig);
	}

}

当然想使用更多的返回结果处理,可以直接在这个类中进行扩展。
来测试一下,针对以Json类型的结果返回给客户端写一个AjaxAction类。
/**
 * 
 */
package test.ajax;

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

/**
 * 
 * @author 张廷 2011-5-29下午07:51:24
 * 
 */
public class AjaxAction {

	private User user;

	public String execute(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("success!");
		return "";
	}

	public String ajaxTest(HttpServletRequest req, HttpServletResponse resp) {
		user.setAge(18);
		user.setBirth("1988-12-12");
		user.setSex("男");
		user.setUsername("admin");
		return "ajaxResponse";
	}

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

}


测试结果表明json结果已经返回到客户端,在客户端自己需要下载json2.js来解析服务器端返回的json数据。
看……一个简单的MVC小框架就已经出来了,但是一个真正的MVC框架考虑的远不止这些,还有更多的工作需要去分析设计,这只是为了理解一下MVC模式。
3
0
分享到:
评论
2 楼 z276356445t 2011-06-12  
easyhaohao 写道
动态方法调用那不好用吗?请求进不去BaseServlet

你是指的用动态代理吗?怎么进不baseServlet?
1 楼 easyhaohao 2011-06-11  
动态方法调用那不好用吗?请求进不去BaseServlet

相关推荐

    利用java反射模拟struts2工作.doc

    下面我们将探讨如何利用Java反射模拟Struts2的工作原理。 首先,Struts2在启动时会读取配置文件,通常是`struts.xml`,该文件定义了各个Action及其对应的处理方法和结果页面。在模拟这个过程时,我们需要创建一个...

    java反射之模拟struts中央控制器

    在本主题中,我们将深入探讨如何利用Java反射来模拟Struts框架中的中央控制器。 Struts框架是基于Model-View-Controller(MVC)设计模式的,它的中央控制器是`ActionServlet`,它负责接收HTTP请求,解析请求参数,...

    Servlet简单模拟Struts2

    在本主题"Servlet简单模拟Struts2"中,我们将探讨如何利用Servlet来实现类似Struts2框架的一些关键功能,包括请求拦截、XML配置解析、动态代理以及日志拦截。 首先,让我们了解一下Struts2框架的核心特性。Struts2...

    自己模拟实现struts的dispatcherAction

    这个过程不仅加深了对Struts工作原理的理解,也锻炼了Java反射和XML解析的能力。不过,实际开发中,使用成熟的Struts框架能提供更多的便利和优化,如AOP(面向切面编程)支持、更丰富的插件等。

    模拟struts2

    总的来说,模拟Struts2环境是学习和理解MVC框架以及Java Web开发的一个良好途径。通过对配置文件的调整和实际代码的编写,开发者可以深入掌握Struts2的工作原理和最佳实践。同时,熟悉反射机制对于理解框架的内部...

    java练习之模拟SPRING IOC,我的SUMMER

    模拟Struts** Struts是一个基于MVC(Model-View-Controller)设计模式的Java Web框架。在这个练习的最后部分,我们将尝试理解Struts的工作原理,并用简单的Java类模拟其关键组件,如Action和ActionForm。 - **...

    2009年Java认证考试重点指导

    [学习资料] 09年Java认证考试:JAVA反射机制的简单应用 [学习资料] 09年Java认证考试:JFreeChart做题杂谈 [学习资料] 09年Java认证考试:struts2.0的标签库(简介) [考试试题] 09年Java认证考试:5道JAVA题 [考试...

    java反射机制

    Java反射机制是Java语言提供的一种强大的能力,它允许在运行时检查类、接口、字段和方法的信息,并且能够在运行时动态地创建对象和调用方法。这种灵活性使得Java成为一种半静态半动态的语言,能够在一定程度上模拟...

    java中三大框架和项目模拟面试题目[参考].pdf

    **Struts2框架的工作流程**: 1. 客户端发起HTTP请求到Servlet容器。 2. 请求经过一系列过滤器,包括ActionContextCleanUp,为与其他框架集成提供便利。 3. FilterDispatcher作为核心控制器被调用,它会询问...

    自己实现struts

    在`myStruts1`项目中,你可能已经实现了这些核心组件,并通过编写自定义的Action、FormBean和XML配置文件来模拟Struts的功能。这将帮助你深入理解Struts的工作原理,为今后使用或优化Struts框架打下坚实的基础。此外...

    Java程序员面试宝典.pdf

    #### 二、深入性——全方位考察Java技能 本书强调了一个核心观点:Java不仅仅是一门编程语言,更是一项包含多个方面的技术体系,主要包括: - **Java编程语言**:这是Java技术的基础,涉及语法、数据类型、控制...

    java技术体系图

    #### 二、Java高级特性 Java的高级特性主要包括反射、泛型、注解、自动装箱拆箱、枚举类、可变参数、可变返回类型、增强循环和静态导入等。 - **反射**:是一种强大的工具,允许运行时动态获取类的信息并操作其...

    java_编程常用英语单词

    在Java中,应用程序可以是桌面应用、Web应用、移动应用等,它们利用Java的跨平台特性,在不同操作系统上运行。 ### Exception 异常(Exception)是在程序执行过程中发生的错误或意外情况,它们中断了正常流程。...

    java面试学习资料.zip

    这包括但不限于:面向对象编程的基本概念(类、对象、继承、多态、封装),数据类型(基本类型和引用类型),控制流(if、for、while等),异常处理,集合框架(List、Set、Map),IO流,多线程,反射,以及Java 8及...

    Struts中等同于DispatchAction类方法

    标题提到的"Struts中等同于DispatchAction类方法"是指在Struts框架中,如何模拟`DispatchAction`的行为,即如何通过URL参数调用Action类的不同方法。在传统的`DispatchAction`中,我们通常会在子类中定义多个方法,...

    Java高级工程师必学内容

    深入理解JVM(Java虚拟机)的工作原理,包括类加载器(Classloaders)、类反射(Class Reflect)、垃圾回收(Garbage Collection)等,能帮助开发者更高效地编写和调试代码。反编译类文件并理解基本的汇编指令,对于...

    小码哥Java学科的课程大纲.docx

    13. **模拟Struts1/2和Spring MVC**:模拟Struts框架或Spring MVC框架进行开发实践。 #### 六、JavaEE核心技能 1. **Struts2**:介绍Struts2框架的架构及使用方法。 2. **Spring MVC**:讲解Spring MVC框架的基本...

    传智播客Java培训ppt大全

    【Java培训核心知识点详解】 Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems(后被Oracle收购)开发,以其“一次编写,到处运行”的特性受到全球程序员的喜爱。本Java培训资料集合了多位知名讲师的...

    java学习路线

    - **反射与注解**:反射是Java动态特性的体现,注解则是元数据的一种形式,二者都是Java高级编程的重要组成部分。 #### 二、数据库&JDBC编程 **1. SQL基础(重点)** - **SQL基础**:包括SQL语句的基本结构、数据...

    Java学习+面试指南.zip

    9. **JVM原理**:理解Java虚拟机的工作原理,包括内存区域(堆、栈、方法区等)、垃圾回收机制、类加载机制等,对于优化代码性能和解决内存问题至关重要。 10. **框架知识**:如Spring框架的IoC和AOP特性,MyBatis...

Global site tag (gtag.js) - Google Analytics