1.struts2的6个优点
2.搭建struts2开发环境的3个步骤
导入jar文件
最少需要的6个jar文件:struts2-core-2.x.x.jar;xwork-2.x.x.jar;ognl-2.6.x.jar;
freemarker-2.3.x.jar;commons-logging-1.1.x.jar;commons-fileupload-1.2.1.jar;
编写Struts2的配置文件 struts.xml,该文件存放在WEB-INF/classes下,在开发阶段放在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>
在Web.xml中加入Struts2 MVC框架启动配置
struts2通过Filter进行启动,在Web.xml中进行配置,StrutsPrepareAndExecuteFilter.init()将读取类路径下默认的配置文件struts.xml完成初始化操作。
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
<!-- struts 2.1.3 以后使用上面的类,struts 2.1.3 以前使用下面的类
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> -->
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3.helloworld程序
3.1配置struts.xml
<package name="itcast" namespace="/test" extends="struts-default">
<action name="helloworld" class="cn.itcast.action.HelloWorldAction" method="execute">
<result name="success">/WEB-INF/page/hello.jsp</result>
</action>
</package>
3.2 写action
包cn.itcast.action 类HelloWorldAction,方法 public String execute(), 返回 return "success",返回方法 getXXX();
3.3 写jsp
输出结果 ${XXX} XXX是返回方法getXXX()的名称除了get的字符信息
3.4 发布,访问
http://localhost:8080/项目名称/命名空间/action名
exp:
http://localhost:8080/struts2/test/helloworld
4.action名称的搜索顺序
命名空间分为多级,则从最后一级想最前一级逐次寻找;如果整个命名空间都找不到时去默认命名空间查找。
5.action配置项的默认值
class默认为ActionSupport;method默认为action.execute() result的name属性默认为success
6.action中result的转发类型
dispatcher(默认,内部请求转发) ,redirect (浏览器重定向转发,只能访问WebRoot根目录下的jsp),redirectAction (重定向到action),plainText(显示jsp源码)
中文字符的乱码是因为编码格式不一致导致的,一般使用utf-8
7.为action中的属性注值
<action name="helloworld" class="cn.itcast.action.HelloWorldAction" method="execute">
<param name="属性名称(属性对应set方法的除set字符以外的名称)">要注入的属性值</param>
<result name="success">/WEB-INF/page/hello.jsp</result>
8.指定Struts2处理的请求后缀
默认后缀.action,可以通过常量struts.action.extension进行修改,如:struts.xml 中
<constant name="struts.action.extension" value="do,go,action"/> (联系2中的报错很有可能是这个常量的配置问题)
或者struts.properties 中 struts.action.extension=do
Struts2加载常量的搜索顺序,
struts-default.xml
struts-plugin.xml
struts.xml 建议在该文件中定义常量
struts.properties
web.xml 后一个文件定义的常量会覆盖前一个前一个文件定义的常量
常用常量有:
<constant name="struts.i18n.encoding" value="UTF-8"/> 指定默认编码集
<constant name="struts.action.extension" value="do,go,action"/> 请求后缀
<constant name="struts.serve.static.browserCache" value="false"/> 是否缓存静态内容
<constant name="struts.configuration.xml.reload" value="true"/> 是否重新加载struts文件
9.struts2的处理流程与Action的管理方式
struts2的处理流程:
用户请求--》StrutsPrepareAndExecuteFilter(核心控制器 用户请求的路径不带后缀或者带.action后缀,则将请求转入Struts2框架处理)-->Interceptor(拦截器)-->Action-->Result-->Jsp/html-->响应
系统为每次的用户请求都会创建一个Action,Action是线程安全的。
10.为应用指定多个struts配置文件
配置文件应该按模块划分,一个模块一个配置文件。
在struts.xml中包含(include)其他配置文件:
<struts>
<include file="struts_user.xml"/>
<include file="struts_order.xml"/>
</struts>
11.动态方法调用和使用通配符定义action
动态方法调用: http://localhost:8888/项目名称/包的命名空间/action名!方法名.action
禁止动态方法调用: 常量<constant name="struts.enable.DynamicMethodlnvocation" value="false"/>
使用通配符定义action
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false"/>
<constant name="struts.action.extension" value="do,action"/>
<package name="employee" namespace="/control/employee" extends="struts-default">
<action name="list_*" class="cn.itcast.action.HelloWorldAction" method="{1}">
<result name="success">/WEB-INF/page/message.jsp</result>
</action>
</package>
</struts>
访问路径: http://localhost:8888/项目名称/包的命名空间/action名_方法名.action
12. 接受请求参数
采用基本类型接受请求参数(get/post)
在action类中定义与请求参数同名的属性,struts2便能够自动接收请求参数并赋给同名属性。
可以通过请求路径: http://localhost:8888/项目名称/包的命名空间/action名_方法名.action?id=id000&name=namexxx
在action类中定义属性id\name,及id/name的get/set方法,struts2通过反射技术调用与请求参数同名的属性的set方法来获取请求参数值
采用复合类型(类)接受请求参数
struts2通过反射技术调用复合类型(类)的默认构造器(用户在类中不能再定义构造器)创建类的对象,再通过反射技术调用类实例中与请求参数同名的属性的set方法来获取请求参数值
在jsp中通过post方法,可以获取界面上用户维护的信息,jsp代码如下:
<form action="<%=request.getContextPath()%>/control/employee/list_execute.action" method="post">
id:<input type="text" name="person.id"><br/>
name:<input type="text" name="person.name"><br/>
<input type="submit" value="发送"/>
</form>
版本问题:
struts2.1.6接受中文请求参数存在乱码问题(以post方式提交,struts2.1.8已解决该问题),解决方法如下:
新建一个Filter,并放在Struts2的Filter之前,Filter中doFilter()方法代码如下:
public void doFilter(...){
HttpServletRequest req = (HttpServletRequest)request;
req.setCharacterEncoding("UTF-8");
filterchain.doFilter(request,response);
}
13.自定义类型转换器
分为:局部类型转换器(只对某个action中的属性类型起作用)和全局类型转换器(对系统中的该种类型进行转换)。
局部类型转换器:
1.先创建一个局部类型转换器(字符串与日期间的转换)
package cn.itcast.type.converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter;
public class DateTypeConverter extends DefaultTypeConverter {
@Override
public Object convertValue(Map<String, Object> context, Object value, Class toType) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
try {
if(toType == Date.class){//当字符串向Date类型转换时
String[] params = (String[]) value;// request.getParameterValues()
return dateFormat.parse(params[0]);
}else if(toType == String.class){//当Date转换成字符串时
Date date = (Date) value;
return dateFormat.format(date);
}
} catch (ParseException e) {}
return null;
}
}
2.注册局部类型转换器
在Action类所在包下放置ActionClassName-conversion.properties文件,ActionClassName是Action的类名,properties文件中内容如下:
属性名称=类型转换器的全类名
14. 3.注册全局类型转换器
在WEB-INF/classes下(开发阶段在src下)放置xwork-conversion.properties文件,properties文件中内容如下:
待转换的类型=类型转换器的全类名 如: java.util.Date=cn.itcast.conversion.DateConverter
15. 访问或添加request/session/application属性
action中
public String execute(){
ActionContext ctx = ActionContext.getContext();
ctx.getApplication().put("app", "应用范围");//往ServletContext里放入app
ctx.getSession().put("ses", "session范围");//往session里放入ses
ctx.put("req", "request范围");//往request里放入req
ctx.put("names", Arrays.asList("老张", "老黎", "老方"));
return "message";
}
public String rsa() throws Exception{
HttpServletRequest request = ServletActionContext.getRequest();
ServletContext servletContext = ServletActionContext.getServletContext();
request.setAttribute("req", "请求范围属性");
request.getSession().setAttribute("ses", "会话范围属性");
servletContext.setAttribute("app", "应用范围属性");
//HttpServletResponse response = ServletActionContext.getResponse();
return "message";
}
jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> //引入标签库,WEB-INF/lib下加入jstl.jar和standard.jar文件
<body>
${applicationScope.app} <br>
${sessionScope.ses}<br>
${requestScope.req}<br>
==============================<br/>
<c:forEach items="${names}" var="name">
${name }<br/>
</c:forEach>
16. 文件上传
1.在WEB-INF/lib下加入commons-fileupload-1.2.1.jar和commons-io-1.3.2.jar文件
2.把from表的enctype设置为:"multipart/from-data",如下:
<form action="${pageContext.request.contextPath}/control/employee/list_execute.action" enctype="multipart/form-data" method="post">
文件:<input type="file" name="uploadimage">
<input type="submit" value="上传"/>
</form>
3.Action的属性及操作
private File uploadimage;//得到上传的文件
private String uploadimageFileName;//得到文件的名称
private String uploadimageContentType;//得到文件的类型
//get、set方法省略
public String execute() throws Exception{
String realpath = ServletActionContext.getServletContext().getRealPath("/images"); //获取程序文件的目录
System.out.println(realpath);
if(image!=null){
File savefile = new File(new File(realpath), imageFileName); //创建文件,new File(realpath) 应该可以用固定路径"c:/temp"代替
if(!savefile.getParentFile().exists()) savefile.getParentFile().mkdirs();//创建文件目录,例如:C盘下没有temp文件夹时可以创建
FileUtils.copyFile(uploadimage, savefile); //将action类中的临时文件uploadimage复制到磁盘文件中
ActionContext.getContext().put("message", "上传成功"); //提示信息
}
return "success";
}
4.上传文件的大小限制
通过常量<constantname="struts.multipart.maxSize" value='10701096'> //设置为10M,在struts中定义
17.多文件上传
在action 中将变量定义为list或数组类型:
private File[] uploadimage;//得到上传的文件
private String[] uploadimageFileName;//得到文件的名称
用循环操作对文件逐个上传
public String execute() throws Exception{
String realpath = ServletActionContext.getServletContext().getRealPath("/images");
System.out.println(realpath);
if(image!=null){
File savedir = new File(realpath);
if(!savedir.exists()) savedir.mkdirs();
for(int i = 0 ; i<image.length ; i++){
File savefile = new File(savedir, imageFileName[i]);
FileUtils.copyFile(image[i], savefile);
}
ActionContext.getContext().put("message", "上传成功");
}
return "success";
}
jsp中写多个文件上传框,名字保持一致:
<form action="${pageContext.request.contextPath}/control/employee/list_execute.action" enctype="multipart/form-data" method="post">
文件1:<input type="file" name="image"><br/>
文件2:<input type="file" name="image"><br/>
文件3:<input type="file" name="image"><br/>
<input type="submit" value="上传"/>
</form>
18.自定义拦截器
要自定义拦截器需要实现com.opensympony.xwork2.interceptor.Interceptor接口
(听了一遍,不是很懂,随后再听一遍)
《【struts2.1】 第18课》