为了更好的理解和学习struts2框架,老师带我们简单模拟了一下struts2框架的工作流程。
1. 新建一个要执行的类。此处是BaseAction.java。
2. 首先通过配置xml文件,将需要运行的上面新建的类名、函数名、访问路径等配置在xml文件中。此处是:struts2.xml
3. 写一个过滤器,在过滤器中的init方法中先解析xml文件,并封装。然后在doFilter中通过反射执行相应的类。此处的过滤器是:MeFilter.java
例如当我访问:,跳转到xml中配置的jsp页面。
并且控制台打印出:
说明访问成功,并且参数也成功传递进去了。
BaseAction.java:
package com.kerwin.struct;
public class BaseAction {
private String name;
private String id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public BaseAction() {
super();
}
public String baseMethod(){
System.out.println("name = " + name +"---id = " +id );
return "ok";
}
}
struts2.xml:
<?xml version="1.0" encoding="UTF-8"?>
<package>
<!-- name:访问路径,class:运行的类的全限定名,method:运行的方法 -->
<action name="base" class="com.kerwin.struct.BaseAction" method="baseMethod">
<!-- name:执行函数后的返回值,type:执行函数后是转发还是重定向 -->
<result name="ok" type="dispatcher">
<!-- 转发或重定向的页面 -->
/index.jsp
</result>
</action>
</package>
<!--
解析src/struts2.xml文件,
将所有标签的属性值解析出来,
封装到Xml2Bean.java这个类的属性中
-->
将xml封装的bean对象:Xml2Bean.java
package com.kerwin.struct;
public class Xml2Bean {
// <action name="register" class="cn.itcast.javaee.ajax.UserAction"
// method="execute"></action>
private String actionName;
private String actionClass;
private String actionMethod;
// <result name="ok" type="dispatcher">/ok.jsp</result>
private String resultName;
private String resultType;
private String resultContent;
public Xml2Bean() {
}
public Xml2Bean(String actionName, String actionClass, String actionMethod, String resultName, String resultType, String resultContent) {
super();
this.actionName = actionName;
this.actionClass = actionClass;
this.actionMethod = actionMethod;
this.resultName = resultName;
this.resultType = resultType;
this.resultContent = resultContent;
}
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 String getActionMethod() {
return actionMethod;
}
public void setActionMethod(String actionMethod) {
this.actionMethod = actionMethod;
}
public String getResultName() {
return resultName;
}
public void setResultName(String resultName) {
this.resultName = resultName;
}
public String getResultType() {
return resultType;
}
public void setResultType(String resultType) {
this.resultType = resultType;
}
public String getResultContent() {
return resultContent;
}
public void setResultContent(String resultContent) {
this.resultContent = resultContent;
}
}
过滤器MeFilter.java:
package com.kerwin.struct;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Enumeration;
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.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class MeFilter implements Filter {
Xml2Bean bean = null;
public void init(FilterConfig filterConfig) throws ServletException {
try {
//使用类加载器,加载src/struts2.xml文件
InputStream inputStream = MeFilter.class.getClassLoader().getResourceAsStream("struts2.xml");
SAXReader reader = new SAXReader();
Document document = reader.read(inputStream);
Element root = document.getRootElement();
Element actionElement = root.element("action");
String actionName = actionElement.attributeValue("name");
String actionClass = actionElement.attributeValue("class");
String actionMethod = actionElement.attributeValue("method");
Element resultElement = actionElement.element("result");
String resultName = resultElement.attributeValue("name");
String resultType = resultElement.attributeValue("type");
String resultContent = actionElement.elementText("result").trim();
bean = new Xml2Bean(actionName, actionClass, actionMethod, resultName, resultType, resultContent);
} catch (Exception e) {
e.printStackTrace();
}
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
try {
//父子接口强转
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
//获取请求的路径(/hello.action)
String servletPath = request.getServletPath();
//获取请求的路径(hello.action)
servletPath = servletPath.substring(1);
int index = servletPath.indexOf(".");
//获取请求的路径(hello)
servletPath = servletPath.substring(0, index);
//用me.xml文件中的<action name="hello"/>做个比较
if( bean.getActionName().equals( servletPath)){
//获取<action class="cn.itcast.javaee.base.HelloAction"/>字符串
String actionClass = bean.getActionClass();
//获取字节码
Class clazz = Class.forName(actionClass);
//字节码产生对象
Object obj = clazz.newInstance();
//获取请求参数的集合
Enumeration<String> enumeration = request.getParameterNames();
//获取Action中所有属性集合
Field[] fields = clazz.getDeclaredFields();
//迭代
for(int i=0; i<fields.length && enumeration.hasMoreElements(); i++){
//获取每一个属性
String fileName = fields[i].getName();
//获取请求参数中的每一个属性值
String fileNameValue = request.getParameter(fileName);
//将每一个属性值注入到Action的属性中去
fields[i].setAccessible(true);
fields[i].set(obj, fileNameValue);
}
//获取<action method="execute"/>字符串
String actionMethod = bean.getActionMethod();
//取得对应的方法,此时method就是execute方法
Method method = clazz.getMethod(actionMethod, null);
//执行method所代表的execute方法
Object returnValue = method.invoke(obj, null);
//获取<result name="ok"/>字符串
if(returnValue.equals(bean.getResultName())){
//获取<result>/ok.jsp</result>字符串
String pagePath = bean.getResultContent();
//获取<result type="dispatcher"/>字符串
if("dispatcher".equals(bean.getResultType())){
//转发
request.getRequestDispatcher(pagePath).forward(request, response);
}else if("redirect".equals(bean.getResultType())){
//重定向
response.sendRedirect(request.getContextPath() + pagePath);
}
else {
//返回404状态码
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
else{
//返回404状态码
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
else{
//返回404状态码
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void destroy() {
}
}
Struts2就是通过配置xml文件,将要执行的类和方法等配置在xml文件中,
然后在过滤器中通过反射执行相应的类和方法。