搭建Struts2的开发环境:
a、拷贝jar包到应用的构建路径中
从Struts2的发行包:
appsstruts_blank.war
b、在web.xml中对核心控制器进行配置
c、在应用的构建路径的顶端(WEB-INFclasses),建立struts2的配置文件。默认文件名struts.xml
第一个Struts2的入门案例
a、建立一个hello.jsp的页面
b、修改struts2的默认配置文件:struts.xml,增加以下内容
c、建立动作类和动作方法
d、定义结果页面
执行原理:
配置文件struts.xml没有提示
a、方案一:联网
b、方案二:进行本地配置
Struts2的配置文件的位置和加载顺序
一、default.properties:在struts2-core-**.jar包中的org.pache.struts2.default.properties中(框架本身用的)
二、struts-default.xml:在struts2-core-**.jar包中(框架本身用的)
三、struts-plugin.xml:在struts2-**-plugin.jar包中(插件中,给插件用的)
四、struts.xml:在你应用的构建路径中(程序员进行配置的地方。推荐)
五、struts.properties:在你应用的构建路径中(程序员进行配置的地方)
六、web.xml:此处也可以对struts2框架进行配置(不建议。只建议配置过滤器)
重点:后面配置文件中的配置会覆盖掉前面的配置。
struts.xml中的package的namespace细节
struts.xml中的action的配置
struts.xml中的常量配置
<constant name="struts.devMode" value="true" />
name:常量的名称。
(struts2-core-**.jar org.apache.struts.default.properties)文件中
常用的常量:
struts.action.extension=action,, 框架要处理的后缀名称。
struts.devMode = true 开发着模式。实际运行时建议为false
struts.i18n.encoding=UTF-8 框架默认使用的编码。请求参数和输入响应
struts.serve.static.browserCache=true 静态资源要不要缓存。(response.setHeader():Expires;Cache-Control;Progma)
struts.ui.theme=xhtml 和显示结果有关,显示用的主题。simple等
struts.objectFactory = spring 指定实例化动作类的工厂(和Spring集成时用)
struts.enable.DynamicMethodInvocation = false 是否允许动态方法调用
struts.multipart.maxSize=2097152 文件上传时的大小限制
Struts.xml可以有多个
主配置文件叫struts.xml,假设单独模块配置文件叫struts-login.xml
struts.xml 包含 struts-login.xml: <include file="com/china/action/struts-login.xml"/>
实现了模块化开发。
动作类
动作类的定义:
方式一:就是一个普通的POJO。不需要继承或实现任何的类或接口。
方式二:实现com.opensymphony.xwork2.Action
该接口中定义了几个常量:
String SUCCESS = "success";//执行成功时用
String NONE = "none";//执行成功后,不转向任何的视图。比如文件下载。
String ERROR = "error";//执行失败,遇到错误。
String INPUT = "input";//输入验证失败或转换失败,转向输入原有页面。
String LOGIN = "login";//没有登录时,转向的页面。
public String execute() throws Exception;
优点:可以使用常量,编码可以做到尽量统一。
方式三:(推荐)
继承com.opensymphony.xwork2.ActionSupport(默认的动作类)。实现了com.opensymphony.xwork2.Action
定义了 表单域校验、错误信息设置和获得国际化信息相关一些方法
动作类的生命周期
动作类每次访问都会重新被实例化,是线程安全的。
动作方法:动作类中的定义的处理业务有关的方法
特点(重要):public
返回值类型是String
方法没有任何的参数
动作方法通配符的匹配
动作方法的动态调用
指定默认的动作类和动作方法
获取内置对象request,session.application
1)解耦:
代码语言:javascript复制ActionContext cont = ActionContext.getContext();
//request
Map<String,Object> request = (Map<String,Object>)cont.get("request");
request.put("key", "value");
//session
Map<String,Object> session = cont.getSession();
session.put("key", "value");
//application
Map<String,Object> application = cont.getApplication();
application.put("key", "value");
2)耦合:
代码语言:javascript复制//request
HttpServletRequest request = ServletActionContext.getRequest();
request.setAttribute("name", "value");
//session
HttpSession session = request.getSession();
session.setAttribute("name", "value");
//application == ServletContext
ServletContext cont = session.getServletContext();
cont.setAttribute("name","value");
局部和全局结果视图
常用的结果视图类型(共10个)
代码语言:javascript复制<result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/> 从一个动作转发到另外一个JSP
<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/> 从一个动作转发到另外一个动作
<result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
<result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/>
<result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/> 从一个动作重定向到一个JSP
<result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/> 从一个动作重定向到另外一个动作
<result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/> 文件下载
<result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/>
<result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
<result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" /> 以纯文本的形式显示JSP
文件下载
代码语言:javascript复制import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import javax.servlet.ServletContext;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
//文件下载;结果类型stream的使用
public class DownLoadAction extends ActionSupport {
private InputStream imageInputStream;
public InputStream getImageInputStream() {
return imageInputStream;
}
public void setImageInputStream(InputStream imageInputStream) {
this.imageInputStream = imageInputStream;
}
public String download() throws Exception{
//得到文件的真实路径
ServletContext sc = ServletActionContext.getServletContext();
String filePath = sc.getRealPath("/WEB-INF/classes/26.jpg");
//构建输入流
imageInputStream = new FileInputStream(filePath);
//用stream结果视图输出
//返回逻辑视图
return SUCCESS;
}
}
代码语言:javascript复制 <package name="p5" extends="struts-default">
<action name="download" class="com.itheima.actions.DownLoadAction" method="download">
<result name="success" type="stream">
<!-- 配置输入流 -->
<param name="inputName">imageInputStream</param>
<!-- 告知浏览器响应正文的MIME类型 -->
<param name="contentType">application/octet-stream</param>
<!-- 告知浏览器用下载的方式打开 -->
<param name="contentDisposition">attachment;filename=26.jpg</param>
<!-- 下载时使用的缓存大小 -->
<param name="bufferSize">1024</param>
</result>
</action>
</package>
Action中接收请求参数
1)ActionSupport
JSP提交页面:
代码语言:javascript复制<form action="zheng/getUserAction" method="post">
用户名:
<input type="text" name="user.username">
<br />
密码:
<input type="password" name="user.pwd">
<br />
<input type="submit" value="提交">
</form>
User 类:
代码语言:javascript复制public class User{
private String username;
private String pwd;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd; }
}
Action:
代码语言:javascript复制public class 类名 extends
ActionSupport{
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String execute(){
String name = user.getUsername();
System.out.println(name);
return "success";
}
}
JSP显示值页面:
代码语言:javascript复制<body>
<%=request.getParameter("user.username")%>
EL表过式: ${user.username}
${requestScope.user.uname}
</body>
===============================================================================================================
2)ModelDriven
JSP提交页面:
代码语言:javascript复制<form action="zheng/getUserAction" method="post">
用户名:
<input type="text" name="username">
<br />
密码:
<input type="password" name="pwd">
<br />
<input type="submit" value="提交">
</form>
User 类:
代码语言:javascript复制public class User{
private String username;
private String pwd;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd; }
}
Action:
代码语言:javascript复制public class GetUserAction implements ModelDriven<User>{//注意:这里的参数是User
private User user = new User();
public User getModel() {
return user; //注意:这里返回的是User 对象
}
public String execute(){
String username = getModel().getUsername();
System.out.println(username);
return "success";
}
}
JSP显示值页面:
代码语言:javascript复制<body>
<%=request.getParameter("username")%>
EL表过式: ${username}/
${param.uname}/ ${requestScope.uname}
</body>
========================================================================================================== 3)在action中定义属性
代码语言:javascript复制JSP提交页面:
<form action="zheng/getUserAction" method="post">
用户名:
<input type="text" name="username">
<br />
密码:
<input type="password" name="pwd">
<br />
<input type="submit" value="提交">
</form>
Action:
代码语言:javascript复制public class GetUserAction{
private String username;
private String pwd;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String execute(){
System.out.println("name= " getUsername());
return "success";
}
}
JSP显示值页面:
代码语言:javascript复制<body>
<%=request.getParameter("username")%>
EL表过式: ${username}
</body>
还可以结合起来:
原理:实际上由一个拦截器来完成的modelDriven
该拦截器会在执行动作方法前,把模型对象压到ValueStack值栈的栈顶。
上传附件
重要:如果因为文件大小不能上传可以在struts.xml中配置<constant name="struts.multipart.maxSize" value="100000000"/> 1)单个附件上传,上传到服务器的硬盘上,用的是struts2提供的二个包 ( commons-io-1.3.2.jar commons-fileupload-1.2.1.jar)
private File uploadImage; //得到上传的文件 注和JSP页上的 text=file 的名称(name)是一样的 private String uploadImageContentType; //得到文件的类型 private String uploadImageFileName; //得到文件的名称 struts2 提供方法 FileUtils.copyFile()
代码语言:javascript复制 String realPath=ServletActionContext.getServletContext().getRealPath("/upload");
File file=new File(realPath);
if(!file.exists()){
file.mkdirs();
}
FileUtils.copyFile(uploadImage, new File(file, uploadImageFileName));
2)多个附件上传,上传到服务器的硬盘上,用的是struts2提供的二个包 private File[] image; // 上传的文件 private String[] imageFileName; // 文件名称 private String[] imageContentType; // 文件类型 FileUtils.copyFile(,)
使用struts标签在页面上显示多个图片的jsp代码:
代码语言:javascript复制<%@ taglib prefix="s" uri="/struts-tags" %>
<body>
上传成功
<s:iterator id="img" value="#session.name" status="st">
第<s:property value="#st.getIndex() 1" />个图片<br>
<img src="upload/<s:property value='#img'/>" width="300">
<br>
</s:iterator>
</body>
3) 单个附件上传,上传到服务器的硬盘上,用的是IO private File uploadImage; //得到上传的文件 注和JSP页上的 text=file 的名称是一样的 private String uploadImageContentType; //得到文件的类型 private String uploadImageFileName; //得到文件的名称 IO
代码语言:javascript复制 BufferedInputStream bis=null;
BufferedOutputStream bos=null;
bis=new BufferedInputStream(new FileInputStream(user.getUploadImage()));
bos=new BufferedOutputStream(new FileOutputStream(new File(file, newFileName)));
byte []buf=new byte[4096];
int len=-1;
while((len=bis.read(buf))!=-1){
bos.write(buf, 0, len);
}
bos.flush();
bos.close();
bis.close();
4) 多个附件上传,上传到服务器的硬盘上,用的是IO private File[] image; //上传的文件 private String[] imageFileName; //文件名称 private String[] imageContentType; //文件类型
或 private List<File> image; // 上传的文件 private List<String> imageFileName; // 文件名称 private List<String> imageContentType; // 文件类型 IO