readbook:struts2
先说一下struts1:
struts1使用model II 模式开发,即jsp+java bean+servlet
再说它的缺陷:
1.表现层支持单一,本来在java web应用的世界里,表现层技术选择时不一定必须选择jsp,其它视图层可用于替代选择的技术如 FreeMaker,Velocity等,
但struts 1无法与其进行整合.
2. 过度依赖servlet api
servlet api需要web容器进行初始化,此时一旦脱离web 容器,整个程序很难完成测试.
3.不利于代码重用
在struts 1中的某些类(比如actionForm)耦合在一起的代码很难再其它系统中进行重用.
于是struts2改变思路,同时吸收struts 1的一些想法,以WebWork(java的另一个类似框架项目)的设计思想为核心进行了框架重构
官网:http://struts.apache.org/
基础包 struts2-core-xxx.jar struts2框架的核心类库 xwork-core-xxx.jar xwork类库,struts2构建基础 ognl-xx.jar struts2使用的一种表达式语言类库 freemaker-xxx.jar struts2的标签模板使用类库 javassist-xxx.GA.jar 字节码处理 commons-fileupload-xx.jar 文件上传时用到的 commons-io-xx.jar java IO 扩展 Commons-lang-xx.jar 包含了一些数据类型的工具库 commons-lang3-xx.jar
如果用到了一些非基础类库里的类导致控制台报错提示类库缺失,可以根据信息引入框架内的其它相应类库
struts helloworld:
关于struts 的ognl(对象图导航语言)表达式语言
1.jsp <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@taglib uri="/struts-tags" prefix="s" %> <%-- 注释: 在jsp文件里增加这一行--%> <html> <head>...</head> <body> ... <%-- 输出struts action中message的值 --%> <h1> <s:property value="message" /> </h1> <div class="row"> <form action="HelloWorld.action" method="post"> <input name="name" type="text"/> <input type="submit" value="提交"/> </form> </div> </body> </html> 2.java类 写处理action逻辑代码 package com.bud.test; import com.opensymphony.xwork2.Action; public class HelloWorldAction implements Action { private String name = ""; private String message = ""; public String execute() throws Exception { // TODO Auto-generated method stub this.setMessage("hello,"+this.getName()+"!"); return "success"; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
发生的事情,表单提交时,struts2来对请求参数进行转换,
同时依据约定由于配置的思想,直接对action中具有相同名字Action类属性赋值(通过setter方法)
Action的excute() return 五个常量
success 表示程序处理正常,并返回用户成功的结果 none 表示处理正常结束,但不返回用户客户端任何数据 error 表示处理结果失败 input 表示需要更多用户输入才能顺利执行 login 表示需要用户正确登录后才能顺利执行
以上5个常量是action默认支持逻辑视图的名称, 也支持扩展返回其它特定字符串作为逻辑视图名称
3.web.xml 配置 用于拦截所有请求 到struts2 上
<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> notice:这里的 org.xxx 根据具体 struts2 core 的jar里的类去找
4.struts2的配置文件
在src路径下建立struts.xml
因为不同版本xml文档定义的问题 我下了对应版本的struts在它的示例app中拷了这个配置文件修改
不过如果用myeclipse的话,完全可以用项目上右键菜单MyEclipse-->Add Struts Capabilities...
不过这里讲原理就不用工具生成了
就我发现的规律文档定义一般也只会改 Configuration 2.3 dtds/struts-2.3.dtd 这里的第二位版本号而已,比如2.0,2.3之类
<?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"> <!-- START SNIPPET: xworkSample --> <struts> <!-- 创建default包,继承struts-default包 --> <package name="default" namespace="/" extends="struts-default"> <action name="HelloWorld" class="com.bud.test.HelloWorldAction"> <result name="success">/test/hello-world.jsp</result> </action> </package> </struts> <!-- END SNIPPET: xworkSample --> notice:注意每一步每一步对应的大小写
配置文件的节点介绍:
package元素定义 struts2请求处理的逻辑单元
name 属性必须唯一(指定包的名称,可用于被其它包引用)
extends 属性用于指定继承哪个包
namespace用来指定命名空间,从而逻辑上不同命名空间下可以出现同名的Action
action元素 用于配置具体工作的Action类
name 属性是action的名字
class 用于设定Action处理的全限定名类
result用来设定Action处理后,系统下一步将要做什么
name 属性是逻辑视图名称,必须和action 类返回值匹配
result节点的值则是对应结果的视图位置
实际上更多的会用javabean(实体对象)来保存信息
这时action 和jsp中就变成了这样
action: public class LoginAction implements Action{ private User user; public String execute() throws Exception { //... } ... //getter setter... } jsp: <input type="text" name="user.name" /> <input type="password" name="user.password" />
struts2实际上会调用LoginAction.getUser().setName()
原本action代码中并没有实例化bean对象,应该报错的,但在struts中会自动实例化任何用于填充数据的对象
struts2 访问servlet api
与servlet api解耦的访问方式:
使用ActionContext类获取Servlet API对象对应的Map对象,在Action类中,我们可以直接访问 HttpServletRequest HttpSession 和 ServeletContext对应的Map对象
通过struts框架内的com.opensymphony.xwork2.ActionContext 类获取, ActionContext是Action执行的上下文,在ActionContext中保存了Action类执行时所需要的一组对象
获取方法:
ActionContext ac = ActionContext.getContext(); //获取 HttpServletRequest Map request = (Map)ac.get("request"); //获取 HttpSession Map session = ac.getSession(); //获取 ServletContext Map application = ac.getApplication();
实例:
jsp: <h3>欢迎您,${sessionScope.CURRENT_USER}!</h3> <div class="row"> <form action="Login.action" method="post"> <input name="user.name" type="text" placeholder="用户名" /> <input name="user.pass" type="password" placeholder="密码" /> <br/> <input type="submit" value="提交" /> </form> </div> Action: public class LoginAction implements Action{ private String message = ""; private User user; public String execute() throws Exception { this.setMessage("hello,"+this.user.getName()+"! pass: "+this.user.getPass()); ActionContext ac = ActionContext.getContext(); Map<String,Object> session = ac.getSession(); if("lili".equals(this.user.getName()) && "dd".equals(this.user.getPass()) ){ session.put("CURRENT_USER", this.user.getName()); return "success"; } else{ return "error"; } } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } } bean: public class User { private String name = ""; private String pass= ""; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPass() { return pass; } public void setPass(String pass) { this.pass = pass; } } struts.xml内的action配置: <action name="Login" class="com.bud.test.LoginAction"> <result name="success">/test/hello-world.jsp</result> <result name="error">/index.jsp</result> </action>
与servlet api耦合的访问方式:
要直接获取servlet api对象可以使用 org.apache.struts2.ServletActionContext类,
它是ActionContext的子类,在这个类中定义了如下方法获取servlet api对象
public static HttpServletRequest getRequest() : 得到HttpServletRequest对象 public static ServletContext getServletContext() : 得到ServletContext对象 public static HttpServletReponse getResponse() : 得到HttpServletResponse对象
notice:
ServletActionContext对象并没有定义直接获取HttpSession对象的方法,但你可以通过HttpServletRequest来得到
此外还可通过Action类实现特定的接口,由struts2向Action实例注入Servlet api对象
org.apache.struts2.util.ServletContextAware 将向Action实例注入ServletContext对象,该接口只有一个方法 void setServletContext(ServletContext context) org.apache.struts2.interceptor.ServletRequestAware : 同上接口只有一个方法 void setServletRequest(HttpServletRequest request) org.apache.struts2.interceptor.ServletReponseAware : 同上接口只有一个方法 void setServletResponse(HttpServletResponse reponse)
后续待补充...