一.自定义的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:代表一个包,用于管理action ,一个包下不能有同名action
name:包名,在一个项目中不能有同名的包,一个项目中一个模块一个包或者小项目中前后台分别一个包
extents:继承,类似于类的继承,如果一个包继承另一个包,那么会把父包的功能继承下来,(我们写的struts.xml中包必须继承默认包struts-default)
namespace;名称空间,区分不同包的访问路径,默认为”/“
用户访问action路径索索规则:
若输入:http://localhost:8080/项目名称/user/a/b/c/login.action
会先搜索:http://localhost:8080/项目名称/user/a/b/c/login.action若没有
会继续搜索:http://localhost:8080/项目名称/user/a/b/login.action若没有
会搜索:http://localhost:8080/项目名称/user/a/login.action知道找到匹配项
abstract:用于表示当前包是否抽象,若为抽象则不能放入action子标签(若包中不做具体逻辑业务,如只是声明拦截器等那就可以设为抽象包)
-->
<package name="xxx" extends="struts-default" namespace="/name" abstract="true">
<!--
配置action:http://localhost:8080/项目名称/login.action
1.
name:action的名称,用于访问此antion的路径
class:action业务对象的类名(包名+类名),struts2使用反射构造Action对象
method:执行的业务方法,默认为execute
2.result标签的配置
name:视图的标记,在一个action中名称不要重复
type:跳转类型
redirect:重定向
dispatcher:转发
redirectAction:重定向到action
chain:转发到action,可以在不同action中用request共享数据
ServletActionContext.getRequest().setAttribute("","");放入
stream:用于下载文件的时候
文本内容:跳转的页面或者antion
-->
<action name="login" class="com.study.action.LoginAction" >
<result name="success" type="redirect">/index.jsp</result>
</action>
</package>
</struts>
注意:structs.xml中的package各个模块可以分出来放入不同的.xml文件中,只需要在主struts.xml中加入<include file="包名/xxx.xml"></include>
即可(注:若两个package中出现完全相同的action则先导入(include)的先执行)
二.web.xml中配置启动struts2核心过滤器
<filter>
<filter-name>StrutsPrepareAndExecuteFilter</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>StrutsPrepareAndExecuteFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
三.项目启动过程
1)创建核心过滤器对象
2)执行过滤器的init方法依次读取三个xml文件
struts-default:默认配置文件
struts-plugin:插件配置文件(如文件io等)
struts:自己写的业务配置
3)在内存中查询相应的action配置,得到class内容,创建action对象、
5)读取action中的method内容,执行action对象对应的方法
四.struts2中action使用的三种方式
1.直接写public class UserAction{}
不实现任何接口和继承任何类
缺点:没有规则和统一规范,里面的方法随意写
2.实现Action类public class LoginAction implements Action{}
优点:有默认方法execute+一些常用的视图标记
String SUCCESS = "success";
String NONE = "none";
String ERROR = "error";
String INPUT = "input";
input视图可以在页面打印错误信息
例如:使用<%@ taglib prefix="s" uri="/struts-tags" %>
<s:fielderror></s:fielderror>就可以在页面打印错误信息
String LOGIN = "login";
3.(推荐使用)继承ActionSupport类public class UserAction extends ActionSupport{}
优点:默认方法execute+提供了常用的视图标记+数据校验功能
五.action配置中的统配
<!--
一个模块中的一个方法都需要一个action太浪费资源
我们可以使用统配功能(首先约定名称一致):建议使用
*:表示路径统配符。使用统配符的内容 {1}表示匹配第一个*的实际内容
我们也可以使用动态方法调用(六中有动态方法调用的开启,默认开启)
使用方法:用user.action访问时可以直接用user!方法名.action调用方法
缺点:安全性问题,会暴露所有的方法:不建议使用
-->
<action name="user_*" class="com.study.action.UserAction" method="{1}">
<result name="{1}" type="dispatcher">/{1}.jsp</result>
</action>
<!--
多模块使用一个action
约定:第一个*代表模块第二个代表方法
-->
<action name="*_*" class="com.study.action.{1}Action" method="{2}">
<result name="{2}">/{1}/{2}.jsp</result>
</action>
六.常量配置
指定默认编码集,作用于HttpServletRequest的setCharacterEncoding方法 和freemarker 、velocity的输出
<constant name="struts.i18n.encoding" value="UTF-8"/>
自定义后缀修改常量
<constant name="struts.action.extension" value="do"/>
设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭
<constant name="struts.serve.static.browserCache" value="false"/>
当struts的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开
<constant name="struts.configuration.xml.reload" value="true"/>
开发模式下使用,这样可以打印出更详细的错误信息
<constant name="struts.devMode" value="true" />
默认的视图主题
<constant name="struts.ui.theme" value="simple" />
与spring集成时,指定由spring负责action对象的创建
<constant name="struts.objectFactory" value="spring" />
该属性设置Struts 2是否支持动态方法调用,该属性的默认值是true。如果需要关闭动态方法调用,则可设置该属性
为 false
<constant name="struts.enable.DynamicMethodInvocation" value="false"/>
上传文件的大小限制
<constant name="struts.multipart.maxSize" value=“10701096"/>
例子1:
<!--修改default.properties的默认常量--> <!-- 修改action默认后缀名(规则:一个逗号(,)一个规则) 修改前访问login.action 修改后访问login.do --> <constant name="struts.action.extension" value="action,do,"></constant>
七.全局视图配置 和默认配置
1.全局配置
局部的会覆盖全局的配置
<global-results>
<result name="success" type="redirect">/index.jsp</result>
</global-results>
2.默认配置
<!--
默认配置:(全部默认的action,专门用于转发(不能用重定向)到web-inf下的页面)
action中
name:必须填
class:可选 默认为ActionSupport 该类继承于struts-default
method:默认execute
result中
name:可选 默认为success
type:可选 默认为dispatcher
-->
<action name="register">
<result>/WEB-INF/login.jsp</result>
</action>
八.属性注入
模拟文件上传
UploadAction类:
package com.study.action;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.commons.io.FileUtils;
import java.io.File;
/**
* @author: Demon
* @date: 2019/1/26
* @time: 15:36
* Description:模拟文件上传(属性注入)
*/
public class UploadAction extends ActionSupport {
private String path;
public void setPath(String path) {
this.path = path;
}
public String update() throws Exception {
//获取文件
File file = new File("e:/1.jpg");
System.out.println(path);
//文件上传至服务器
FileUtils.copyFile(file, new File(path + "/img"));
return SUCCESS;
}
}
struts.xml文件配置:
<!--属性注入-->
<action name="ioc" class="com.study.action.UploadAction" method="update">
<result name="success">/success.jsp</result>
<!--
属性注入:param
name:UploadAction中setter方法名
-->
<param name="path">e:/img/</param>
</action>
九.数据共享三种方法(struts2提供的域对象的使用)
第一种(若单纯存储数据不推荐,若用到域对象中除了共享数据外的其他方法就必须使用)
ServletActionContext对象:可以在struts2的action中使用域对象
特点:依赖servlet原生的api
HttpServletRequest request= ServletActionContext.getRequest();
第二种(Action对象方法比较少时可以用)
ActionContext对象(拦截器创建的方法):action的上下文对象,提供了操作不同域对象数据的map集合
特点:不依赖servlet原生的api,只能在某个方法中用
ActionContext actionContext=ActionContext.getContext();
//得到request域的map集合
Map<String ,Object> requestMap=actionContext.getContextMap();
requestMap.put("list",list);
//得到session
Map<String ,Object> sessionMap=actionContext.getSession();
sessionMap.put("list",list);
//得到context域
Map<String ,Object> contextMap=actionContext.getApplication();
contextMap.put("list",list);
第三种(推荐使用)
通过struts提供的接口(RequestAware,SessionAware,ApplicationAware )注入到Action中
特点:不依赖servlet原生的api,可以在Action类中的所有方法中共享
public class Test extends ActionSupport implements RequestAware,SessionAware,ApplicationAware {
private Map<String, Object> contextMap;
private Map<String, Object> requestMap;
private Map<String, Object> sessionMap;
@Override
public void setApplication(Map<String, Object> map) {
this.contextMap = map;
}
@Override
public void setRequest(Map<String, Object> map) {
this.requestMap = map;
}
@Override
public void setSession(Map<String, Object> map) {
this.requestMap = map;
}
//放数据
public String test() {
contextMap.put("list", list);
requestMap.put("list", list);
sessionMap.put("list", list);
return null;
}
}
十.请求数据封装
实现原理是依靠struts-default.xml中的拦截器(类似于过滤器,拦截器只对antion起作用)实现的,其中<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
实现请求参数的封装
第一种方式:直接赋值给简单的参数
代码示例
页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/data/user_get.action">
名字:<input type="text" name="username"/><br/>
密码:<input type="password" name="password"/><br/>
性别:<input type="radio" name="sex" value="男"/>男
<input type="radio" name="sex" value="女"/>女
爱好:<input type="checkbox" name="hobby" value="抽烟">抽烟
<input type="checkbox" name="hobby" value="喝酒">喝酒
<input type="checkbox" name="hobby" value="烫头">烫头<br/>
<input type="submit" value="提交"/>
</form>
</body>
</html>
接收类UserAction:
public class UserAction extends ActionSupport{
private String userName;
private String password;
private String sex;
private String[] hobby;
public void setUserName(String userName) {
this.userName = userName;
}
public void setPassword(String password) {
this.password = password;
}
public void setSex(String sex) {
this.sex = sex;
}
public void setHobby(String[] hobby) {
this.hobby = hobby;
}
public String get(){
System.out.println(userName);
System.out.println(password);
System.out.println(sex);
System.out.println(hobby);
return SUCCESS;
}
}
第二种方式:直接赋值给javabean对象
注意:这里需要在表单jsp页面提交时name属性应该为对象名.属性的getter方法名
代码示例
页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/data/user_get.action">
名字:<input type="text" name="user.userName"/><br/>
密码:<input type="password" name="user.password"/><br/>
性别:<input type="radio" name="user.sex" value="男"/>男
<input type="radio" name="user.sex" value="女"/>女
爱好:<input type="checkbox" name="user.hobby" value="抽烟">抽烟
<input type="checkbox" name="user.hobby" value="喝酒">喝酒
<input type="checkbox" name="user.hobby" value="烫头">烫头<br/>
<input type="submit" value="提交"/>
</form>
</body>
</html>
接收类UserAction:
package com.study.data;
import com.opensymphony.xwork2.ActionSupport;
import com.study.bean.User;
/**
* @author: Demon
* @date: 2019/1/26
* @time: 17:13
* Description:
*/
public class UserAction extends ActionSupport{
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String get(){
System.out.println(user);
return SUCCESS;
}
javabean:User类这里略
十一.自定义类型转换继承StrutsTypeConverter
自定义日期的类型转换
MyDateConverter:类
package com.study.converter;
import org.apache.struts2.util.StrutsTypeConverter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
/**
* @author: Demon
* @date: 2019/1/26
* @time: 19:53
* Description:自定义日期转换器
*/
public class MyDateConverter extends StrutsTypeConverter{
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy/MM/dd");
/**
*从页面到服务器的类型转换
* map:值栈上下文对象
* strings:从页面传递过来的参数值
* aClass:转换到的类型 String-》java.util.Date
*/
@Override
public Object convertFromString(Map map, String[] strings, Class aClass) {
try {
//判断values是否为空
if(strings==null||strings.length==0){
return null;
}
Date[] dates=new Date[strings.length];
//取出数据进行转换
for(int i=0;i<dates.length;i++){
Date date=simpleDateFormat.parse(strings[i]);
dates[i]=date;
}
return dates;
} catch (ParseException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
@Override
public String convertToString(Map map, Object o) {
return null;
}
}
与struts2绑定才能使用:
1)方式一:局部绑定(只能绑定一个)
建立一个Action的文件名-conversion.properties
一定和绑定的Action放在同一个目录下
例如:
UserAction-conversion.properties与UserAction在同一目录下
properties中写user.birth对应自己定义的转换器(如:MyDateConverter )的全名(包名+类名)
2)方式二:全局绑定(绑定整个项目的action)
建立一个xwork-conversion.properties(名称不能改)
放在src目录下
例如:
properties写java.util.Date对应自己定义的转换器(如:MyDateConverter )的全名(包名+类名)
抗遗忘最好的方法就是记下来
未完待续。。。。。。。