实现Struts2跳转功能

MVC 框架最基础的功能就是跳转,struts2支持注解+xml配置跳转,在这里我设计成xml配置的跳转。

配置跳转需要用到的知识有:反射,xml读取。

反射是实现动态装配的基础,它使我们的程序更具动态性和可扩展性,几乎所有的流行框架都以它为基础实现。xml读取基本都会采用dom4j完成。

实现跳转的过程:xml配置命名空间,Action处理类,请求的action方法和跳转的页面,在form提交请求后,被中心Servlet处理,解析出请求的路径,根据xml配置的各种信息,反射调用目标Action类的处理方法,并且根据xml配置的目标跳转页面进行跳转。

因此提炼出的 核心配置有

1、namcespace:命名空间,不同模块有不同的namespace。

2、name:form请求的名字。

3、method:name对应的Action处理方法名,会被反射调用。

4、 class:Action处理类的全路径,用于在中心Servlet反射生成。

5、 result子标签:Action处理后的跳转页面,跳转方式为forward或redirect。


下面我们就开始实现这个简单的跳转功能:

1、首先建一个web工程(Eclipse),取名Controller

2、接着建一个Filter,取名StrutsFilter,做中心处理器用。(也可以用Servlet,这里我用Filter

3、根目录建control.xml当作跳转配置文件。

<?xml version="1.0" encoding="UTF-8"?>

    //标签名可自定义,这里高仿Struts看着习惯点。
    <struts>
       <package name="user" namespace="/admin">
         <action name="userAction" class="action.UserAction">
          <result name="addUser" >/addUser.jsp</result>
         </action>
       </package>
    </struts>

4、配置web.xml,使其拦截所有action结尾的请求。

<?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">
	
    <filter>
        <filter-name>struts3</filter-name>
        <filter-class>core.StrutsFilter</filter-class>
    </filter>	
    
    <filter-mapping>
        <filter-name>struts3</filter-name>
        <url-pattern>*.action</url-pattern>
    </filter-mapping>
    	
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
  
</web-app>

5 、创建Entity( ActionEntity、PackageEntity、ResultEntity)

package core;

import java.util.List;

public class ActionEntity {
	
	private String name;
	private String classname;
	private List<ResultEntity> result;
	
	public List<ResultEntity> getResult() {
		return result;
	}
	public void setResult(List<ResultEntity> result) {
		this.result = result;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getClassname() {
		return classname;
	}
	public void setClassname(String classname) {
		this.classname = classname;
	}
}

package core;

import java.util.List;

public class PackageEntity {
	
	private String name;
	private String namespace;
	private List<ActionEntity> action;
	
	public List<ActionEntity> getAction() {
		return action;
	}
	public void setAction(List<ActionEntity> action) {
		this.action = action;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getNamespace() {
		return namespace;
	}
	public void setNamespace(String namespace) {
		this.namespace = namespace;
	}
}

package core;

public class ResultEntity {
	private String name;
	private String page;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPage() {
		return page;
	}
	public void setPage(String page) {
		this.page = page;
	}
}

6、创建解析xml的类(ConfigUtils),实现配置文件的解析功能。

package core;

import java.util.ArrayList;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

/**
 * 解析配置文件
 * @author Candy
 *
 */
public class ConfigUtils {
	
	//创建封装对象,把从配置文件中读取到的值设置到对象里。(这里假设只有一个package,如果多个换成集合)
	public static PackageEntity packageEntity=new PackageEntity();

	public static void config(){	
        	//创建解析对象
        	SAXReader reader= new SAXReader();
        try {
        	//读取自定的配置文件
	        Document document= reader.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("control.xml"));
		//得到根元素
		Element root=document.getRootElement();
                //得到根元素下面的package元素
		Element packageElement=root.element("package");
                packageEntity.setName(packageElement.attributeValue("name"));
                packageEntity.setNamespace(packageElement.attributeValue("namespace"));
                
                //得到package里面的所以action元素
                List<Element> listActions=packageElement.elements("action");
            
                //创建一个集合用来存得到的所有的action元素,后面要把这个集合设置到封装的package对象里面。
                List<ActionEntity> action=new ArrayList<ActionEntity>();
                //循环得到每一个action元素,并把得到的action的值设置到封装的action对象里。
                for( Element actionElement :listActions){
            	   ActionEntity actionEntity=new ActionEntity();
            	   actionEntity.setName(actionElement.attributeValue("name"));
            	   actionEntity.setClassname(actionElement.attributeValue("class"));
            	//得到action里面的所有result元素,
            	List<Element> listResult=actionElement.elements("result");
            	
            	//创建一个集合用来存储得到的所以的result元素,后面要把这个集合设置到封装的action对象里面
            	List<ResultEntity> result=new ArrayList<ResultEntity>();
            	//循环得到每一个result元素,并把得到的值设置到封装的result对象里。
            	for(Element resuleElement :listResult){
            		ResultEntity resultEntity=new ResultEntity();
            		resultEntity.setName(resuleElement.attributeValue("name"));
            		resultEntity.setPage(resuleElement.getText());
            		//把创建的所有的并赋值后的result添加的上面定义的集合里面。
            	    result.add(resultEntity);
            	}
            	//这里把上面有数据的result所有集合设置到所有的action封装对象里面。
            	actionEntity.setResult(result);
            	//把包含所有result的所有action添加到上面定义的这个action的集合里
            	action.add(actionEntity);
                }
                //把含有所有数据的action这个集合设置到package这个封装的对象里。
                packageEntity.setAction(action);
                } catch (DocumentException e) {
		        	e.printStackTrace();
	         	}
	  }
}

7、实现StrutsFilter中跳转的核心功能。

package core;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;
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;

/**
 * 实现基本跳转功能
 * @author Candy
 *
 */
public class StrutsFilter implements Filter{
	@Override
	public void destroy() {
	}
	@Override
	public void doFilter(ServletRequest request0, ServletResponse response0,
			FilterChain chain) throws IOException, ServletException {
	    //得到封装的package对象。
	    PackageEntity pack=ConfigUtils.packageEntity;
	    //得到用户访问的路径。
	    HttpServletRequest request=(HttpServletRequest)request0;
	    String path=request.getServletPath();
	    //拆分得到的路径。
	    String [] pathArr=path.split("/");
	    //namespace的名字。
	    String nameSpace=pathArr[1];
	    //action的名字和方法的一个整体。
	    String action=pathArr[2];
	    //接着查拆分这个整体,得到action名
	    String actionName=action.split("!")[0];
	    //得到方法名
	    String methodName=action.split("!")[1].split("\\.")[0];
	    List<ActionEntity>listAction=pack.getAction();
	    ActionEntity doAction=null;
	    for(ActionEntity ae:listAction){
	    	if(ae.getName().equals(actionName)){
	    		doAction=ae;
	    		break;
	    	}
	    }
	    try {
	    	//反射一个action的类
			Class actionClass=Class.forName(doAction.getClassname());
			//创建一个action的对象。
		    Object actionObject=actionClass.newInstance();
		    //再次得到类
			Class cla=actionObject.getClass();
			//调用用户访问路径里的方法
			Method actionMethod= cla.getDeclaredMethod(methodName);
			//执行方法
			String resultValue=(String)actionMethod.invoke(actionObject,null);
			//得到result的集合。然后查找对应的result返回。
			List<ResultEntity> listResult=doAction.getResult();
			ResultEntity result=null;
			for(ResultEntity re: listResult){
				if(re.getName().equals(resultValue)){
					result=re;
					break;
				}
			}
			//得到跳转的页面
			String page=result.getPage();
			request.getRequestDispatcher(page).forward(request, response0);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	            ConfigUtils.config();	
	}
}

8、到此为止一个简单的跳转功能就实现了。测试代码如下:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%String path = request.getContextPath();%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
     <title>首页</title>
  </head>
 
  <body>
      <a href="<%=path%>/admin/userAction!toAddUser.action">添加用户</a>
  </body>
</html>

package action;

public class UserAction {	
	public String toAddUser(){
	    System.out.println("添加新用户");
		return "addUser";
	}
}

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <body>
        添加用户成功。
  </body>
</html>


转载于:https://my.oschina.net/CandyDesire/blog/205801

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个简单的 Struts2 连接 MySQL 数据库实现登录功能的示例代码: 首先,在 `struts.xml` 文件中配置一个 Action: ```xml <action name="login" class="com.example.LoginAction"> <result name="success">welcome.jsp</result> <result name="error">login.jsp</result> </action> ``` 然后,创建一个名为 `LoginAction` 的 Java 类,该类实现 `com.opensymphony.xwork2.Action` 接口: ```java package com.example; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import com.opensymphony.xwork2.Action; import com.opensymphony.xwork2.ActionSupport; public class LoginAction extends ActionSupport implements Action { private String username; private String password; public String execute() { Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "password"); pstmt = conn.prepareStatement("SELECT * FROM users WHERE username=? AND password=?"); pstmt.setString(1, username); pstmt.setString(2, password); rs = pstmt.executeQuery(); if (rs.next()) { return SUCCESS; } else { return ERROR; } } catch (ClassNotFoundException e) { e.printStackTrace(); return ERROR; } catch (SQLException e) { e.printStackTrace(); return ERROR; } finally { try { if (rs != null) { rs.close(); } if (pstmt != null) { pstmt.close(); } if (conn != null) { conn.close(); } } catch (SQLException e) { e.printStackTrace(); } } } public void setUsername(String username) { this.username = username; } public void setPassword(String password) { this.password = password; } } ``` 在上面的代码中,我们使用了 JDBC 连接 MySQL 数据库,并在 `execute()` 方法中执行了一个查询语句,查询指定用户名和密码是否存在于 `users` 表中。如果存在,返回 `SUCCESS`;否则,返回 `ERROR`。 最后,在 JSP 页面中添加一个表单,向 Action 提交用户名和密码: ```html <form action="login.action" method="post"> <label>Username:</label> <input type="text" name="username"/><br/> <label>Password:</label> <input type="password" name="password"/><br/> <input type="submit" value="Login"/> </form> ``` 这样,当用户输入用户名和密码并点击登录按钮时,就会向 `LoginAction` 提交表单数据,并执行上面的查询语句,最终到 `welcome.jsp` 或 `login.jsp` 页面。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值