1.Struts2的简介
首先简单介绍下struts2是干什么的。
Struts2是一个web应用框架。它不是一个Struts的新的发布版本,而是一个全新的框架。Struts2是第二代基于Model-View-Controller(MVC)模型的web应用框架。Struts2是java企业版web应用的可扩展性的框架。它是WebWork和Struts社区合并后的产物。struts2没有继承struts1的血统,而是继承了webwork的血统。
2.什么是MVC模型
MVC模型指的是模型-视图-控制器(Model-View-Controller)。MVC模型有助于将应用程序分割成三个组件,使得程序设计更加的容易,并使各个组件之间的耦合程度降到最低。MVC中三个组件分别是:模型(Model)、视图(View)和控制器(Controller).
- 模型(Entity)
模型代表应用程序的数据以及用于访问控制和修改这些数据的业务规则 - 视图(JSP)
视图用来组织模型的内容。视图对象使用对象模型的查询方法以获得数据,并将数据显示给用户 - 控制器(Dao,Service)
控制器定义了应用程序的行为。它负责对来自视图的用户请求进行解析,并把这些请求映射成相应的行为,这些行为由模型负责实现。
3.Struts2的架构
简单分析一下它的工作原理:首先,由用户发出一个请求,经过过滤器(Dispatcher Filter),然后经过一系列的拦截器(Interceptor),通过拦截器的请求会到达Model中的Action类,请求可以通过setxxx()方法给Action中的属性赋值,然后执行相应的execute()方法,根据方法的返回值跳转到相应的JSP.JSP可以通过getxxx()方法从Action中取值,最后给用户做出响应。
4.struts2与传统架构的区别
一般的都采用:JSP+Servlet+JavaBean
Struts2:所有的Servlet都由控制器来管理
5.Struts2的工作流程及其相应的代码
(1).首先,struts2需要一个xml配置文件config.xml,用来配置Action中的一些方法
<?xml version="1.0" encoding="UTF-8"?> <config> <action name="user" class="com.hpu.action.UserAction" method="execute"> <result name="success">WEB-INF/views/suc.jsp</result> <result name="error" type="redirect">/login.action</result> </action> </config>
class:值为相应的Action的完全限定名
method:如果method的值为"execute",则可以省略method属性
result:name属性的值是对应的method方法的放回值;如果type值为“dispatcher”则type属性可以省略
(2).其次,书写相应的Action方法 (其实,应该先写Action方法,然后在配置相应的xml文档)
package com.hpu.action;
public class UserAction {
public String execute(){
//xxxx在这里 你可以做你想做的事
if(2 >= 1){
return "success";
}
return "error";
}
}
注:方法的修饰符必须是public,并且放回类型是String,没有参数列表
(3).配置Controller,简单点也就是配置过滤器
package com.hpu.core;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
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.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.hpu.tag.AcctionTag;
import com.hpu.tag.ResultTag;
public class DispatcherFilter implements Filter{
private Map<String, AcctionTag> config = new HashMap<String, AcctionTag>();
@SuppressWarnings("unchecked")
public void init(FilterConfig filterConfig) throws ServletException {
SAXReader sax = new SAXReader();
Document doc;
try {
doc = sax.read(DispatcherFilter.class.getClassLoader().getResourceAsStream("cofig.xml"));
Element root = doc.getRootElement(); //获取根节点
List<Element> actionList = root.elements("action");
AcctionTag acctionTag = new AcctionTag();
for (Element action : actionList) {
acctionTag.setName(action.attributeValue("name"));
acctionTag.setClassName(action.attributeValue("class"));
acctionTag.setMethod(action.attributeValue("method"));
List<ResultTag> resultTagList = new ArrayList<ResultTag>();
List<Element> resultList = action.elements("result");
for (Element result : resultList) {
ResultTag resultTag = new ResultTag();
resultTag.setName(result.attributeValue("name"));
resultTag.setType(result.attributeValue("type"));
resultTag.setValue(result.getText());
resultTagList.add(resultTag);
}
acctionTag.setResultList(resultTagList);
config.put(acctionTag.getName(), acctionTag);
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
String url = request.getRequestURI();
if(url.endsWith(".action")){
url = url.substring(1,url.indexOf(".action"));
if(config.containsKey(url)){
AcctionTag acctionTag = config.get(url);
String className = acctionTag.getClassName();
try {
Class<?> clazz = Class.forName(className);
Object obj = clazz.newInstance();
Method method = clazz.getMethod(acctionTag.getMethod());
String result = method.invoke(obj).toString(); //获取相应方法的返回值
//看看该返回值是否有配置,然后在找到相应的跳转
List<ResultTag> resultTagList = acctionTag.getResultList();
ResultTag rt = null;
for (ResultTag resultTag : resultTagList) {
if(resultTag.getName().equals(result)){
rt = resultTag;
break;
}
}
if(rt == null){
response.sendError(404, "没找到"+result+"配置项");
}else{
//找到相应的配置,进行页面的跳转
String type = rt.getType();
if("redirect".equals(type)){
response.sendRedirect(rt.getValue());
}else{
request.getRequestDispatcher(rt.getValue()).forward(request, response);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}else{
response.sendError(404, "未找到你请求的URL!");
}
}else{
chain.doFilter(request, response);
}
}
public void destroy() {
}
}
在过滤器的inint方法中解析config.xml文档,在doFilter方法中过滤以“.action”结尾的URL请求,并且做出对应的响应。
还需要在web.xml中配置过滤器
<filter> <filter-name>ControllerFilter</filter-name> <filter-class>com.hpu.core.DispatcherFilter</filter-class> </filter> <filter-mapping> <filter-name>ControllerFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
再次阐述Struts2的请求流程:
首先,客户端发出一个请求,该请求经过过滤器,过滤器首先会解析config.xml文档,完了之后,根据URL找到配置文件中action的name属性值,判断URL请求是否存在,如果存在,根据反射机制找到class属性对应的对象,根据method执行该对象对应的方法,然后获取返回值,由返回值再找到action节点的result节点,根据跳转类型进行跳转。