继
上一篇文章模拟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模式。
分享到:
相关推荐
利用java反射模拟struts2工作
利用java反射校验struts中的formbean 在struts框架中,如果每次都去校验form中的每个字段,显然费时费力,本例通过java反射得到form中的字段和值,并较验,用于在与数据库交互之前的校验,从而防止数据库恶意注入. 随包...
NULL 博文链接:https://chaoyi.iteye.com/blog/2156733
自己模拟实现struts的dispatcherAction 模拟struts DispatcherAction 反射 xml
使用servlet模拟struts1的工作原理,解析xml,处理请求,自动封装数据
关于struts中央控制器的简单模拟
java动态验证码Struts2集成实现
初学者struts2 myeclipse开发实例,登陆界面
模拟struts2框架的功能,用java模拟实现struts2的基础功能。
java struts2
本Java视频教程对 Struts2 庞杂的技术点进行抽丝剥茧,提炼出企业开发必备的核心技术和重要技能。每个技术点都配备案例和代码,对于拦截器、Struts2 运行流程分析、值栈等技术点的讲授更是深入解析源代码,授之以渔...
struts2标签java分页。struts2标签java分页。struts2标签java分页。struts2标签java分页。struts2标签java分页。struts2标签java分页。struts2标签java分页。struts2标签java分页。struts2标签java分页。struts2标签...
java培训-struts2 MVC设计模式.ppt Struts2.ppt 过滤器.ppt
Struts2是struts1与webwork结合的产物,与struts1有很大差别,虽然目前struts2在开发领域中的份额逐年下降,但是作为一款经典的MVC框架,其核心思想还是很有必要去研究学习的,通过本套Java视频教程的学习,在将来...
利用IBM的资料整理的java语言+struts2框架实现页面折线图,柱状图,饼状图图表的显示
用案例学Java Web整合开发:Java+Eclipse+Struts 2+Ajax
java struts2开发总结,word文档
java javaee struts2 spring hibernate免费学习视频教程
此资源是通过java反射,实现了struts的拦截器和转发请求的功能,实现简单,易懂。
基于java开发的Struts图书馆管理系统基于java开发的Struts图书馆管理系统基于java开发的Struts图书馆管理系统基于java开发的Struts图书馆管理系统基于java开发的Struts图书馆管理系统基于java开发的Struts图书馆管理...