本文主要是一个模拟的Struts2的简单实现
真正的MVC架构
实现主要思路
定义一个过滤器,接收传递过去的Action,根据处理的结果重定向或者转发。
首先定义index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><title></title><meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0"> <!--<link rel="stylesheet" type="text/css" href="styles.css">--></head><body><form action="${pageContext.request.contextPath}/addCustomer.action" method="post">姓名:<input type="text" name="name"/><br/>年龄:<input type="text" name="age"/><br/><input type="submit" value="保存"/></form></body>
</html>
在web.xml中配置过滤器
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"><display-name>MyStruct2</display-name><filter><filter-name>CenterFilter</filter-name><filter-class>cn.itcast.framework.core.CenterFilter</filter-class>
<!-- <init-param>-->
<!-- <param-name>aciontPostFix</param-name>-->
<!-- <param-value>action,do</param-value>-->
<!-- </init-param>--></filter><filter-mapping><filter-name>CenterFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><welcome-file-list><welcome-file>index.html</welcome-file><welcome-file>index.htm</welcome-file><welcome-file>index.jsp</welcome-file><welcome-file>default.html</welcome-file><welcome-file>default.htm</welcome-file><welcome-file>default.jsp</welcome-file></welcome-file-list>
</web-app>
核心配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!-- 核心配置文件 -->
<framework><!-- action:name:必须有,且唯一。如同之前请求的什么operationclass:必须有,要执行哪个JavaBean的类名method:可以没有。没有的话就是默认值execute。JavaBean中对应的操作方法。该方法的特点是:public String addCustomer(){}--><action name="addCustomer" class="cn.itcast.domain.Customer" method="addCustomer"><!-- result:代表着一种结果。type:可以没有,默认是dispatcher。转向目标的类型。dispatcher代表着请求转发name:必须有。对应的是JavaBean中addCustomer的返回值主体内容:必须有。目标资源的URI--><result type="redirect" name="success">/success.jsp</result><result type="dispatcher" name="error">/error.jsp</result></action><action name="updateCustomer" class="cn.itcast.domain.Customer" method="updateCustomer"><result type="dispatcher" name="success">/success.jsp</result></action>
</framework>
核心过滤器实现
- 初始化配置文件,读取XML配置文件:把配置文件中的信息封装到对象中.再放到actions中
- 取配置参数,如果你请求的地址以action\do\空结尾的话,才真正过滤。
- 解析用户请求的URI,截取后缀名,看看是否需要我们的框架进行处理
- 如果需要框架处理,解析uri中的动作名称,获得相应方法处理
- 根据结果中的type决定是转发还是重定向,重定向的目标就是结果中的targetUri
package cn.itcast.framework.core;import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
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 org.apache.commons.beanutils.BeanUtils;
import org.dom4j.Document;
import org.dom4j.Element;import cn.itcast.framework.util.Dom4JUtil;public class CenterFilter implements Filter {//存取配置文件信息。key:对应action中的name value:Action对象private Map<String, Action> actions = new HashMap<String, Action>();private FilterConfig filterConfig;public void init(FilterConfig filterConfig) throws ServletException {initCfg();//初始化配置文件this.filterConfig = filterConfig;}//初始化配置文件private void initCfg() {//读取XML配置文件:把配置文件中的信息封装到对象中.再放到actions中Document document = Dom4JUtil.getDocument();Element root = document.getRootElement();//得到所有的action元素,创建Action对象,封装信息List<Element> actionElements = root.elements("action");if(actionElements!=null&&actionElements.size()>0){for(Element actionElement:actionElements){//封装action信息开始Action action = new Action();action.setName(actionElement.attributeValue("name"));action.setClassName(actionElement.attributeValue("class"));String methodXmlAttrValue = actionElement.attributeValue("method");if(methodXmlAttrValue!=null)action.setMethod(methodXmlAttrValue);//封装action信息结束//得到每个action元素中的result元素,创建Result对象,封装信息//封装属于当前action的结果List<Element> resultElements = actionElement.elements("result");if(resultElements!=null&&resultElements.size()>0){for(Element resultElement:resultElements){Result result = new Result();result.setName(resultElement.attributeValue("name"));result.setTargetUri(resultElement.getText().trim());String typeXmlValue = resultElement.attributeValue("type");if(typeXmlValue!=null){result.setType(ResultType.valueOf(typeXmlValue));}action.getResults().add(result);}}//封装属于当前action的结果//把Action对象都放到Map中actions.put(action.getName(), action);}}}public void doFilter(ServletRequest req, ServletResponse resp,FilterChain chain) throws IOException, ServletException {try {HttpServletRequest request = (HttpServletRequest)req;HttpServletResponse response = (HttpServletResponse)resp;//真正的控制器部分//取一个配置参数String aciontPostFixs [] = {"action","","do"};//你请求的地址以action\do\空结尾的话,才真正过滤。默认值String aciontPostFix = filterConfig.getInitParameter("aciontPostFix");if(aciontPostFix!=null){aciontPostFixs = aciontPostFix.split("\\,");}//解析用户请求的URIString uri = request.getRequestURI();// /strutsDay01MyFramework/addCustomer.action//截取后缀名,看看是否需要我们的框架进行处理//切后缀名String extendFileName = uri.substring(uri.lastIndexOf(".")+1);// /strutsDay01MyFramework/addCustomer.action action// /strutsDay01MyFramework/addCustomer.do do// /strutsDay01MyFramework/addCustomer ""boolean needProcess = false;for(String s:aciontPostFixs){if(extendFileName.equals(s)){needProcess = true;break;}}if(needProcess){//需要框架处理//解析uri中的动作名称String requestActionName = uri.substring(uri.lastIndexOf("/")+1, uri.lastIndexOf("."));System.out.println("您的请求动作名是:"+requestActionName);//查找actions中对应的Action对象if(actions.containsKey(requestActionName)){Action action = actions.get(requestActionName);//得到类名称的字节码Class clazz = Class.forName(action.getClassName());//封装数据到JavaBean中,利用BeanUtils框架Object bean = clazz.newInstance();BeanUtils.populate(bean, request.getParameterMap());//实例化,调用其中指定的方法名称Method m = clazz.getMethod(action.getMethod(), null);//根据方法的返回值,遍历结果String resultValue = (String)m.invoke(bean, null);List<Result> results = action.getResults();if(results!=null&&results.size()>0){for(Result result:results){if(resultValue.equals(result.getName())){//根据结果中的type决定是转发还是重定向//重定向的目标就是结果中的targetUriif("dispatcher".equals(result.getType().toString())){//转发request.getRequestDispatcher(result.getTargetUri()).forward(request, response);}if("redirect".equals(result.getType().toString())){//重定向response.sendRedirect(request.getContextPath()+result.getTargetUri());}}}}}else{throw new RuntimeException("The action "+requestActionName+" is not founded in your config files!");}}else{chain.doFilter(request, response);}} catch (Exception e) {throw new RuntimeException(e);}}public void destroy() {}}
javabean如下
package cn.itcast.domain;import java.io.Serializable;public class Customer implements Serializable {private String name;private int age;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String addCustomer(){if("wzhting".equals(name)){return "success";}else{return "error";}}
}