在此处我将记录一些我学习struts2时总结的要点,分章节与学习进度保持同步,与君共勉。
注:视频学习资料来自北京尚学堂培训公司-马士兵所有。
开发环境:IDE为IDEA 2016.2.5,JDK1.8,struts版本为2.1.6,Tomcat为7.0.75
学习资料下载:点我下载(涵盖源码+视频)
=============================================================
如何使用struts2
1.将7个jar包导入到项目lib中去,IDEA需在WEB-INFO文件夹下新建文件夹lib,导入jar包,右键文件夹--add as librery--完成
2.编写web.xml配置文件,将以下代码插入至<web-app>标签中
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3.导入struts.xml配置文件至项目src根目录
4.创建JavaAction类进行操作
=====================================================================
命名空间
namespace决定了action的访问路径,也就是namespace里面写了什么,你的请求地址栏里就必须要包括什么。
namespace默认为“”,可以接收到所有路径的action,可以写为/,/xxx,/xxx/yyy 对应的访问路径就应该为/xxx/xxx.action,/xxx/yyy/xxx.action
namespace最好用模块来命名。
如下代码:
<constant name="struts.devMode" value="true" />
<package name="login" namespace="/login" extends="struts-default">
<action name="login">
<result>/login_success.jsp</result>
</action>
</package>
constant name="struts.devMode" value="true" 为调试模式开启(IDEA无法调用此功能,调试须重新部署)
package *name*属性用来区分重名的情况。
=====================================================================
Action
struts.xml内代码如下:
<package name="path" namespace="/path" extends="struts-default">
<action name="path" class="test.example">
<result name="success">
/path.jsp
</result>
</action>
</package>
action标签里的class值为你在src目录创建的JavaAction类的路径
Action操作类我用继承了一个ActionSupport类,类里包含了一些预设好了的对象和属性供开发者利用,后续struts2的Action类也都将继承此类。
在此处我重载了ActionSupport里的execute()方法,返回了一个值为“success”的String对象。
execute()为默认执行的方法,即在上面的配置文件里的action标签内,你不声明method属性时默认执行的方法。
example.java代码如下:
package test;
import com.opensymphony.xwork2.ActionSupport;
/**
* Created by Alex on 2017/5/8.
*/
public class example extends ActionSupport{
@Override
public String execute(){
return "success";//result默认值为success
}
}
这个action类返回一个“success”的String至struts.xml,里面的result标签负责接收这个值,其中name属性为结果值,默认为"success"
也就是说 若返回值为success,那么result标签内就不用再写name属性。
另外一种action类的的写法,此方法为主流方法,可以自定义方法名来进行开发操作,而不仅仅局限与execute()这一种方法。
另外返回值我们利用了SUCCESS这一在父类ActionSupport中接口Action中的变量值,
可看到struts2的源码中为我们内置了这些变量值:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.opensymphony.xwork2;
public interface Action {
String SUCCESS = "success";
String NONE = "none";
String ERROR = "error";
String INPUT = "input";
String LOGIN = "login";
String execute() throws Exception;
}
Action代码如下:
package action;
import com.opensymphony.xwork2.ActionSupport;
/**
* Created by Alex on 2017/5/9.
*/
public class CourseAction extends ActionSupport {
public String add(){
return SUCCESS; //接口包含变量
}
public String delete(){
return SUCCESS;
}
}
可以看到此处我们不在重载execute方法,而是选择自定义命名的方法,那么在struts.xml里面我们应该如何接受返回值?
请看
<package name="actions" namespace="/actions" extends="struts-default">
<action name="course" class="action.CourseAction" method="add">
<result>
/User_add_success.jsp
</result>
</action>
<action name="course" class="action.CourseAction" method="delete">
<result>
/User_delete_success.jsp
</result>
</action>
</package>
可以看到,在此处action标签内我们编写了一个method属性,里面的值就是我们action类里自定义方法的名称
这样一来,我们就可以通过这种方法来调用自定义的方法了。
=====================================================================
通配符
上面的代码大家有没有觉得很冗余,其实我们可以精简一点通配符的运用:
struts.xml
<package name="actions" namespace="/actions" extends="struts-default">
<action name="*_*" class="action.{1}Action" method="{2}" >
<result>
/{1}_{2}_success.jsp
</result>
</action>
</package>
可以看到action的name值变为了*_*, 这些*就代表了我们要传(要变)的参数,可以为add,可以为delete等等,后面的{1}{2}分别代表了第一个*所代表的值与第二个*所代表的值,依次代入,就可以实现动态接受与判断数据了。
配置代码是不是精简了很多?但是需要遵循约定优于配置这个原则
对应action类与jsp页面
=====================================================================
用Action的属性接收参数
package action;
import com.opensymphony.xwork2.ActionSupport;
/**
* Created by Alex on 2017/5/9.
*/
public class UserAction extends ActionSupport{
private String name;
private int age;
public String add(){
System.out.println("name:"+name);
System.out.println("age:"+age);
return SUCCESS;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
可以看到这种方式可以接收到页面传递过来的参数值,并进行处理。 但是这种传参模式有缺点,就是如果变量过多,会导致代码异常冗余
用DomainModel接受参数
package bean;
/**
* Created by Alex on 2017/5/9.
*/
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package action;
import bean.User;
import com.opensymphony.xwork2.ActionSupport;
/**
* Created by Alex on 2017/5/9.
*/
public class UserAction2 extends ActionSupport{
private User user; //实例化User实体类
public String add(){
System.out.println("username:"+user.getName());
System.out.println("username:"+user.getAge());
return SUCCESS;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
这种方式我们称之为 DomainModel 预模型
DTO(VO\DO)
用ModelDriven接收参数
package action;
import bean.User;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
/**
* Created by Alex on 2017/5/11.
*/
public class UserAction3 extends ActionSupport implements ModelDriven<User>{
private User user = new User();
public String add(){
System.out.println("name"+user.getName());
System.out.println("name"+user.getAge());
return SUCCESS;
}
@Override
public User getModel(){
return user;
}
}
2.1.6版本的中文问题
<constand name=“struts.i18n.encoding" value="utf-8" />
若版本在2.1.7以下,则可用过滤器的方式来进行转码
package filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* Created by Alex on 2017/5/11.
*/
@WebFilter(filterName = "EncodingFilter")
public class EncodingFilter implements Filter {
public void destroy() {
}//过滤器销毁
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
}//过滤器初始化
}
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
更改为:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URLEncoding="utf-8" />
即可修复中文输入乱码问题
简单的数据验证
<package name="actions" namespace="/actions" extends="struts-default">
<action name="user2" class="action.UserAction2">
<result> /User_add_success.jsp </result>
<result name="error">/user_add_error.jsp</result>
</action>
</package>
此处有两个result代表了两种处理情况,成功与失败
package action;
import com.opensymphony.xwork2.ActionSupport;
/**
* Created by Alex on 2017/5/11.
*/
public class LoginAction extends ActionSupport {
private String name;
public String add(){
if(name==null || !name.equals("fjnmbb12")){
this.addFieldError("name","name is error");
return ERROR;
}
return SUCCESS;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
可以看到这里add()内有两种情况,返回了不同的结果。其中发生错误的结果内有一个addFieldError方法,此方法将会发送错误的原因至前端页面。
<%--
Created by IntelliJ IDEA.
User: Alex
Date: 2017/5/11
Time: 22:32
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<title>Title</title>
</head>
<body>
用户添加异常!
<s:fielderror fieldName="name" theme="simple" /> <br/>
<s:property value="errors.name[0]"/> <br/>
<s:debug></s:debug>
</body>
</html>
在前端页面我们引用了struts 的标签,首先在顶部插入引用语,
访问Web元素
<%--
Created by IntelliJ IDEA.
User: Alex
Date: 2017/5/10
Time: 16:43
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<base href="http://localhost:8080/">
<title>$Title$</title>
</head>
<body>
<form action="" id="f" name="f" method="post">
<input type="text" name="name" placeholder="输入用户名" /><br />
<input type="password" name="password" placeholder="输入密码" /> <br />
<input type="button" value="提交1" οnclick="javascript:document.f.action='login/login1';document.f.submit();" />
<input type="button" value="提交2" οnclick="javascript:document.f.action='login/login2';document.f.submit();" />
<input type="button" value="提交3" οnclick="javascript:document.f.action='login/login3';document.f.submit();" />
<input type="button" value="提交4" οnclick="javascript:document.f.action='login/login4';document.f.submit();" />
</form>
</body>
</html>
<package name="login" namespace="/login" extends="struts-default">
<action name="login*" class="action.LoginAction{1}">
<result>/login_success.jsp</result>
</action>
</package>
package action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import javax.net.ssl.SSLSessionContext;
import java.util.Map;
/**
* Created by Alex on 2017/5/10.
*/
public class LoginAction1 extends ActionSupport{
private Map request;//声明类型为Map的request变量
private Map session;//声明类型为Map的session变量
private Map application;//声明类型为Map的application变量
public LoginAction1(){
//调用ActionSupport内的方法对三大对象进行取值
request = (Map)ActionContext.getContext().get("request");
session=ActionContext.getContext().getSession();
application = ActionContext.getContext().getApplication();
}
@Override
public String execute(){
request.put("r1","r1");
session.put("s1","s1");
application.put("a1","a1");
return SUCCESS;
}
}
package action;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.interceptor.ApplicationAware;
import org.apache.struts2.interceptor.RequestAware;
import org.apache.struts2.interceptor.SessionAware;
import java.util.Map;
/**
* Created by Alex on 2017/5/10.
*/
public class LoginAction2 extends ActionSupport implements RequestAware,SessionAware,ApplicationAware{
private Map<String,Object> request;
private Map<String,Object> session;
private Map<String,Object> application;
public String execute(){
request.put("r1","r2");
session.put("s1","s2");
application.put("a1","a2");
return SUCCESS;
}
@Override
public void setRequest(Map<String, Object> request) {
this.request = request;
}
@Override
public void setSession(Map<String, Object> session) {
this.session = session;
}
@Override
public void setApplication(Map<String, Object> application) {
this.application = application;
}
}
Action总结
- 实现一个Action的最常用的方式:从ActionSupport继承
- DMI动态方法调用 !xxx
- 通配符配置 * {1} {2}
- *_*
- 接收参数的方法(一般用属性和DomainModel来接收)
- 简单的数据验证 addFieldError
- 一般不使用struts2的ui标签
- 访问WEB元素
- Map类型(1、IoC 2、依赖struts2)
- 原始类型 (1、IoC 2、依赖struts2)
- 包含文件配置(include标签)
- 默认action处理
结果类型
- dispatcher
- redirect
- chain
- redirectAction
<package name="resultTypes" namespace="/r" extends="struts-default">
<action name="r1">
<result type="dispatcher"> /r1.jsp </result>
</action>
<action name="r2">
<result type="redirect">/r2.jsp</result>
</action>
<action name="r3">
<result type="chain">r1</result>
</action>
<action name="r4">
<result type="redirectAction">r2</result>
</action>
</package>
我写了4个Action,每一个Action都对应了一个结果类型
http://localhost:8080/r/r1
http://localhost:8080/r2.jsp
<action name="r3">
<result type="chain">
<param name="actionName">actionName</param>
<param name="/namespace">namespace</param>
</result>
</action>
全局结果集
定义一个可以共用的结果集,配置如下: <package name="user" namespace="/user" extends="struts-default">
<global-results>
<result name="mainpage">/main.jsp</result>
</global-results>
<action name="user" class="action.userAction">
<result> /user_success.jsp </result>
<result name="error">/user_error.jsp</result>
</action>
</package>
Action代码:
package action;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.inject.Scope;
/**
* Created by Alex on 2017/5/15.
*/
public class userAction extends ActionSupport {
private int type;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
@Override
public String execute() throws Exception{
if(type==1)return SUCCESS;
else if(type == 2) return ERROR;
else return "mainpage";
}
}
那么只要是返回值为mainpage时,都会跳转至:main.jsp页面
<package name="admin" namespace="/admin" extends="user">
<action name="admin" class="action.adminAction">
<result>/admin.jsp</result>
</action>
</package>
Action代码如下:
package action;
import com.opensymphony.xwork2.ActionSupport;
/**
* Created by Alex on 2017/5/15.
*/
public class adminAction extends ActionSupport {
@Override
public String execute(){
return "mainpage";
}
}
这样配置,使得我们新包继承了原来的包的全局结果集,所以可以使用该结果集。
动态结果集
使用特殊标志来动态接受结果集 <constant name="struts.devMode" value="true" />
<package name="user" namespace="/user" extends="struts-default">
<action name="user" class="action.userAction">
<result>${r}</result>
</action>
</package>
可以看到我们的result标签内跳转的页面名改为了${r}的形式,为何使用这种结构呢?
package action;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.inject.Scope;
/**
* Created by Alex on 2017/5/15.
*/
public class userAction extends ActionSupport {
private String r;
private int type;
public String getR() {
return r;
}
public void setR(String r) {
this.r = r;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
@Override
public String execute() throws Exception{
if(type==1)r="/user_success.jsp";
else if(type==2)r="/user_error.jsp";
return SUCCESS;
}
}
可以看到我们action代码里,定义了两个变量,生成了2个get and set方法,他们分别为type和r
带参数的结果集
<package name="user" namespace="/user" extends="struts-default">
<action name="user" class="action.userAction">
<result type="redirect"> /user_success.jsp?t=${type}</result>
</action>
</package>
可以看到在result内,我们传过来的参数使用了ONGL表达式来接收
<%--
Created by IntelliJ IDEA.
User: Alex
Date: 2017/5/15
Time: 22:05
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>user success</title>
</head>
<body>
user success!! <br/>
from valueStack:<s:property value="r" /><br/>
from actionContext: <s:property value="#parameters.t"/>
<s:debug></s:debug>
</body>
</html>
效果如图
<s:property value="t" />
并不能取到值,而用
<s:property value="#parameters.t"/>
结果集(result)总结
- 常用的四中类型:
- dispatcher(默认)
- redirect
- chain
- redirecAction
- 全局结果集
- global-results || extends(继承另外一个包的结果集)
- 动态结果(了解即可)
- 在action中保存一个属性,储存具体的结果location
- 传递参数
- 客户端跳转才需要传递
- ${}(ONGL表达式 不是EL表达式) 从valueStack取值
OGNL
<%--
Created by IntelliJ IDEA.
User: Alex
Date: 2017/5/16
Time: 18:00
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首页</title>
</head>
<body>
访问属性:<br/>
<a href="ognl.action?username=alex&password=123">ognl</a>
</body>
</html>
<%--
Created by IntelliJ IDEA.
User: Alex
Date: 2017/5/16
Time: 18:01
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>OGNL表达式语言学习</title>
</head>
<body>
<ol>
在此插入例子
</ol>
<s:debug></s:debug>
</body>
</html>
<?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>
<constant name="struts.enable.DynamicMethodInvocation" value="false"/>
<constant name="struts.devMode" value="true" />
<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
<include file="/ognl/ognl.xml" />
</struts>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
"http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
<package name="ognl" extends="struts-default">
<action name="ognl" class="ognl.ognlAction" >
<result>/OGNL.jsp</result>
</action>
</package>
</struts>
- ognlAction.java:
package ognl; import com.opensymphony.xwork2.ActionSupport; import java.util.*; /** * Created by Alex on 2017/5/16. */ public class ognlAction extends ActionSupport { private String username; private String password; private User user; private Cat cat; private List<User> users = new ArrayList<User>(); private Set<Dog> dogs = new HashSet<Dog>(); private Map<String,Dog> dogMap = new HashMap<String , Dog>(); public Cat getCat() { return cat; } public void setCat(Cat cat) { this.cat = cat; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } public ognlAction() { users.add(new User(1)); users.add(new User(2)); users.add(new User(3)); dogs.add(new Dog("dog1")); dogs.add(new Dog("dog2")); dogs.add(new Dog("dog3")); dogMap.put("dog100",new Dog("dog100")); dogMap.put("dog101",new Dog("dog101")); dogMap.put("dog102",new Dog("dog102")); } public List<User> getUsers() { return users; } public void setUsers(List<User> users) { this.users = users; } public Set<Dog> getDogs() { return dogs; } public void setDogs(Set<Dog> dogs) { this.dogs = dogs; } public Map<String, Dog> getDogMap() { return dogMap; } public void setDogMap(Map<String, Dog> dogMap) { this.dogMap = dogMap; } @Override public String execute(){ return SUCCESS; } 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; } public String m(){ return "hello!"; } }
- User.java:
package ognl; /** * Created by Alex on 2017/5/16. */ public class User { private int age = 8; public User(){ } public User(int age){ super(); this.age=age; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User:" +age ; } }
- Cat.java:
package ognl; /** * Created by Alex on 2017/5/16. */ public class Cat { private Dog friend; public Dog getFriend() { return friend; } public void setFriend(Dog friend) { this.friend = friend; } public String miaomiao(){ return "miaomiao~"; } }
- Dog.java:
package ognl; /** * Created by Alex on 2017/5/16. */ public class Dog { private String name; public Dog(){} public Dog(String name){ super(); this.name = name; }; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Dog:" + name; } }
- S.java:
package ognl; /** * Created by Alex on 2017/5/16. */ public class S { public static String STR="static string"; public static String s(){ return "static method"; } }
- OGNL全称 Object Gragh Navigation Language,对象图导航语言
- 1.user.xxx 只有传,才会构造(在页面内只有传了参数进去,值栈里面才会有值) 当然可以直接new对象出来,默认变量值,效果一样(domain model)。但是需要保持一个无参构造方法
<li>访问值栈中的Action的普通属性:username = <s:property value="username"/> </li>
<li>访问值栈中的对象的普通属性(get set方法) :<s:property value="user.age"/></li>
<li>访问值栈中的对象的普通属性(get set方法): <s:property value="cat.friend.name" /></li>
<li>访问值栈中的对象的普通方法: <s:property value="password.length()" /></li>
<li>访问值栈中的对象的普通方法: <s:property value="cat.miaomiao()" /></li>
<li>访问值栈中的action的普通方法: <s:property value="m()" /></li>
如何访问静态属性与方法:
<li>访问静态方法: <s:property value="@ognl.S@s()" /></li>
<li>访问静态属性: <s:property value="@ognl.S@STR" /></li>
<li>访问Math类的静态方法: <s:property value="@@max(2,3)" /></li>
P.S: 第三种方法不常用。
<li>访问普通类的构造方法: <s:property value="new ognl.User(8)" /></li>
P.S:在此处可以直接在value属性里new对象出来
<li>访问List: <s:property value="users" /></li>
<li>访问List中的某个元素: <s:property value="users[1]" /></li>
<li>访问List中的某个元素集合: <s:property value="users.{age}" /></li>
<li>访问List中的某个元素集合中的特定值:<s:property value="users[0].age" /> (最常用) || <s:property value="users.{age}[0]" /> </li>
<li>访问Set: <s:property value="dogs" /></li>
<li>访问Set中的某个元素: <s:property value="dogs[1]" /></li>
<li>访问Map: <s:property value="dogMap" /></li>
<li>访问Map中的某个元素: <s:property value="dogMap.dog101" /> || <s:property value="dogMap['dog101']"/> | <s:property value="dogMap[\"dog101\"]" /> </li>
<li>访问Map中的所有key: <s:property value="dogMap.keys" /></li>
<li>访问Map中的所有value: <s:property value="dogMap.values" /></li>
<li>访问Map容器的大小: <s:property value="dogMap.size()" /></li>
<li>访问Set容器的大小: <s:property value="dogs.size()" /></li>
<li>访问List容器的大小: <s:property value="users.size()" /></li>
<li>投影(过滤):<s:property value="users.{?#this.age==1}.{age}" /></li>
<li>投影:<s:property value="users.{^#this.age>1}.{age}" /></li>
<li>投影:<s:property value="users.{$#this.age>1}.{age}" /></li>
<li>投影:<s:property value="users.{$#this.age>1}.{age} == null" /></li>
P.S: ^为开头第一个,$为最后一个,而加判断式 == 输出true or false
struts标签
- 通用标签:
- property
- set (默认为action scope 会将值放入request 和 ActionContext中 ; page,request,session,application)
- bean
- include(对中文文件有支持问题,不建议使用,如需包含,改用jsp包含)
- param
- debug
- 控制标签
- if、elseif、 else
- iterator(collections map enumeration iterator array,循环遍历)
- subset(截取集合一部分)
- UI标签
- theme(simple xhtml:默认 、 css xhtml、 ajax )
- AJAX标签
- 再补充
- $ # %的区别
- $用于 i18n 和 struts配置文件
- #取得ActionContext的值
- %将原本的文本属性解析为ognl,对于本来就是ongl的属性不起作用(参考<s:property>和<s:include>)
<%--
Created by IntelliJ IDEA.
User: Alex
Date: 2017/5/16
Time: 23:15
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首页</title>
</head>
<body>
访问属性:<br/>
<a href="tags.action?username=alex&password=123">tags</a>
</body>
</html>
在此处我们传了两个参数(username和password)至struts.xml
<%--
Created by IntelliJ IDEA.
User: Alex
Date: 2017/5/17
Time: 5:21
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<ol>
在此处写例子
</ol>
</body>
</html>
<?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>
<constant name="struts.devMode" value="true" />
<package name="tags" extends="struts-default">
<action name="tags" class="tags.tagsAction">
<result>/tags.jsp</result>
</action>
</package>
</struts>
package tags;
import com.opensymphony.xwork2.ActionSupport;
/**
* Created by Alex on 2017/5/17.
*/
public class tagsAction extends ActionSupport {
private String username;
private String password;
public tagsAction(){
}
@Override
public String execute(){
this.addFieldError("fieldError.test","wrong!");
return SUCCESS;
}
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;
}
}
struts标签的property标签
<li>property: <s:property value="username" /> </li>
<li>property 取值为字符串: <s:property value="'username'" /> </li>
<li>property 设定默认值: <s:property value="admin" default="管理员" /> </li>
<li>property 设定HTML: <s:property value="'<hr/>'" escape="false" /> </li>
<li>set 设定adminName值(默认为request和ActionContext):<s:set var="adminName" value="username" /> var adminName = username</li>
<li>set 从request里取值 :<s:property value="#request.adminName" /></li>
<li>set 从ActionContext里取值 :<s:property value="#adminName" /></li>
<%--<li>set 设定范围:<s:set name="adminPassword" value="password" scope="page" /> name adminPassword = password (page) </li>--%>
<%--<li>set 从相应的范围取值:<%=pageContext.getAttribute("adminPassword")%></li>--%>
<li>set 设定var 范围为ActionContext: <s:set name="adminPassword" value="password" var="a"/> var a = password(废弃) </li>
<li>set 使用#取值: <s:property value="#a" /> </li>
<li>set 设定var 范围为Session: <s:set var="adminPassword" value="password" scope="session"/> var adminPassword = password(主流) </li>
<li>set 从相应的范围取值: <s:property value="#session.adminPassword" /> </li>
<li>
bean 定义bean,并使用param来设定新的属性值:
<s:bean name="tags.Dog" var="myDog">
<s:param name="name" value="'linda'"></s:param>
</s:bean>
</li>
<li>bean 取值:<s:property value="#myDog.name" /> </li>
<li>bean 查看debug:<s:debug></s:debug></li>
P.S:param子标签内部的value值我们若需要插入字符串格式,那么需要在里面加上单引号,若是需要插入OGNL表达式,则不需要单引号。
struts标签的include标签
官方文档:
页面内容:
<li>
include _include1.html 包含静态英文文件:
<s:include value="_include1.html" ></s:include>
</li>
<li>
include _include1.html 包含静态中文文件:
<s:include value="_include2.html" ></s:include>
</li>
<li>
include _include1.html 包含静态中文文件,说明%的用法:
<s:set var="incPage" value="'/_include2.html'" />
<s:include value="%{#incPage}" ></s:include>
</li>
<li>
fieldError simple:<s:fielderror fieldName="fieldError.test" theme="simple"></s:fielderror>
</li>
P.S:此标签有默认样式(ul li标签)若需要去除标签样式,请转至本博客另一篇《去除struts2中s:fieldError标签中的默认样式》中查阅 <li>
if elseif 和 else:
age = <s:property value="#parameters.age" /><br/>
<s:if test="#parameters.age[0] < 0">wrong age!</s:if>
<s:elseif test="#parameters.age[0] <= 20" >too young!</s:elseif>
<s:else>这才对嘛</s:else>
<s:if test="#parameters.aaa == null">null</s:if>
</li>
简单easy,通俗易懂
<li>
遍历集合:<br/>
<s:iterator value="{1,2,3}">
<s:property /> |
</s:iterator>
</li>
<li>
自定义变量:<br/>
<s:iterator value="{'aaa','bbb','ccc'}" var="x" >
<s:property value="#x.toUpperCase()" /> |
</s:iterator>
</li>
<li>
使用struts:<br/>
<hr/>
<s:iterator value="{'aaa','bbb','ccc'}" status="status">
元素值:<s:property/> <br/>
遍历过的元素总数:<s:property value="#status.count" /> <br/>
遍历过的元素索引:<s:property value="#status.index" /> <br/>
当前是偶数? <s:property value="#status.even"/><br/>
当前是奇数? <s:property value="#status.odd"/><br/>
是第一个元素吗? <s:property value="#status.first" /><br/>
是最后一个元素吗? <s:property value="#status.last" /> <br/>
<hr/>
</s:iterator>
</li>
<li>
遍历Map:<br/>
<s:iterator value="#{1:'a',2:'b',3:'c'}">
<s:property value="key" /> | <s:property value="value"/> <br/>
</s:iterator>
</li>
P.S:在遍历Map时,需要在value里加入#符。
<s:subset source="myList" count="13" start="3">
<s:iterator>
<s:property />
</s:iterator>
</s:subset>
P.S:截取部分集合内容,了解即可,过多不再阐述
- 把所有的主体定义为simple
- fieldError特殊化处理
- 自己控制其他标签的展现
BBS项目
- 原则:能简单就别复杂,简单就是美;
- 库名:项目名
- 表的命名:_Model名
- 字段命名:保持与属性名一致(尽量不要与数据库命名冲突)
- 用层来划分包:*.*.action: userAction studentAction *.*.model(bean): User,Student. *.*.service(dao):userDAO,StudentDAO
- Action的命名:模块名+Action 驼峰命名规则
- JSP的命名:*-*
- package的命名:action adminAction
2.建立struts.xml
a).确定namespace
b).确定package
c).确定Action的名称
d).确定result
e).将界面原型页面进行修改,匹配现有配置
f).测试
声明式异常处理
- 在Action中进行异常映射
- 在package中进行全局异常映射
- 使用继承共用异常映射
- struts2中异常处理由拦截器实现(观察struts-default.xml) 实际上struts2的大多数功能都由拦截器实现
I18N
拦截器
类型转换
<%--
Created by IntelliJ IDEA.
User: Alex
Date: 2017/5/24
Time: 23:07
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>类型转换测试</title>
</head>
<body>
name:<s:property value="name" /> <br/>
age: <s:property value="age" />
</body>
</html>
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 name="test" namespace="/" extends="struts-default">
<action name="test" class="com.alex.action.testAction">
<result>/test.jsp</result>
</action>
</package>
</struts>
testAction.java:
package com.alex.action;
import com.opensymphony.xwork2.ActionSupport;
/**
* Created by Alex on 2017/5/24.
*/
public class testAction extends ActionSupport {
private String name;
private int age;
@Override
public String execute() throws Exception{
return super.execute();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
非常简单的一个环境,运行后是这样子的:
package com.alex.action;
import com.opensymphony.xwork2.ActionSupport;
import java.util.Date;
/**
* Created by Alex on 2017/5/24.
*/
public class testAction extends ActionSupport {
private String name;
private int age;
private Date d;
public Date getD() {
return d;
}
public void setD(Date d) {
this.d = d;
}
@Override
public String execute() throws Exception{
return super.execute();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
在前端使用<s:date>标签对日期类型进行转换,
<%--
Created by IntelliJ IDEA.
User: Alex
Date: 2017/5/24
Time: 23:07
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>类型转换测试</title>
</head>
<body>
name:<s:property value="name" /> <br/>
age: <s:property value="age" /><br/>
date: <s:property value="d"/><br/>
<s:date format="yyyy/MM/dd HH:mm:ss" name="d" />
</body>
</html>
可以看到如下效果: