Java后台处理框架之struts2学习总结
最近我在网上了解到,在实际的开发项目中struts2的使用率在不断降低,取而代之的是springMVC。可能有很多的朋友看到这里就会说,那还不如不学struts2,直接学习springMVC算了。如果你急于忙着开发项目,这个想法没错。但是,我在这里想说一下的就是,框架其实是对基础代码的封装,对流行功能的优化,为了提高开发效率而存在的。好比武林大会上降龙十八掌,金钟罩,铁布衫,说到底大家还是要靠拳打脚踢的嘛。Struts2,springMVC就是各种招式,我们学习它,学的是招式,以便于更好的见招拆招。闲话不多扯,我来对我这几天的struts2学习做一次总结。
1.struts2防重复提交。
首先要在jsp提交页面导入<%@taglib prefix="s" uri="/struts-tags" %>
在这里有两种方法:一个是在要提交的表单里面嵌入标签<s:token></s:token>,如下:
<s:actionerror/><!--提示错误信息-->
<form action="student" method="post" >
<s:token></s:token>
姓名:<input type="text" name="student.name"/><br/>
年龄:<input type="text" name="student.age"/><br/>
<input type="submit" value="提交"/>
</form>
接着,在项目src下配置struts.xml如下:
<package name="main" extends="struts-default">
<action name="student" class="action.StudentAction" method="add">
<result name="success">/success.jsp</result>
<result name="invalid.token">/student.jsp</result><!--令牌提醒重复提交-->
<interceptor-ref name="token"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
</package>
另一种方法是:直接在struts.xml中配置为无视重复提交(推荐使用这种方法),如下
<package name="main" extends="struts-default">
<action name="student" class="action.StudentAction" method="add">
<result name="success">/success.jsp</result>
<interceptor-ref name="tokenSession"></interceptor-ref><!--无视重复提交-->
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
</package>
2.struts2过滤敏感词汇。比如在进行用户注册时,对用户提交的姓名进行过滤。
假如有个提交页面:
<s:form action="/validationAction" method="post">
<s:textfield name="name" label="姓名"></s:textfield>
<s:submit value="提交"></s:submit>
</s:form>
提交之后,在struts.xml(src直接目录下)中找到配置,
<package name="manager" extends="struts-default">
<action name="validationAction" class="action.ValidationAction">
<result name="input">/validation.jsp</result><!-- 错误,内部返回的是input-->
<result name="success">/success.jsp</result>
</action>
</package>
此时,在包action下找到ValidationAction.java里面代码如下:
package action;
import java.util.Map;
import org.apache.struts2.components.ActionComponent;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class ValidationAction extends ActionSupport{
/**
*
*/
private static final long serialVersionUID = 1L;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String execute() throws Exception {
ActionContext actionComtext=ActionContext.getContext();
Map<String, Object> session=actionComtext.getSession();
session.put("name", name);
System.out.println("姓名:"+name);
return SUCCESS;
}
}
配置文件为ValidationAction-validation.xml(不可随便命名,格式为xx-validation.xml),代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.2//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<validators>
<field name="name">
<field-validator type="requiredstring"><!-- 系统自带验证是否为空-->
<message>请输入姓名</message>
</field-validator>
<field-validator type="sensitive"><!-- 自定义验证。注意此文件是validationAction的配置文件,命名格式一定得为xx-validation.xml,前面的xx一定要和上面的验证validationAction一致 -->
<message>有敏感词汇</message><!-- 此处的自定义验证名为sensitive,自动到validators.xml中去找 -->
</field-validator>
</field>
</validators>
在上面的配置中,我们自定义了一个sensitive验证,在src目录下与struts平级的还得有一个配置文件validators.xml,代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator Config 1.0//EN"
"http://struts.apache.org/dtds/xwork-validator-config-1.0.dtd">
<validators>
<validator name="required" class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"/>
<validator name="requiredstring" class="com.opensymphony.xwork2.validator.validators.RequiredStringValidator"/>
<validator name="int" class="com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator"/>
<validator name="double" class="com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator"/>
<validator name="date" class="com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator"/>
<validator name="expression" class="com.opensymphony.xwork2.validator.validators.ExpressionValidator"/>
<validator name="fieldexpression" class="com.opensymphony.xwork2.validator.validators.FieldExpressionValidator"/>
<validator name="email" class="com.opensymphony.xwork2.validator.validators.EmailValidator"/>
<validator name="url" class="com.opensymphony.xwork2.validator.validators.URLValidator"/>
<validator name="visitor" class="com.opensymphony.xwork2.validator.validators.VisitorFieldValidator"/>
<validator name="conversion" class="com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator"/>
<validator name="stringlength" class="com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator"/>
<validator name="regex" class="com.opensymphony.xwork2.validator.validators.RegexFieldValidator"/>
<validator name="conditionalvisitor" class="com.opensymphony.xwork2.validator.validators.ConditionalVisitorFieldValidator"/>
<!-- 下面的为自定义验证,上面的是系统验证 -->
<validator name="sensitive" class="validators.SensitiveWordValidators"/>
</validators>
根据此配置找到包validators下的SensitiveWordValidators.java,代码如下:
package validators;
import com.opensymphony.xwork2.validator.ValidationException;
import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport;
public class SensitiveWordValidators extends FieldValidatorSupport{
@Override
public void validate(Object object) throws ValidationException {
String fieldName=this.getFieldName();
String value=this.getFieldValue(fieldName, object).toString();//获取输入值
if(!check(value)){
this.addFieldError(fieldName, object);//返回页面提示有敏感词汇(此句话在ValidationAction-validation.xml中)
}
}
public boolean check(String value){
String sensitiveWords[]={"操","你妈","屌","尼玛","日","cao","艹"}; for(int i=0;i<sensitiveWords.length;i++){
if(value.indexOf(sensitiveWords[i])!=-1){
return false;
}
}
return true;
}
}
执行到这里之后,如果有敏感词汇,则直接返回页面提示有敏感词汇。没有敏感词汇的话,则跳转到success.jsp页面。(struts.xml中可知道)
3.Struts2实现文件上传与下载。Struts2实现文件上传是基于拦截器实现的,使用的是fileupload,文件上传大小、类型控制是在struts.xml中配置(src目录下),默认上传最大为2M。
首先来总结单文件上传:假如有个上传页面,如下
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!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>单文件上传</title>
</head>
<body>
<s:fielderror></s:fielderror><!-- 提示上传 错误信息 -->
<form action="upload" method="post" enctype="multipart/form-data">
文件:<input type="file" name="java1234"/><br/>
<input type="submit" value="提交"/>
</form>
</body>
</html>
struts.xml中配置如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="manager" extends="struts-default">
<action name="upload" class="action.FileUploadAction">
<result name="success">/success.jsp</result>
<result name="input">/fileupload.jsp</result>
<!-- <interceptor-ref name="fileUpload">用来进行上传文件限制,只能为图片和大小不超过81101b
<param name="allowedTypes">image/bmp,image/x-png,image/gif,image/jpg,image/jpeg</param>
<param name="maximumSize">81101</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref> -->
</action>
</package>
</struts>
在action包下找到FileUploadAction.java,代码如下:
package action;
import java.io.File;
import org.apache.commons.io.FileUtils;
import com.opensymphony.xwork2.ActionSupport;
public class FileUploadAction extends ActionSupport {
/**
*
*/
private static final long serialVersionUID = 1L;
private File java1234;// 文件
private String java1234FileName;//文件名,格式为提交页面name(java1234)+FileName
private String java1234ContentType;// 文件类型。格式为提交页面name(java1234)+ContentType
public File getJava1234() {
return java1234;
}
public void setJava1234(File java1234) {
this.java1234 = java1234;
}
public String getJava1234FileName() {
return java1234FileName;
}
public void setJava1234FileName(String java1234FileName) {
this.java1234FileName = java1234FileName;
}
public String getJava1234ContentType() {
return java1234ContentType;
}
public void setJava1234ContentType(String java1234ContentType) {
this.java1234ContentType = java1234ContentType;
}
@Override
public String execute() throws Exception {
System.out.println("文件名:" + java1234FileName);
System.out.println("文件类型:" + java1234ContentType);
String filePath="E:/"+java1234FileName;
File savePath=new File(filePath);
FileUtils.copyFile(java1234, savePath);
return SUCCESS;
}
}
上传成功则跳转到success.jsp页面,失败则继续留在原界面(struts.xml可知)
其次来总结多文件上传:多文件上传和单文件上传不同之处便是FileUploadAction.java中用数组来处理文件。代码如下:
package com.java1234.action;
import java.io.File;
import org.apache.commons.io.FileUtils;
import com.opensymphony.xwork2.ActionSupport;
public class FilesUploadAction extends ActionSupport{
/**
*
*/
private static final long serialVersionUID = 1L;
private File[] java1234; // 文件
private String[] java1234FileName; // 文件名
private String[] java1234ContentType; // 文件类型
public File[] getJava1234() {
return java1234;
}
public void setJava1234(File[] java1234) {
this.java1234 = java1234;
}
public String[] getJava1234FileName() {
return java1234FileName;
}
public void setJava1234FileName(String[] java1234FileName) {
this.java1234FileName = java1234FileName;
}
public String[] getJava1234ContentType() {
return java1234ContentType;
}
public void setJava1234ContentType(String[] java1234ContentType) {
this.java1234ContentType = java1234ContentType;
}
@Override
public String execute() throws Exception {
for(int i=0;i<java1234.length;i++){
System.out.println("文件名:"+java1234FileName[i]);
System.out.println("文件类型:"+java1234ContentType[i]);
String filePath="C:/"+java1234FileName[i];
File saveFile=new File(filePath);
FileUtils.copyFile(java1234[i], saveFile);
}
return SUCCESS;
}
}
最后来总结文件下载:返回的是一个文件流
假如有个下载页面如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!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>
<a href="download">文件下载</a>
</body>
</html>
struts.xml中配置为:
<package name="manager" extends="struts-default">
<action name="download" class="action.FileDownloadAction">
<result type="stream"><!-- 前面处理返回的是InputStream -->
<param name="contentDisposition">attachment;filename=${fileName}</param>
</result>
</action>
</package>
根据配置找到action包下面的FileDownloadAction.java,代码如下:
package action;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import com.opensymphony.xwork2.ActionSupport;
public class FileDownloadAction extends ActionSupport{
/**
*
*/
private static final long serialVersionUID = 1L;
private String fileName;
public String getFileName() throws Exception{
fileName=new String(fileName.getBytes(),"ISO8859-1");//解决乱码 return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public InputStream getInputStream()throws Exception{
File file=new File("C:/美女1.jpg");//假设下载的为此文件
this.fileName="美女1号";//自己定义下载的文件名字,系统会补上文件后缀名无需自己添加
return new FileInputStream(file);//和上传不同,返回的是一个InputStream
}
}
4.struts2实现国际化。什么意思呢,就是根据浏览器语言环境,显示不同语言网页。不同国家地区访问网站,给出相应版本语言的网页。
直接先贴出struts.xml配置文件(src目录下)。如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<!-- struts配置支持多语言,根据浏览器环境 -->
<constant name="struts.custom.i18n.resources" value="java1234"></constant>
<!--注意上面的value="java1234",后面的默认properties文件也要java1234此名字-->
</struts>
假如有这么一个登录网页和欢迎界面:注意<s:text name="xx"></s:text>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!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>
<table>
<tr>
<td><s:text name="userName"></s:text></td>
<td>
<input type="text"/>
</td>
</tr>
<tr>
<td><s:text name="password"></s:text></td>
<td>
<input type="text"/>
</td>
</tr>
<tr>
<td>
<input type="button" value="<s:text name='login'></s:text>"/>
</td>
</tr>
</table>
</body>
</html>
欢迎网页:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!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>
<s:text name="welcomeInfo">
<s:param>Jack</s:param><!--此处一般从登录后从session取值-->
</s:text>
</body>
</html>
此时,需要在src下配置properties文件相应的转换规则。此处配置三个properties文件,默认,英文,中文。其他国家的自己去搞,这里只展示三个。默认文件是必须的,文件名要和struts.xml中配置的一致。
Java1234.properties(src目录下)[默认文件],采用Uicode编码,代码如下:
userName=\u7528\u6237\u540d
password=\u5bc6\u7801
login=\u767b\u5f55
welcomeInfo=\u6b22\u8fce{0}
Java1234_en_US.properties(src目录下)[英文],采用Uicode编码,代码如下:
userName=userName
password=password
login=login
welcomeInfo=welcome{0}
Java1234_zh_CN.properties(src目录下)[中文],采用Uicode编码,代码如下:
userName=\u7528\u6237\u540d
password=\u5bc6\u7801
login=\u767b\u5f55
welcomeInfo=\u6b22\u8fce{0}
5.struts2标签。Struts2标签是封装完全的,可以换几套皮肤。
数据标签:
①bean标签:
<s:bean name="com.java1234.model.Student" var="student">
<s:param name="name" value="'张三'"></s:param>
<s:param name="age" value="10"></s:param>
</s:bean>
<s:property value="#student.name"/>
<s:property value="#student.age"/>
②date标签:
<s:date name="#request.date" format="yyyy-MM-dd"/>
举例如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.util.*" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<%
request.setAttribute("date",new Date());
%>
</head>
<body>
${date }<br/>
当前日期:<s:date name="#request.date" format="yyyy-MM-dd"/>
</body>
</html>
③debug标签:
<s:debug></s:debug>
④include标签:
<s:include value="head.html"></s:include>
⑤property标签:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<%
request.setAttribute("name","<font color=red>张三</font>");
%>
</head>
<body>
<s:property value="#request.name" /><br/>
<s:property value="#request.name2" default="某某人"/><br/>
<s:property value="#request.name" default="某某人" escapeHtml="false"/><br/>
</body>
</html>
⑥set标签:
<s:set var="i" value="1"></s:set>
<s:property value="#i" /><br/>
<s:set var="a" value="'action范围的值'" scope="action"></s:set>
<s:set var="p" value="'page范围的值'" scope="page"></s:set>
<s:set var="r" value="'request范围的值'" scope="request"></s:set>
<s:set var="s" value="'session范围的值'" scope="session"></s:set>
<s:set var="app" value="'application范围的值'" scope="application"></s:set>
<s:property value="#a" /><br/>
<s:property value="#attr.p"/><br/>
<s:property value="#request.r"/><br/>
<s:property value="#session.s"/><br/>
<s:property value="#application.app"/><br/>
⑥url标签:
<s:url action="hello" namespace="/foreground" id="h">
<s:param name="name" value="'struts2'"></s:param>
</s:url>
<s:a href="%{h}">超链接</s:a>
<s:a action="hello" namespace="/foreground">
<s:param name="name" value="'struts2'"></s:param>
超链接2
</s:a>
控制标签:
Append标签(叠加标签)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="com.java1234.model.Student" %>
<%@ page import="java.util.*" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<%
List<Student> studentList1=new ArrayList<Student>();
List<Student> studentList2=new ArrayList<Student>();
studentList1.add(new Student(1,"张三",10));
studentList1.add(new Student(3,"李四",20));
studentList2.add(new Student(5,"王五",30));
studentList2.add(new Student(7,"赵六",40));
request.setAttribute("studentList1",studentList1);
request.setAttribute("studentList2",studentList2);
%>
</head>
<body>
<s:append var="studentList3">
<s:param value="#request.studentList1"></s:param>
<s:param value="#request.studentList2"></s:param>
</s:append>
<table>
<tr>
<th>序号</th>
<th>编号</th>
<th>姓名</th>
<th>年龄</th>
</tr>
<s:iterator value="studentList3" status="status">
<tr>
<td><s:property value="#status.index+1"/></td>
<td><s:property value="id"/></td>
<td><s:property value="name"/></td>
<td><s:property value="age"/></td>
</tr>
</s:iterator>
</table>
</body>
</html>
generator标签(分割标签)
<s:generator separator="," val="'张三,李四,王五'" var="nameList"></s:generator>
<s:iterator value="#nameList"><!--相当于去掉,-->
<s:property/>
</s:iterator>
ifelse标签(判断标签)
<title>Insert title here</title>
<%
int age=11;
request.setAttribute("age",age);
%>
</head>
<body>
<s:if test="#request.age<20">
年龄小于20岁
</s:if>
<s:elseif test="#request.age==20">
年龄等于20岁
</s:elseif>
<s:else>
年龄大于20岁
</s:else>
</body>
UI标签:
<s:checkboxlist list="#{0: '游泳', 1:'唱歌 ',2:'跳舞'}" name="hobby" value="1" />
<s:form action="hello" method="post" namespace="/foreground">
<s:radio list="#{0: '男 ', 1:'女 '}" name="sex" value="0" />
<s:select list="#{0: '游泳', 1:'唱歌 ',2:'跳舞'}" name="hobby" value="1" multiple="true"/>
<s:textfield name="userName"></s:textfield><br/>
<s:password name="password"></s:password><br/>
<s:textarea name="desc"></s:textarea><br/>
其他标签:
<s:optiontransferselect label="选择你喜欢图书"
name="cnbook" leftTitle="中文图书" list="{'struts2权威指南','轻量级javaeye 企业应用空实战','ajax讲义'}"
doubleName="enBook" rightTitle="外文图书" doubleList="{'JavaScrip:The definitive Guide','export one-to-one'}" multiple="true"
addToLeftLabel="向左移动" addToRightLabel="向右移动" addAllToRightLabel="全部右移" addAllToLeftLabel="全部左移"
allowSelectAll="true" headerKey="cnKey" headerValue="选择图书" emptyOption="true" doubleHeaderKey="enKey"
doubleHeaderValue="选择外文图书" doubleMultiple="true" doubleEmptyOption="true" leftDownLabel="向下移动"
rightDownLabel="向下移动"
leftUpLabel="向上移动"
rightUpLabel="向上移动" >
</s:optiontransferselect>
<s:updownselect
list="#{0:'游泳', 1:'唱歌', 2:'跳舞'}"
name="hobby"
headerKey="-1"
headerValue="请选择"
emptyOption="true"
allowMoveUp="true"
allowMoveDown="true"
allowSelectAll="true"
moveUpLabel="Move Up"
moveDownLabel="Move Down"
selectAllLabel="Select All" />
6.struts2中用ognl(对象图导航语言)访问复杂对象,静态方法和静态属性(此功能太过于强大,请慎用。注意数据的安全性)
此处要获取静态方法和属性,必须为public。默认状态下,是不允许访问静态方法,因此要在struts.xml配置<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant><!-- 此处配置为可以使用ognl访问静态方法 -->
在jsp页面访问代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!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>
ognl获取静态属性:<s:property value="@com.java1234.comom.MyStatic@name"/><br />
ognl获取静态方法:<s:property value="@com.java1234.comom.MyStatic@print()"/><!-- 在此处要获取静态方法必须在struts.xml中配置<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>,默认是不能直接访问的,保证安全性 -->
</body>
</html>
获取对象代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!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>
ognl获取对象值:
<s:property value="student.name"/><s:property value="student.age"/><br />
ognl获取list对象
<s:property value="students[0].name"/><s:property value="students[0].age"/><s:property value="students[1].name"/><s:property value="students[1].age"/><br />
ognl访问Map:<s:property value="studentMap['goodStudent'].name"/><s:property value="studentMap['goodStudent'].age"/><br/>
<s:property value="studentMap['badStudent'].name"/><s:property value="studentMap['badStudent'].age"/><br/>
</body>
</html>
7.struts2中的值的存储与获取
首先配置struts.xml,代码如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="manage" namespace="/" extends="struts-default">
<action name="hello" class="com.java1234.action.HelloAction">
<result name="success">success.jsp</result>
</action>
</package>
</struts>
配置接着找到action包下面的HelloAction.java,代码如下:
package com.java1234.action;
import java.util.Map;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
public class HelloAction extends ActionSupport{
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public String execute() throws Exception {
ActionContext actionContext=ActionContext.getContext();
//设置狭义上的值栈
ValueStack valueStack= actionContext.getValueStack();
valueStack.set("name", "女神(ValueStack)");
valueStack.set("age", 21);
//设置session中的值
Map<String, Object> session=actionContext.getSession();
session.put("name", "女神(session)");
session.put("age", 22);
//设置application中的值
Map<String, Object> application=actionContext.getApplication();
application.put("name", "女神(application)");
application.put("age", 23);
return SUCCESS;
}
}
现在怎么取值呢,代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!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>
<%
request.setAttribute("name", "女神(request)");
request.setAttribute("age", "24");
%>
</head>
getValueStack's value is:<s:property value="name"/><s:property value="age"/><br />
getSession's value is:<s:property value="#session.name"/><s:property value="#session.age"/><br />
getApplication's value is:<s:property value="#application.name"/><s:property value="#application.age"/><br />
getRequest's value is:<s:property value="#request.name"/><s:property value="#request.age" /><br />
getAttr's value is:<s:property value="#attr.name" /><s:property value="age"/><!-- attr默认的获取值的方式是:ValueStack Page Request Session Application顺序来找一个 -->
</body>
</html>
8.struts2中登录验证,也就是服务器端的验证了。在这里我要谈谈我对js登录验证和struts登录验证的联系和区别。一开始我学习到这里的时候很迷糊,我以前学习过js,很好用。为什么在这里还有学习登录验证呢。原来,struts2是服务器端验证。两种方式都是对用户身份进行验证,区别便是一个是客户端验证,一个是服务器验证。客户端验证也是就是js验证,反应速度很快,无需刷新页面,用户体验度很高。但是提升用户体验度的同时,也付出了安全性代价,js验证可以人为的跳过,使黑客能不经身份验证便访问服务器资源。服务器验证也就是这里的struts2验证,用户每次验证都要刷新页面,用户体验度不高,验证速度较慢,但是安全性高。所以验证最好的方式便是双重验证,至于为什么,想想很快就能明白了。
现在总结struts2登录验证,Struts2验证是基于拦截器的。
首先贴出struts.xml配置文件(src目录下),代码如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="manage" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="loginInterceptor" class="com.java1234.interceptor.LoginInterceptor"></interceptor>
<interceptor-stack name="myStack">
<interceptor-ref name="loginInterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="myStack"></default-interceptor-ref>
<global-results>
<result name="error">error.jsp</result>
</global-results>
<!-- 在这里的action中class都要指向有的,不然浏览器直接无法访问所有的 -->
<action name="user" class="com.java1234.action.UserAction">
<result name="success">success.jsp</result>
<interceptor-ref name="defaultStack"></interceptor-ref><!-- 必须加上这句话,不然永远拦截没有通过 -->
</action>
<!--gril是模拟的登录之后的后续访问操作,没有验证通过便不能访问-->
<action name="gril" class="com.java1234.action.GrilAction">
<result name="success">success.jsp</result>
</action>
</package>
</struts>
当页面访问user后,找到UserAction.java,代码如下:
package com.java1234.action;
import java.util.Map;
import com.java1234.model.User;//放用户数据
import com.java1234.service.UserService;//登录具体的验证方法
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class UserAction extends ActionSupport{
/**
*
*/
private static final long serialVersionUID = 1L;
private UserService userService=new UserService();
private User user;
private String error;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
@Override
public String execute() throws Exception {
if(userService.login(user)){
ActionContext actionContext=ActionContext.getContext();
Map<String, Object> session=actionContext.getSession();
session.put("currentUser", user);
return SUCCESS;
}else{
this.error="用户名或密码错误";
return "error";
}
}
}
上面的代码意思为:如果验证通过,则把数据放到session中,如果没有通过则返回用户名或者密码错误。这里要说明的是,Useraction.java中为最后的验证,验证数据放在User.java中,验证方法放在UserService.java中。
现在贴出拦截器代码:
package com.java1234.interceptor;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class LoginInterceptor implements Interceptor{
@Override
public void destroy() {
// TODO Auto-generated method stub
System.out.println("LoginInterceptor销毁");
}
@Override
public void init() {
// TODO Auto-generated method stub
System.out.println("LoginInterceptor初始化");
}
@Override
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("在Action执行之前");
ActionContext actionContext=invocation.getInvocationContext();
Map<String, Object> session=actionContext.getSession();
Object currentUser=session.get("currentUser");
String result=null;
if(currentUser!=null){
result=invocation.invoke();
}else{
HttpServletRequest request=(HttpServletRequest)invocation.getInvocationContext().get(ServletActionContext.HTTP_REQUEST);
request.setAttribute("error", "请先登录!");
result="error";
}
System.out.println("result:"+result);
return result;
}
}
上面的代码其实就是验证session是否为空,空的话提醒先登录,不能有后续的gril操作。注意,在程序运行的时候就已经初始化拦截器,在struts.xml可以知道,拦截器是放在user的前面的。还有要注意的就是,在struts.xml中<action name=”user”.....>中后面要添加上<interceptor-ref name="defaultStack"></interceptor-ref>,不然没法通过拦截器
在struts.xml还配置了一个全局error页面,
<global-results>
<result name="error">error.jsp</result>
</global-results>
这样只需一个就可以搞定所有的出错页面,不用再在每个<result>中写<result name=”error”>error.jsp</result>,error.jsp代码贴出来:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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>
错误信息:${error } <a href="login.jsp">登录</a>
</body>
</html>
还有要说明的是,有四个包分别为:action、interceptor、model、service
action中写UserAction.java(最后的验证),interceptor中写LoginInterceptor.java(判断session中是否为空),空的话直接返回error,不为空则进行下一步操作
ActionContext actionContext=invocation.getInvocationContext();
Map<String, Object> session=actionContext.getSession();
Object currentUser=session.get("currentUser");
String result=null;
if(currentUser!=null){
result=invocation.invoke();//
}else{
HttpServletRequest request=(HttpServletRequest)invocation.getInvocationContext().get(ServletActionContext.HTTP_REQUEST);
request.setAttribute("error", "请先登录!");
result="error";
}
model中写User.java放用户数据
package com.java1234.model;
public class User {
private String userName;
private String password;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Service中写UserService.java,判断登录方法:
package com.java1234.service;
import com.java1234.model.User;
public class UserService {
public boolean login(User user){
if("java1234".equals(user.getUserName())&&"123456".equals(user.getPassword())){
return true;
}else{
return false;
}
}
}
9.struts2处理多值传入(批量添加)
比如有个提交页面,添加多个学生:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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="student" method="post">
<table>
<tr>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
</tr>
<tr>
<td><input type="text" name="students[0].name"/></td>
<td><input type="text" name="students[0].sex"/></td>
<td><input type="text" name="students[0].age"/></td>
</tr>
<tr>
<td><input type="text" name="students[1].name"/></td>
<td><input type="text" name="students[1].sex"/></td>
<td><input type="text" name="students[1].age"/></td>
</tr>
<tr>
<td colspan="3">
<input type="submit" value="提交"/>
</td>
</tr>
</table>
</form>
</body>
</html>
struts.xml(src目录下)配置如下
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="helloWorld" extends="struts-default">
<action name="student" namespace="/fore" class="com.java1234.action.StudentAction" method="show" >
<result name="success">success.jsp</result>
<result name="error">false.jsp</result>
</action>
</package>
</struts>
根据配置找到StudentAction.java,代码如下:
package com.java1234.action;
import java.util.List;
import com.java1234.model.Student;//放数据,并重写toString方法
import com.opensymphony.xwork2.Action;
public class StudentAction implements Action {
private List<Student> students;
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
@Override
public String execute() throws Exception {
System.out.println("执行了Action的默认方法");
for (Student s : students) {
System.out.println(s);
}
return SUCCESS;
}
public void show() throws Exception {
System.out.println("执行了show的方法");
for (Student s : students) {
System.out.println(s);
}
}
}
再来举个例子,比如处理多选框值:
假如有个提交页面如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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="hobby" method="post">
爱好:
<input type="checkbox" name="hobby" value="吃饭"/>吃饭
<input type="checkbox" name="hobby" value="睡觉"/>睡觉
<input type="checkbox" name="hobby" value="打豆豆"/>打豆豆
<input type="checkbox" name="hobby" value="数绵阳"/>数绵阳
<input type="submit" value="提交"/>
</form>
</body>
</html>
struts.xml配置如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="helloWorld" extends="struts-default">
<action name="hobby" class="com.java1234.action.HobbyAction">
<result name="success">success.jsp</result>
<result name="error">false.jsp</result>
</action>
</package>
</struts>
根据配置找到HobbyAction.java代码如下:
package com.java1234.action;
import com.opensymphony.xwork2.ActionSupport;
public class HobbyAction extends ActionSupport {
/**
*
*/
private static final long serialVersionUID = 1L;
private String[] hobby;
public String[] getHobby() {
return hobby;
}
public void setHobby(String[] hobby) {
this.hobby = hobby;
}
@Override
public String execute() throws Exception {
System.out.println("执行了Action的默认方法");
if (hobby != null) {
for (String h : hobby) {
System.out.println(h);
}
}
return SUCCESS;
}
}
好了,以上便是我这几天所学struts2我认为应该总结的东西,还有很多细枝末节就不再累述了。学完了struts2感触最深的就是拦截器,功能很强大,能处理很多用户需求。但是使用struts2的时候要小心,会出现意想不到的情况,数据要保护好,异常也要处理得当。