愿望总是很美好,给自己罗列的计划总想着能完成,但是执行起来总是大打折扣。。。
第三天才要把action这块结束了,效率真的很慢,希望这么慢的效率能有好的成长。
ModelDriven接口实现参数输入:
定义一个UserAction它继承于ActionSupport 实现了ModelDriven接口
public class UserAction extends ActionSupport implements ModelDriven<User>{
private User user = new User();
public String add(){
System.out.println("name = " + user.getName());
System.out.println("age = " + user.getAge());
return SUCCESS;
}
@Override
public User getModel() {
return user;
}
}
ModelDriven接口只有一个方法是getModel()方法,需要再定义一个vo包把属性和方法分开,通过得到对象的引用来得到那些属性
User类中:
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;
}
}
一般这种方式不常用,但是这种设计理念一定要掌握
简单的数据验证:
新建一个UserAction类
public class UserAction extends ActionSupport {
private String name;
public String add(){
if(name == null || !name.equals("admin")) {
this.addFieldError("name", "name is error");
this.addFieldError("name", "name is too long");
System.out.println(name);
return ERROR;
}
return SUCCESS;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
这个类中调用了一个this.addFieldError()方法,这个方法是struts2中的方法,这个方法会返回一个数据信息,但是前台如何才能接受到错误的信息呢?这个时候就需要用到ognl表达式标签了,首先先开struts.xml的配置:
result结果是error的话会定位到 User_Add_error.jsp页面:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>insert title here</title>
</head>
<body>
User Add Error
<s:fielderror fieldName="name" theme="simple" /><%-- 默认为simple --%>
<br/>
<s:property value="errors.name[0]"/>
<s:debug></s:debug>
</body>
</html>
ognl表达式使用前需要先引用一下
<%@taglib uri="/struts-tags" prefix="s" %>
<s:fielderror fieldName="name"> 能够接受到
this.addFieldError
传递的name值。<s:property>标签是访问值栈对象的普通属性的,
值栈可以通过<s:debug>标签显示出:
我们可以看见errors 是一个map值,map 对应的key 和 value ,而value是一个数组(或者说是集合,通过看源码可以判定)。
通过给前台传递错误信息这种方式比较恶心,它的格式是固定的,这样就让程序员很头疼。。。
下面来说一个比较关键的:
通过web访问元素:
首先定义一个LoginAction1:
public class LoginAction1 extends ActionSupport{
private Map request;
private Map session;
private Map application;
public LoginAction1() {
request = (Map)ActionContext.getContext().get("request");
session = ActionContext.getContext().getSession();
application = ActionContext.getContext().getApplication();
}
public String execute() {
request.put("r1", "r1");
session.put("s1", "s1");
application.put("a1", "a1");
return SUCCESS;
}
}
这种方式用的比较少,它通过手动调用的方式来获取request、session和application ,
ActionContext是什么,以及ognl表达式如何 见博客 http://blog.csdn.net/super_yc/article/details/61629522
再看struts.xml中的配置:
index.jsp中的配置:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<% String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path;
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Action页面</title>
</head>
<body>
取得request,session,application,HttpServletRequest,HttpServletSession,ServletContext的引用
<ol>
<li>前三者:依赖于容器</li>
<li>前三者:IoC</li>
<li>后三者:依赖于容器</li>
<li>后三者:依赖于IoC</li>
</ol>
<br>
<form name="f" action="" method="post">
用户名: <input type="text" name="name"><br/>
密码:<input type="password" name="password"><br/>
<input type="button" value="submit1" onclick="javascript:document.f.action='login/login1';document.f.submit()" /><br/>
<input type="button" value="submit2" onclick="javascript:document.f.action='login/login2';document.f.submit()" /><br/>
<input type="button" value="submit3" onclick="javascript:document.f.action='login/login3';document.f.submit()" /><br/>
<input type="button" value="submit4" onclick="javascript:document.f.action='login/login4';document.f.submit()" /><br/>
</form>
</body>
jsp中没有指定action,他是一个动态的action,由dom来进行复制。
User_Login_success.jsp中:
我们看到<s:property>属性可以通过#来进行赋值,这里解释一下attr的属性,attr属性不同于request,session,application,它会自动搜索你想要得到的属性,它会在request,session,application中搜索你想要的属性,很方便,但是我们一般不用,因为假如你有两个r1你该怎么办?而且这三个对象的储存位置需要编程人员精确的知道其位置的。
再看LoginAction2:
public class LoginAction2 extends ActionSupport implements RequestAware,SessionAware,ApplicationAware{
// Ioc控制反转
private Map<String,Object> request;
private Map<String,Object> session;
private Map<String,Object> application;
public String execute() {
request.put("r1", "r1");
session.put("s1", "s1");
application.put("a1", "a1");
return SUCCESS;
}
public void setApplication(Map<String, Object> request) {
this.request = request;
}
public void setSession(Map<String, Object> session) {
this.session = session;
}
public void setRequest(Map<String, Object> application) {
this.application = application;
}
}
RequestAware,SessionAware,ApplicationAware
可以从字面上翻译,RequestAware意为知道request对象,另外两个也一样。
想一个问题: 为什么request、session、application 通过map.put()放入值之后就能被浏览器解析并且拿到这个值?
肯定有一种机制是把request、session、application三个对象和浏览器进行交互,由此引用IoC(控制反转)这个概念,编程人员不用再自己主动去调用,而是把这种交互注入到request、session、application中,让你可以拿来直接使用,这也是我们struts常用的方式。
下面再看LoginAction3:
public class LoginAction3 extends ActionSupport{
private HttpServletRequest request;
private HttpSession session;
private ServletContext application;
public LoginAction3() {
request = ServletActionContext.getRequest();
session = request.getSession();
application = session.getServletContext();
}
public String execute() {
request.setAttribute("r1", "r1");
session.setAttribute("s1", "s1");
application.setAttribute("a1", "a1");
return SUCCESS;
}
}
LoginAction4:
public class LoginAction4 extends ActionSupport implements ServletRequestAware{
private HttpServletRequest request;
private HttpSession session;
private ServletContext application;
public String execute() {
request.setAttribute("r1", "r1");
session.setAttribute("s1", "s1");
application.setAttribute("a1", "a1");
return SUCCESS;
}
public void setServletRequest(HttpServletRequest request) {
this.request = request;
session = request.getSession();
application = session.getServletContext();
}
}
上述两种方式使用的少之又少,可以不用考虑,直接忘掉即可。
Include 包含
这个标签比较简单,但是蕴含的道理很耐人寻味
新建一个login.xml:
<struts>
<package name="login" extends="struts-default" namespace="/login"> <!-- package包区分不同的类名 -->
<action name="login*" class="com.liuxuan.struts.LoginAction{1}">
<result>/User_Login_success.jsp</result> <!-- 默认即为success -->
</action>
</package>
</struts>
struts.xml持有对login.xml的引用:
<constant name="struts.devMode" value="true" />
<include file="login.xml"></include>
由此带来的好处是如果是项目组的话,可以专注于各自手头的工作即可。
Default属性:
struts.xml中
<constant name="struts.devMode" value="true" />
<package name="default" extends="struts-default" namespace="/"> <!-- package包区分不同的类名 -->
<default-action-ref name="index"></default-action-ref>
<action name="index">
<result>/default.jsp</result> <!-- 默认即为success -->
</action>
</package>
指定一个属性
<default-action-ref name="index"></default-action-ref>
这样无论在url地址中如何输入都会跳转到default.jsp页面