实现Struts2核心功能示例

在平常使用struts开发项目中,我们只需要通过添加struts的支持的jar包以及在配置文件中web.xml中配置核心过滤器以及编写相应的struts,xml配置文件,我们就可以在Action实现类中添加属性以及get和set方法,便可以获得封装在给属性中的信息;那么它是怎么实现的呢,下面通过一个案例实现其核心的功能:

①新建项目relizeStruts(实现加减乘除四则运算)

目录结构如下:


首先我们知道,在struts2中用到了配置文件,配置文件的结构如下:

<struts>

       <action  name =”…..” class=”……”>

              <result  name=”….resultName”>…..resultPath</result>

</action>

</struts>

新建节点的配置文件mystruts.xml

<?xml version="1.0"encoding="UTF-8"?>
<struts>
   <!-- 配置请求名和请求的全类名 -->
   <action name="add" class="com.xiyou.jackielin.action.AddAction">
      <result name="success">result.jsp</result>
   </action>
   <action name="plus" class="com.xiyou.jackielin.action.PlusAction">
      <result name="success">result.jsp</result>
   </action>
   <action name="mul" class="com.xiyou.jackielin.action.MulAction">
      <result name="success">result.jsp</result>
   </action>
   <action name="divide" class="com.xiyou.jackielin.action.DivideAction">
      <result name="success">result.jsp</result>
   </action>
</struts>

注意:配置文件的name(add)应和Action(AddAction )的前半段相同

②新建 result 节点的封装类:ResultMapping

/**
 * 用于封装配置文件中result节点的信息
 * @author Administrator
 *
 */
public class ResultMapping{
		private String resultName;//逻辑名称
		private String resultPath;//物理路径
	
		public String getResultName() {
			return resultName;
		}
		public void setResultName(String resultName) {
			this.resultName = resultName;
		}
		public String getResultPath() {
			return resultPath;
		}
		public void setResultPath(String resultPath) {
			this.resultPath = resultPath;
		}
}

③ 新建action节点的封装类:ActionMapping

/**
 * 用于封装配置文件中Action节点的信息
 * @author Administrator
 *
 */
public class ActionMapping {
	private String actionName;//封装name属性的值
	private String actionClass;//封装class属性的值
	//封装action节点下的所有result节点的信息,以result的name属性值做key,以resultMapping对象信息做value
	private Map<String,ResultMapping> resulsMap = new HashMap<String,ResultMapping>();
	
	public String getActionName() {
		return actionName;
	}
	public void setActionName(String actionName) {
		this.actionName = actionName;
;	}
	public String getActionClass() {
		return actionClass;
	}
	public void setActionClass(String actionClass) {
		this.actionClass = actionClass;
	}
	public Map<String, ResultMapping> getResulsMap() {
		return resulsMap;
	}
	public void setResulsMap(Map<String, ResultMapping> resulsMap
){
		this.resulsMap = resulsMap;
	}
}

④新建ActionMappingManager类并添加解析配置文件的方法,得到action节点信息的集合

/**
 * Action节点的管理类
 * @author Administrator
 */
public class ActionMappingManager {
    //封装配置文件中所有的action节点信息,以action的name属性值做key,以actionMapping对象做value
    Map<String,ActionMapping> actionsMap = new HashMap<String, ActionMapping>();
    
    /**
     * 解析配置文件mystruts.xml 将action节点封装成ActionMapping对象
     */
    public void parseXML() {
        //将配置文件转换为字节流
        InputStream ips = this.getClass().getResourceAsStream("/mystruts.xml");
        //这里要导入dom4j支持包
        SAXReader saxReader = new SAXReader();
        try {
            //读取流中配置文件信息并转为文档树对象类型
            Document document = saxReader.read(ips);
            //获取根节点<struts><action></action></struts>
            Element root = document.getRootElement();
            //迭代根节点下的子节点,获取要封装的action信息
            for(Iterator<Element> actionIter = root.elementIterator();actionIter.hasNext();) {
                Element action = actionIter.next(); //获取action节点的信息
                //获取action的name和class属性值
                String actionName = action.attributeValue("name");
                String actionClass = action.attributeValue("class");
                //创建Action节点的封装类对象用于封装Action节点的信息
                ActionMapping actionMapping = new ActionMapping();
                actionMapping.setActionName(actionName);
                actionMapping.setActionClass(actionClass);
                //获取action节点的子节点信息(result节点)
                for(Iterator<Element> resultIter = action.elementIterator();resultIter.hasNext();) {
                    Element result = resultIter.next();//获取result节点信息
                    String resultName = result.attributeValue("name");
                    String resultPath = result.getText();
                    //创建ResultMapping对象用来封装result节点的信息
                    ResultMapping resultMapping = new ResultMapping();
                    resultMapping.setResultName(resultName);
                    resultMapping.setResultPath(resultPath);
                    //将resultMapping添加到ActionMapping中的result节点信息中
                    actionMapping.getResultsMap().put(resultName, resultMapping);
                }
                //将actionMapping添加到actionsMap中
                actionsMap.put(actionName, actionMapping);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
}
}
⑤创建Action接口

public interface Action {
   public String execute(HttpServletRequest request,HttpServletResponse response);
}
⑥创建ActionManager并添加动态创建Action的方法(这里主要通过反射机制创建类)

public class ActionManager {
    /**
     * 根据全类名(包名+类名)动态创建Action对象
     * eg:com.xiyou.jackielin.action.AddAction
     * @param actionClass
     * @return
     */
    public static Action createActionByClassName(String actionClass) {
        Action action = null;
        try {
            //根据全类名来创建一个Action对象
            action = (Action)Class.forName(actionClass).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }    
        return action;
    }
}
⑦ 编写核心的控制器:ActionServlet并且注意在web.xml中配置servlet过滤所有以.action结尾的请求连接

/**
 * 编写处理业务的业务类
 * @author Administrator
 */
public class ActionServlet extends HttpServlet {
    //创建action节点的业务管理类
    ActionMappingManager actionMappingManager;
    
    //当ActionServlet创建的时候解析配置文件
    @Override
    public void init() throws ServletException {
        actionMappingManager = new ActionMappingManager();
        actionMappingManager.parseXML();//调用解析方法解析配置文件
    }
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        //获取请求的路径(http://127.0.0.1:8080/relizeStruts/add.action)
        String uri = req.getRequestURI();
        //截取地址栏(/relizeStruts/add.action)-->add
        String actionName = uri.substring(uri.lastIndexOf("/")+1, uri.lastIndexOf("."));
        System.out.println(actionName);
        //第一版
        /*Action action = null;
        if(actionName.equals("add")) {
            action = new AddAction();
        }else if(actionName.equals("plus")){
            action = new PlusAction();
        }else if(actionName.equals("mul")){
            action = new MulAction();
        }else if(actionName.equals("divide")) {
            action = new DivideAction();
        }
        String pathName = action.execute(req, resp);
        String path = actionMappingManager.actionsMap.get(actionName).getResultsMap().get(pathName).getResultPath();
        req.getRequestDispatcher(path).forward(req, resp);*/
        
        //第二版
        Map<String,ActionMapping> actionsMap = actionMappingManager.actionsMap;
        //根据action节点的name在配置文件中查找对应的action节点信息
        ActionMapping actionMapping = actionsMap.get(actionName);
        String actionClass = actionMapping.getActionClass();
        //根据全类名创建相应的类
        Action action = ActionManager.createActionByClassName(actionClass);
        String resultName = action.execute(req, resp);//执行execute方法,返回逻辑名称
        //得到actin中封装的result节点信息
        ResultMapping resultMapping = actionMapping.getResultsMap().get(resultName);
        String resultPath = resultMapping.getResultPath();//获得结果节点对应的物理路径
        req.getRequestDispatcher(resultPath).forward(req, resp);//实现跳转到成功页面
    }
}

在核心控制器中,处理业务的方式有两种,在第一种的做法中,如果我们不采用反射机制通过全类名创建相应的类,那么我们必须判断地址请求中要请求的是哪个Action,显然我们知道这种做法是很低效率的,当有很多Action时我们需要花费很大的功夫去判断,那么我们可以通过actionName取到action的节点中的actionClass(全类名),再通过全类名动态创建Action;

配置servlet:

<!-- 这里记得配置servlet去拦截所有的.action结尾的链接 -->
  <servlet>
  	<servlet-name>actionServlet</servlet-name>
  	<servlet-class>com.xiyou.jackielin.framework.ActionServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>actionServlet</servlet-name>
	<url-pattern>*.action</url-pattern>
  </servlet-mapping>

⑧编写业务逻辑接口Action,实现Action接口;

新建处理业加减乘除业务逻辑类,AddAction,PlusAction,MulAction,DivideAction

/**
 * 两个数相加的动作
 * @author Administrator
 *
 */
public class AddAction implements Action{

    public String execute(HttpServletRequest request,
            HttpServletResponse response) {
        String num1Str = request.getParameter("num1");
        String num2Str = request.getParameter("num2");
        int num1 = Integer.parseInt(num1Str);
        int num2 = Integer.parseInt(num2Str);
        CalcBiz calcBiz = new CalcBiz();
        int result = calcBiz.add(num1, num2);
        request.setAttribute("result", result);
        return "success";
    }
}

其他减乘除只要将业务调处理调用方法改为相应的运算就可以。即calcBiz.plus(num1,num2)..

⑨编写测试页面

index.jsp:

<head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'index.jsp' starting page</title>
	<script type="text/javascript">
		function doSubmit(op) {
			if(op=='+'){
    			document.myform.action='add.action';
    		}else if(op=='-'){
    			document.myform.action='plus.action';
    		}else if(op=='*'){
    			document.myform.action='mul.action';
    		}else if(op=='/'){
    			document.myform.action='divide.action';
    		}
    		document.myform.submit();//提交表单
		}
	</script>
  </head>
  
  <body>
      <FORM METHOD=POST ACTION="" name="myform">	
        <TABLE>
            <TR>
	           <TD>第一个数:</TD>
	           <TD><INPUT TYPE="text" NAME="num1"></TD>
            </TR>
            <TR>
	           <TD>第二个数:</TD>
	           <TD><INPUT TYPE="text" NAME="num2"></TD>
            </TR>
            <TR>
	           <TD><INPUT TYPE="button" VALUE="+" ONCLICK="doSubmit('+')"><INPUT TYPE="button" VALUE="-" ONCLICK="doSubmit('-')"></TD>
	           <TD><INPUT TYPE="button" VALUE="*" ONCLICK="doSubmit('*')"><INPUT TYPE="button" VALUE="/" ONCLICK="doSubmit('/')"></TD>
            </TR>
        </TABLE>
    </FORM>
  </body>

通过调用相应的Action运算之后,我们得到了计算成功时的路径,编写计算结果页面

 

 <body>

  结果:${result}

</body>

取出得到运算结果;

10.测试运算结果


点击相加:


到这里我们通过手写实现了struts2的核心部分功能,通过解析配置文件,及动态创建Action,希望对你理解struts2的实现有所帮助,有问题请多多指教!






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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值