配置细节问题
struts.xml中默认配置
<default-action-ref name="default"></default-action-ref> <default-class-ref class="com.example.struts2.DefaultAction"> </default-class-ref> <action name="default"> <result name="success">/index.jsp</result> </action>
通用界面配置 —如果某个action中没有对应的result,默认跳转到default.jsp中
<global-results> <result>/default.jsp</result> </global-results>
struts.xml模块分离
<include file="struts-user.xml"></include> 复制 创建struts-user的xml文件
常用常量配置
<constant name="struts.action.extension" value="action,do,"/> <constant name="struts.devMode" value="true" /> 提供详细报错页面,修改struts.xml后不需要重启服务器 (要求) <constant name="struts.serve.static.browserCache" value="false"/> false不缓存,true浏览器会缓存静态内容,产品环境设置true、开发环境设置false
全局异常
<global-exception-mappings> <exception-mapping result="error" exception="java.lang.Exception" name="ErrorAction"></exception-mapping> </global-exception-mappings>
文件上传
企业常用文件上传技术 : jspSmartUpload(主要应用 JSP model1 时代) 、
fileupload (Apache commons项目中一个组件)、
Servlet3.0 集成文件上传 Part类
文件上传 enctype=”multipart/form-data”
是 MIME协议定义多部分请求体 (消息体)
private File upload;
private String uploadContentType;
private String uploadFileName;
public void setUpload(File upload) {
this.upload = upload;
}
public void setUploadFileName(String uploadFileName) {
this.uploadFileName = uploadFileName;
}
public void setUploadContentType(String uploadContentType) {
this.uploadContentType = uploadContentType;
}
@Override
public String execute() throws Exception {
// 查询
String realPath = ServletActionContext.getServletContext().getRealPath(
"/upload");
// 路径
String targetPath = realPath + File.separator + uploadFileName;
// 开始上传
File targetFile = new File(targetPath);
FileUtils.copyFile(upload, targetFile);
return NONE;
}
多文件上传
private File[] upload;
private String[] uploadContentType;
private String[] uploadFileName;
// 查询
String realPath = ServletActionContext.getServletContext().getRealPath("/upload");
for (int i = 0; i < uploadFileName.length; i++) {
String targetPath = realPath + File.separator + uploadFileName[i];
File targetFile = new File(targetPath);
FileUtils.copyFile(upload[i], targetFile);
}
ServletActionContext.getRequest().setAttribute("name", "上传成功");
文件下载
配置xml
<action name="download" class="com.example.demo6.DownloadAction">
<result name="success" type="stream">
<!-- 也是OGNL表达式在配置文件中的写法 setContentType(action中的getContentType()) -->
<param name="contentType">${contentType}</param>
<param name="contentDisposition">${contentDisposition}</param>
</result>
</action>
/**
* 获取请求参数中的文件名称
*/
public void setFileName(String fileName) {
try {
this.fileName = new String(fileName.getBytes("ISO-8859-1"), "UTF-8");
ServletActionContext.getRequest().setAttribute("name", fileName);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// 进行转码
}
//获取了输入流
public InputStream getInputStream() throws FileNotFoundException {
// 第一步:得到文件的真实路径
String realPath = ServletActionContext.getServletContext().getRealPath(
"/upload");
// 第二步:拼接下载的文件路径
String downloadPath = realPath + File.separator + fileName;
// 接下来获取这个输入流
return new FileInputStream(downloadPath);
}
/**
* 获取数据类型
* @return
*/
public String getContentType() {
return ServletActionContext.getServletContext().getMimeType(fileName);
}
//获取下载的头信息
public String getContentDisposition() throws IOException {
// 如何得到客户端浏览器版本
String agent = ServletActionContext.getRequest()
.getHeader("user-agent");
return "attachment;filename=" + encodeDownloadFilename(fileName, agent);
}
注解方式使用Struts2
注意:Action类必须在以.action后缀结尾的位置
@ParentPackage("struts-default")
@Namespace("/test")
public class HelloAnnotationAction extends ActionSupport {
@Action(value = "hehe", results = @Result(location = "/index.jsp", name = "success"))
public String execute() throws Exception {
System.out.println("被访问到了");
return SUCCESS;
}
}
Struts校验
第一种方式 代码校验(简单校验,实际项目中应用较少)
代码校验 validate方法 @Override public void validate() { // 进行验证 if (TextUtils.isEmpty(user.getUsername())) { this.addFieldError("username", "用户名不能为空"); } else { if (user.getUsername().length() < 3 || user.getUsername().length() > 8) { this.addFieldError("username", "用户名长度必须3-8位"); } } if (TextUtils.isEmpty(user.getPassword())) { this.addFieldError("password", "密码不能为空"); } } 代码校验某个方法 login public void validateLogin() { // 进行验证 if (TextUtils.isEmpty(user.getUsername())) { this.addFieldError("username", "用户名不能为空"); } else { if (user.getUsername().length() < 3 || user.getUsername().length() > 8) { this.addFieldError("username", "用户名长度必须3-8位"); } } if (TextUtils.isEmpty(user.getPassword())) { this.addFieldError("password", "密码不能为空"); } } struts.xml中定义这个action <action name="validate" class="com.example.demo2.ValidateAction" method="login"> <result name="input">/demo2/login.jsp</result> <result name="success">/index.jsp</result> </action>
xml校验 实际项目中有较多应用
在当前要校验的action中,创建xxx-validation.xml,源码在 xwork-core-2.3.32.jar中的 com.opensymphony.xwork2.validator.validators default.xml中进行了配置,根据default找到适合自己判断的需求 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> <validators></validators> 内建校验器 * required (必填校验器,要求被校验的属性值不能为null) * requiredstring (必填字符串校验器,要求被校验的属性值不能为null,并且长度大于0,默认情况下会对字符串去前后空格) * stringlength (字符串长度校验器,要求被校验的属性值必须在指定的范围内,否则校验失败,minLength参数指定最小长度,maxLength参数指定最大长度,trim参数指定校验field之前是否去除字符串前后的空格) * regex (正则表达式校验器,检查被校验的属性值是否匹配一个正则表达式,expression参数指定正则表达式,caseSensitive参数指定进行正则表达式匹配时,是否区分大小写,默认值为true) * int(整数校验器,要求field的整数值必须在指定范围内,min指定最小值,max指定最大值) * double(双精度浮点数校验器,要求field的双精度浮点数必须在指定范围内,min指定最小值,max指定最大值) * fieldexpression (字段OGNL表达式校验器,要求field满足一个ognl表达式,expression参数指定ognl表达式,该逻辑表达式基于ValueStack进行求值,返回true时校验通过,否则不通过) * email(邮件地址校验器,要求如果被校验的属性值非空,则必须是合法的邮件地址) * url(网址校验器,要求如果被校验的属性值非空,则必须是合法的url地址) * date(日期校验器,要求field的日期值必须在指定范围内,min指定最小值,max指定最大值) 案例 required 必填校验器 <field-validator type="required"> <message>性别不能为空!</message> </field-validator> requiredstring 必填字符串校验器 <field-validator type="requiredstring"> <param name="trim">true</param> <message>用户名不能为空!</message> </field-validator> stringlength:字符串长度校验器 <field-validator type="stringlength"> <param name="maxLength">10</param> <param name="minLength">2</param> <param name="trim">true</param> <message><![CDATA[产品名称应在2-10个字符之间]]></message> </field-validator> int:整数校验器 <field-validator type="int"> <param name="min">1</param> <param name="max">150</param> <message>年龄必须在1-150之间</message> </field-validator> date: 日期校验器 <field-validator type="date"> <param name="min">1900-01-01</param> <param name="max">2050-02-21</param> <message>生日必须在${min}到${max}之间</message> </field-validator> url: 网络路径校验器 <field-validator type="url"> <message>传智播客的主页地址必须是一个有效网址</message> </field-validator> email:邮件地址校验器 <field-validator type="email"> <message>电子邮件地址无效</message> </field-validator> regex:正则表达式校验器 <field-validator type="regex"> <param name="expression"><![CDATA[^13\d{9}$]]></param> <message>手机号格式不正确!</message> </field-validator> fieldexpression : 字段表达式校验 <field-validator type="fieldexpression"> <param name="expression"><![CDATA[(password==repassword)]]></param> <message>两次密码输入不一致</message> </field-validator>
国际化 i18n
在当前src下创建properties文件
基本名称_语言(小写)_国家(大写).properties
messages_en_US.properties
messages_zh_CN.properties
值栈 ValueStack
什么是值栈?
ValueStack 是 struts2 提供一个接口,实现类 OgnlValueStack ---- 值栈对象 (OGNL是从值栈中获取数据的 ) 每个Action实例都有一个ValueStack对象 (一个请求 对应 一个ValueStack对象 ) 在其中保存当前Action 对象和其他相关对象 (值栈中 是有Action 引用的 ) Struts 框架把 ValueStack 对象保存在名为 “struts.valueStack” 的请求 属性中,request中 (值栈对象 是 request一个属性) valueStack vs = request.getAttribute("struts.valueStack");
值栈的内部结构?
ObjectStack (root): Struts 把动作和相关对象压入 ObjectStack 中--List ContextMap (context): Struts 把各种各样的映射关系(一些 Map 类型的对象) 压入 ContextMap 中 Struts 会把下面这些映射压入 ContextMap 中 parameters: 该 Map 中包含当前请求的请求参数 ?name=xxx request: 该 Map 中包含当前 request 对象中的所有属性 session: 该 Map 中包含当前 session 对象中的所有属性 application:该 Map 中包含当前 application 对象中的所有属性 attr: 该 Map 按如下顺序来检索某个属性: request, session, application
值栈ValueStack 和 ActionContext关系? --- 值栈的创建
* 创建ActionContext 对象过程中,创建 值栈对象ValueStack * ActionContext对象 对 ValueStack对象 有引用的 (在程序中 通过 ActionContext 获得 值栈对象 )
如何获得值栈对象?
方式一 了解 ValueStack valueStack = (ValueStack) ServletActionContext.getRequest(). getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY); 方式二 掌握 ValueStack valueStack2 = ActionContext.getContext().getValueStack();
向值栈保存数据?
方式一 valueStack.push("zhiyuanyuan"); 方式二 valueStack.set("name", "zhiyuan");
在页面通过struts2标签 获取值栈内容?
普通字符串形式
在jsp中 通过 <s:debug /> 查看值栈的内容
取出没有key值且在栈顶下边的数据
<s:property value="[1].top" />
取出栈顶的数据map类型----两种方式
<s:property value="[0].top.name" />-----<s:property value="name"/>
//取出request域中的数据
<s:property value="#request.sex" />
对象存储方式取值
//获取栈顶中的对象的username
<s:property value="username" />
//获取栈中第二个元素对象的username
<s:property value="[1].top.username" />
//获取u对象中的username
User u;
public User getU() {
return u;
}
u = new User();
u.setUsername("wangwu");
u.setPassword("12345");
<s:property value="u.username" />