struts2原理及struts2常用标签
struts1:是个特殊的servlet 本身与serlvet API有很大的耦合性,核心是一个叫做actionServlet的servlet类 (配置在web.xml里随web容器启动而加载)
struts2:是个Filter,核心是FilterDispatcher的过滤器
开发步骤:
一.导入struts2的依赖包(struts-core,xwork2,ongl,freemarker,common-loging)
二.在web.xml里添加这个FilterDispatcher的过滤器
三.写个Action类继承SupportAction父类,在类里写ActionForm(可要可不要),覆盖excute方法
四.编写struts.xml文件,一般放在WEB-INF/classes目录下,在里面配置package action
五.编写jsp(使用struts2标签库里的标签-不一定必须要使用,也可以使用通用的jstl和jsp标签)
完成。
strust2大致原理:
一个请求在Struts2框架中的处理大概分为以下几个步骤:
1) 客户端初始化一个指向Servlet容器(例如Tomcat)的请求。
2) 这个请求经过一系列的过滤器(Filter)。
3) 接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请是否需要调用某个Action。
4) 如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy。
5) ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类。
6) ActionProxy创建一个ActionInvocation的实例。
7) ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
8) 一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。
Struts2的核心就是拦截器。Struts.xml中所有的package都要extends="struts-default"。同理与所有的Java类都要extends自Object一样。struts-default.xml里面就是要做以上事情。
总之大致是这样的:http请求-->一系列拦截器-->FilterDispatcher-->ActionMapper-->ActionProxy-->ConfigrationMapper-->Struts.xml-->ActionInvocation-->返回视图
ActionMapper-->确定是不是需要调用struts的action--》把请求给ActionProxy--》通过ConfigrationMapper询问配置文件找到具体的Action和方法
并实例化一个ActionInvocatoin实例(处理返回结果) --》这些东西都是在struts-default.xml里配置好了的
struts2常用标签及解释
<%@ taglib uri="/struts-tags" prefix="s"%>
/* struts 常用表单标签 */
<s:form action="test" namespace="/tag">
<s:textfield label="用户名" name="uname" tooltip="你的名字" javascriptTooltip="false"></s:textfield>
<s:textarea name="rmake" cols="40" rows="20" tooltipDelay="300" tooltip="hi" label="备注" javascriptTooltip="true"></s:textarea>
<s:password label="密码" name="upass"></s:password>
<s:file name="file" label="上传文件"></s:file>
<s:hidden name="id" value="1"></s:hidden>
<s:select list="#{'1':'博士','2':'硕士'}" name="edu" label="学历" listKey="key" listValue="value"></s:select>
<s:checkbox label="爱好 " fieldValue="true" name="checkboxFiled1"></s:checkbox>
<!-- 多个checkbox -->
<s:checkboxlist list="#{1:'java',2:'css',3:'html',4:'struts2',5:'spring'}" label="喜欢的编程语言" name="box"></s:checkboxlist>
<s:radio list="{'男','女'}" name="sex" value="#request.sex"></s:radio>
<s:radio list="#{1:'男',2:'女'}" name="sex1" listKey="key" listValue="value" value="#request.sex1"></s:radio>
<!-- 防止表单提交的方式 -->
<s:token></s:token>
<s:submit value="提交">
</s:form>
/* struts 常用jstl标签 struts标签做jstl标签和jsp标签的时候用#替代了${} */
<h3>获取request里面的值</h3>
<h3>获取的是requet中的对象值</h3>
第一种方式:<s:property value="#request.user1.realName"/>
<br/>
第二种方式:<s:property value="#request.user1['realName']"/>
<br/>
第三种方式:<s:property value="#user1.realName"/>
<h3>获取session中的值</h3>
第一种方式:<s:property value="#session.user1.realName"/>
第二种方式:<s:property value="#session.user1['realName']"/>
<h3>iterator标签的使用 及if-else和输出标签</h3>
<s:iterator var="ent" value="#request.list" status="statu">
<s:if test="%{#statu.odd}"><!-- 取status的数据就要%{} -->
<font color="red"><s:property value="#ent" />
</font>
</s:if>
<s:else>
<s:property value="#ent" />
</s:else>
</s:iterator>
<h3>if else语句的使用</h3>
<s:set name="age" value="21" />
<s:if test="#age==23">
</s:if>
<s:elseif test="#age==21">
</s:elseif>
<s:else>
都不等
</s:else>
<h3>设置page变量</h3>
<s:set name="list" value="{'a','b','c','d'}"></s:set>
<h3>url超链接标签</h3>
<s:a href="http://baidu.com">测试URL</s:a>
<h3>日期标签</h3>
<s:date name="#request.birth" format="yyyy年MM月dd日"/>
struts2小例子
我用的版本是struts-2.3.4.1。虽然我不喜欢废话,可是我不得不废话,我真不明白为什么Struts版本之间怎么差距那么大,坑爹!(言归正传)
1.导包
2.配置文件
(1)web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" 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>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
<!-- 注:struts2从struts-2.1.3以后,org.apache.struts2.dispatcher.FileDispatcher值被标注为过时
且原来struts2默认的必须包也发生了变化,较以前要多加 javassist-3.11.0.GA.jar,commons-lang3-3.1.jar包-->
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
(2)struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="default" namespace="/" extends="struts-default">
<action name="login" class="com.action.LoginAction">
<result name="success">/success.jsp</result>
<result name="error">/error.jsp</result>
</action>
<action name="index" class="com.action.LoginAction" method="indexMethod">
<result>/index.jsp</result>
</action>
</package>
</struts>
3.java代码
(1)工具Action类
package com.action;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.dispatcher.SessionMap;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.interceptor.SessionAware;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
/**
* IoC方式
*/
public class BaseAction extends ActionSupport implements SessionAware,
ServletRequestAware, ServletResponseAware {
private static final long serialVersionUID = 7620009925942346125L;
ActionContext context = ActionContext.getContext();
HttpServletRequest request;
HttpServletResponse response;
@SuppressWarnings("rawtypes")
SessionMap session;
@SuppressWarnings("rawtypes")
public void setSession(Map map) {
this.session = (SessionMap) map;
}
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
public void setServletResponse(HttpServletResponse response) {
this.response = response;
}
}
(2)处理业务的action类
package com.action;
import java.util.ArrayList;
import java.util.List;
import com.model.Account;
import com.service.AccountService;
/**
* Struts2的action可以继承StrutsAPI中的ActionSupport类也可以不继承。
* 这里因为action中要用到request,response,session所以这里我利用IOC做了一个基类Action即BaseAction
* 可以在以后的action中直接继承这个BaseAction就啥都有了
* @author xiefeng
*
*/
@SuppressWarnings("serial")
public class LoginAction extends BaseAction {
private Account accounts;//这个名称一定要与页面端的一样,不然IOC无法注入Bean
public Account getAccounts() {
return accounts;
}
public void setAccounts(Account accounts) {
this.accounts = accounts;
}
AccountService service = new AccountService();
@Override
public String execute() {
//通常从页面获得值到action我们不再用request了,而是用ioc方式,这也正式struts2区别与struts1的一个亮点,与ServletAPI没啥关系了
System.out.println(accounts.getAge());
//Account account = service.getOntAccount(" select * from account where name ='"+accounts.getName()+"'");
//if(account != null) {
return SUCCESS;
//} else {
// return ERROR;
//} 这里的查询数据库,因为我这里的JDBC写的有点儿问题,自己也不想搞JDBC了,实际项目中没有人傻到用JDBC吧,呵呵
}
@SuppressWarnings("unchecked")
public String indexMethod() throws Exception {
Account account = new Account();
account.setId(1l);
account.setName("sdsd");
account.setSex("nan");
account.setAge(23);
session.put("account", account);
request.setAttribute("mesg", "你把我带到哪里去呀!");
List<Account> accountlist = new ArrayList<Account>();
Account account2 = new Account();
account2.setId(2l);
account2.setName("呵呵");
account2.setSex("女");
account2.setAge(46);
accountlist.add(account);
accountlist.add(account2);
request.setAttribute("list",accountlist);
return SUCCESS;
}
}
4.jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%-- <%@ taglib uri="/struts-tags" prefix="s2"%> 这个是引入struts2的标签库--%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="login">
用户名称: <input type="text" name="accounts.name" value=""/>
<br>
用户年龄: <input type="text" name="accounts.age" value="" />
<br>
<input type="submit" value="提交"/>
这里有个问题就是:struts2.1以后非String类型的字段在为空的情况下提交后,会在action端校验抛出异常,但又不影响程序运行,<br>
我现在还没有找到合适的方法解决(除了都定义为String的苦逼方法).忘看到这个帖子的高手教教我吧!
</form>
<%--这个是用struts的标签库 <s2:form action="login">
<s2:textfield name="accounts.name" label="用户名称"></s2:textfield><br>
<s2:textfield name="accounts.age" label="用户年龄 "></s2:textfield><br>
name="accounts.XX"中的accounts一定要与控制器中的一样
<s2:submit></s2:submit>
</s2:form> --%>
<br>
<table>
<tr>
<td>获得session</td>
<td>${sessionScope.account.id},${sessionScope.account.name},${sessionScope.account.sex},${sessionScope.account.age}</td>
</tr>
<tr>
<td>获得request中的list并遍历</td>
<td>
<c:forEach items="${list}" var="accou">
名称:${accou.name},性别:${accou.sex},年龄:${accou.age}<br>
</c:forEach>
</td>
</tr>
<tr>
<td>获得简单的message</td>
<td>${mesg}</td>
</tr>
</table>
<br>
</body>
</html>