struts2

来源:互联网 发布:java 泛型 class 参数 编辑:程序博客网 时间:2024/06/06 20:31
Struts2不是继承struts1的血统,而是在Webwork上的升级,同时吸收了Strust1和WebWork两者的优势
Struts :支柱,支干,来源于旧建筑和旧式飞机使用的金属支架;Struts是流行和成熟的基于MVC设计模式的Web应用程序框架。使用Struts的目的:为了减少在运用MVC设计模型来开发Web应用时间。
小提示插入:Hibernate中修改、删除、添加操作要开启事务,查询操作不要开启事务:修改、删除、添加要对数据库中持久化数据进行变动,为了保护数据安全,防止错误数据存入,而查询操作不要对数据库中的数据进行更改。
JSP+JavaBean = Model1:适用于小型网站的开发 JSP+Servlet+JavaBean = Model2:最典型的MVC模式MVC是模型(Model)、视图(View)和控制器(Controller)的缩写;MVC是一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。在Struts中,Controller就是action。
Struts2.5版本在web.xml中加载struts2过滤器<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
Tomcat无法正常启动,抛出异常:java.lang.NoClassDefFoundError: Lorg/apache/logging/log4j/Logger;是因为缺少log4j-api-2.7.jar包,将包导入项目中就可以了。在struts.xml中使用通配符时,编译没有问题,但浏览器访问抛出异常:Struts has detected an unhandled exception:Message:There is no Action mapped for namespace [/] and action name [user_login] associated with context path [/shop].为了提高安全性,内部会验证是否允许访问该方法,所以要在struts.xml文件中的Action标签里面加上:<allowed-methods>方法名1,方法名2…</allowed-methods>
工作原理在Struts2框架中的处理大概分为以下几个步骤 1 客户端初始化一个指向Servlet容器(例如Tomcat)的请求 2 这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin) 3 接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请是否需要调用某个Action 4 如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy 5 ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类 6 ActionProxy创建一个ActionInvocation的实例。 7 ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。 8 一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可 能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2 框架中继承的标签。在这个过程中需要涉及到ActionMapper 二 工作流程1、客户端浏览器发出HTTP请求.2、根据web.xml配置,该请求被FilterDispatcher接收3、根据struts.xml配置,找到需要调用的Action类和方法, 并通过IoC方式,将值注入给Aciton4、Action调用业务逻辑组件处理业务逻辑,这一步包含表单验证。5、Action执行完毕,根据struts.xml中的配置找到对应的返回结果result,并跳转到相应页面6、返回HTTP响应到客户端浏览器

运行struts2的环境:(1)Servlet API 2.4(2)JSP API 2.0(3)Java JDK 1.5 或者以上过程:(1)将struts 添加到项目中:Apache官网下载struts库文件,解压;将lib目录下struts.jar文件复制到项目WEB-INF/lib之下;其他文件则复制到/WEB-INF文件夹下,然后在该文件夹下创建struts-config.xml配置文件.(2)给项目添加struts2支持(3)创建Action进行测试
commons-fileupload(上传下载包)commons-io(输入输出包)commons-lang 3-3.2(基础包)commons-logging(日志包)freemarker(模板引擎,通过模板生成文本输出的通用工具)structs2-core(核心包)xwork-core(一些类基于xwork)ognl(表达式)javassist-3.11.0.GA.jar(解析java类文件的一个包)1.新版本的struts2的xwork.jar包已经合并到核心包里了2. 新版本的过滤器类的class路径是org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter
之后配置web.xml文档web项目在启动tomcat时第一个启动的文件就是web.xml首先定义过滤器<filter><filter-name>struct2</filter-name><filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>这里写完后按住ctrl点击鼠标左键如果可以跳转则证明正确</filter>filter的映射<filter-mapping><filter-name>struct2</filter-name><url-pattern>/*</url-pattern>/*是所有的都需要过滤</filter-mapping>映射与文件的filter-name应该保持一致之后再src中创建struts的核心xml  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="default" namespace="/" extends="struct-default>       <action name="helloworld"class="com.imooc.action.HelloWorldAction">//class为包中的方法             <result  name="success" >result.jsp</result>//name默认为success       </action>    </package>
</struts>之后创建action包 创建action类让其继承ActionSupport Struts2中有一个默认的方法不指定方法名的话有一个execute()方法之后去配置struts.xml中的action文件
只有配置在web.xml文件中的Servlet才会被应用加载,在其中加载web应用的一个核心控制器Controller,对于Structs2框架而言,这个核心控制器是StructsPrepareAndExecuteFilter,在这个控制器中加载Structs2框架struts.xml是struts2的核心配置文件,负责管理应用中的action映射,拦截器和result定义。
Struts.xml文件的标签<struts><include file="">包含其他的独立xml配置文件<package提供了将多个action组织为一个模块的方式名字必须唯一,name:package名称extends:继承父package名称abstract:设置package的属性为抽象的package不能定义action,值true:falsenamespace:定义package命名空间影响到URL的地址,例如命名空间为/test,那么访问的地址为http://localhost:8080/struts2/test/xx.action**以下介绍都是写在<package>与</package>之间的**<interceptor>定义拦截器name:拦截器名称class:拦截器类路径<interceptor-stacck name="">定义拦截器栈<default-interceptor-ref name="">定义默认拦截器定义全局result配置<global-results><result name="error">/error.jsp</result></golbal-result><action>name:action名称,影响//localhost:8080/struts2/xx.actionclass:对应类的路径method:调用action的方法名在action中可以定义拦截器,定义返回result,定义参数例如URL<constant name="..." value="..."></constant> 可以配置一些可调用的参数

struts.properties内容1.#指定默认编码集,对于请求参数带有中文的情况应该设置成GBK或GB2312,默认值UTF-82.struts.i18n,encoding = GB23123.#是否每次HTTP请求到达时,都重新加载国际化资源文件,默认值false4.struts.i18n.reload = true5.#当struts.xml改动后,是否重新加载该文件。在开发阶段建议将此属性设置为“true”,提高开发效率,默认为false6.struts.configuration.xml.reload =true7.#是否使用Struts2的开发模式,可以获得更多报错信息,便于调试。在开发阶段设置为true。默认为false8.struts.devMode = true9.#设置浏览器是否缓存静态页面,开发阶段设置为false,以获得最新响应。默认值为true10.struts.serve.static.browserCache = true11.#指定后缀为.action形式的请求可被Struts2处理,可配置多个请求后缀,比如.do,.struts2等,配置时多个后缀用逗号隔开12.struts.action.extension = action,do,struts213.#配置服务器运行时的端口号。一般情况下改属性不修改,如果端口号占用则重新分配端口号,默认值8014.struts.url.http.port = 8080
struts的八个主要步骤:1.访问Servlet API2.Action搜索顺序3.动态方法调用4.指定多个配置文件5.默认Action6.Struts2后缀7.接受参数8.处理结果类型
在Strut2中访问Servlet API有三种方式:1).创建一个ActionContext              ActionContext context=ActionContext.getContext();2).通过context对象获取Servlet APIMap<String,Object> getApplication() 获取的是application中存储的所有信息 Map<String,Object> getParameters() 相当于 request.getParameterMap();Map<String,Object> getSession(); 获取的是session中存储的所有信息.put(String key,Object value); 就相当于request.setAttribute();Object get(String key) 就相当于request.getAttribute();2、通过实现Aware接口注入方式(真正的Servlet API)ServletContextAware : 注入ServletContext对象ServletRequestAware :注入 request对象ServletResponseAware : 注入response对象3、通过ServletActionContext(真正的Servlet API)通过ServletActionContext类中提供了静态方法可以直接获取Servlet API:
servlet api:httpRequest、httpResponse、servletContext3个api对应jsp面向对象:request、response、applicationservlet中可以直接调用servlet apistruts2 Action中execute没有任何参数,也就是不存在servlet apistruts2 提供了3种方式访问servlet api:1.ActionContext类2.实现***Aware接口3.ServletActionCotext类
Action的搜索顺序:1.判断package是否存在存在:2.判断action是否存在,如果不存在则去默认的namespace的package里面寻找          3.如果没有,则报错不存在:2.检查上一级路径的package是否存在(直到默认的namespace),重复第一步             3.如果没有,则报错如果请求为/login.action,系统会根据根命名空间("/")中查找名为login的Action,如果在根命名空间中找到了名为login的Action,则该Action处理用户的请求;否则系统将转为在默认命名空间中寻找名为login的Action,如果默认的命名空间中有名为login的Action,则由该Action处理用户的请求。如果两个命名空间中都找不到名为login的Action,那么系统将出现错误。      注意:命名空间只有一个级别。如果请求的URL是/bookservice/search/get.action系统将先在/bookservice/search的命名空间下查找名为get的Action,如果在该系统命名空间内找到名为get的Action,则由该Action处理该用户的请求;如果在该命名空间中没有找到名为get的Action,系统将直接进入默认的命名空间中查找名为get的Action,而不会在bookservice的命名空间下查找名为get的Action。可以多个包使用同一个命名空间,但是相同的命名空间相当于同一个模块,也就是同一个包。一个包中可以有name值相同的action,但是后面的action会把前面同名的action覆盖掉
动态方法调用:动态方法调用是为了解决一个Action对应多个请求的处理,以免Action太多。三种方式:指定method属性、感叹号方式(不推荐)、通配符方式(推荐使用)1:<action name="add" method="add" class="com.imooc.action.HelloWorldAction">2:<constant name="struts.enable.DynamicMethodInvocation" value="true">                                                </constant><action name="helloWorld" class="com.Action.HelloWorldAction">      <result >/result.jsp</result>      <result name="add">/add.jsp</result>      <result name="update">/update.jsp</result>      </action>http://localhost:8080/HelloWorld/HelloWorld!add(或update).action3: 第一个*代替{1},第二个*代替{2},result里的name是Action的返回值,action的里method是Action里的方法名,调用某个方法时最后目标就输入 {1}_{2}.action;这样可以访问多个Action里的方法.<action name="*_*" method="{2}" class="com.imooc.action.{1}Action">      <result >/result.jsp</result>      <result name="add">/{2}.jsp</result>      <result name="update">/{2}.jsp</result>      </action>http://localhost:8080/HelloWorld/HelloWorld_add.action

指定多个配置文件,如果项目比较大,xml配置文件比较多,那么可以在struts.xml中使用include标签,将多个配置文件包括进来。<include file="***.xml"> </include><constant name="struts.i18n.encoding" value="UTF-8"> </constant>注意:1.被include的标签一定要符合struts的dtd规范。也就是说被include的xml文件的内部格式要符合struts的xml文件规范。2.xml文件的编码格式要相同,如果是utf-8,那么都是utf-8。
默认Action,在网页找不到原来输入的网址的情况下,跳转的页面新建<default-action-ref name = "xxx"></default-action-ref>//这是默认跳转指令,name中的名字可以自定义<action name= "xxx">//这里的name必须跟<default-action-ref>中的name一样<result>xxxx.jsp</result>//需要默认跳转到的jsp页面</action>//结束action

Struts2后缀,默认是.action或者是空值如何要设置,请在Struts2的三大核心文件中设置在strts.xml中的配置语句<constant name = "strts.action.extension" value = "xxx,xx,yyy"></constant>//name是固定的,value是指定的后缀,可以是空值在struts.properties中的配置struts.action.extension = xxxx,xxx,xx//可以配置多个,以,号分隔在web.xml中的配置<filter>//过滤器<init-param>  <param-name>struts.action.extension</param-name>//struts.action.extension为固定  <param-value>do</param-value>//do为可选后缀</init-param>//结束init-param</filter>//结束过滤器

接收参数三个方法,推荐使用ModeIDriven接收第一种接收参数的方法:直接在action类中创建相应的属性和getter和setter,和前端的name名字相同。eg:前端的username,在action类中就要建立一个private String username; Struts会自动映射为这个属性赋值第二种接受参数的方法:使用DomainModel,将username 和password两个属性封装为一个类User(必须是标准的JavaBean),在action中声明这个属性:private User user; 同时必须为user设置getter和setter;在前端中的name需要设置为user.name和user.password,才能映射成功。如果private User user=new User();是没有办法映射成功的第三种接收参数的方法:使用ModelDriven<T>接口,这个action必须实现这个接口的public T getModel()方法。此时声明的属性必须实例化,eg: private User user = new User(); 同时不需要getter和setter。前端的name也只需要写username和password就可以,不需要再加域了。这种方法时最推荐的方法,因为可以减少前后端的耦合注意:1、使用Action的属性接受参数,在Action中定义需要接受的属性,并写它的set/get方法。2、使用DomainModel接受参数,创建实体类定义需要接受的属性,并set/get方法,在Action中创建实体类名属性。并在界面进行指定。3、使用ModelDriver接受参数,在Action中实现ModelDriver<实体类名>接口,并实现方法返回当前需要转换的对象,删除set/get方法,并对 对象 进行实例化,并取消指定。4、获取List集合中的参数。获取多个参数
例子:
也可以传集合 但是数组不能传==============
把表单的数据提交到LoginAction.action  struts.xml文件配置: <action name="LoginAction" method="login" class="com.action.LoginAction">          <result>/LoginSuccess.jsp</result>     </action>action name一定是表单的提交action 调用该action的login方法
public class LoginAction extends ActionSupport implements ModelDriven<User> {private User user =new User();public String login(){System.out.println(user.getBookList().get(0));System.out.println(user.getBookList().get(1));System.out.println(user.getUserlist().get(0).getUsername());System.out.println(user.getUserlist().get(1).getUsername()); return SUCCESS; }------------------private String username;private String password;private List<String> bookList;private List<User> userlist;-----------------<form action="LoginAction.action" method="post" name="LoginForm"> 书籍1:<input type="text" name="bookList[0]" value=""/><br> 书籍2:<input type="text" name="bookList[1]" value=""/><br> 人1:<input type="text" name="userlist[0].username" /><br> 人2:<input type="text" name="userlist[1].username" /><br> <input type="submit" value="提交"/><br> </form>

【Structs2处理流程】用户请求→Structs框架→控制器(Action)→Structs框架→视图资源返回String,提供代码复用性,有利于框架分离。【Action中五种内置属性(com.opensymphony.xwork2.Action)】(1) SUCCESSAction正确的执行完成,返回相应的视图,success是name属性的默认值。 (2) NONE表示Action正确的执行完成,但并不返回任何事视图。(3) ERROR表示Action执行失效,返回错误处理视图。(4) LOGINAction因为用户没有登录的原因没有正确执行,将返回该登录视图,要求用户进行登录验证(5) INPUTAction的执行,需要从前端界面获取参数,INPUT就是代表这个参数输入界面,一般在应用中,会对这些 参数进行验证,如果验证没有通过,将自动返回该视图。注意:<result>/success.jsp</result>有“/”:绝对路径,开始是整个项目的上下文路径无“/”:相当于执行该action namespace指定的路径

结果类型input的效果 * 1.当参数类型转换错误时,如age输入框中的类型是字母等情况,方法自动返回input * 2.当action中存在addFiledError时: *    1)addFileError放在一般执行方法,addFieldError("", "");语句后面有返回input的语句 *    2)addFileError放在validate()中,则不需要return INPUT; *3.FileError的表现形式: *    在jsp页面中使用<s:fielderror></s:fielderror>标签,该标签name属性为addFieldError方法中的参数fieldName,在jsp页面中使用struts标签, *    需要导入标签库  语句:<%@ taglib prefix="s" uri="/struts-tags"  %>

处理结果类型-result标签下还有param标签:1)location:该属性定义了该视图对应的实际视图资源2)parse:该参数指定是否可以再实际视图名字中使用OGNL表达式,默认值为TRUE,支持OGNL(Object-Graph Navigation Language)表达式ognl表达式可以在jsp页面去写,也可以在struts2页面中去写,在实际开发中是不常用的,默认情况下ognl是允许的,是打开状态<param name="parse">true</param><param name="location">...地址</param>ognl表达式使用:<param name="location">/${#request.path}.jsp</param>在action类中对应的方法中写request.setAttribute("path","返回的jsp页面名称");
(1)在result里面最重要的属性是type类型,type的默认值为dispatcher(转发),这个类型支持JSP视图技术。(2)Struts2支持多种视图技术,例如JSP、Valocity(模板引擎)、FreeMaker(模板引擎)等。(3)常用三个:chain,redirect,plaintext。1、chain:将action和另外一个action链接起来。2、redirect:重定向(会丢失请求参数)。3、plaintext:返回网页源代码。4、stream:返回inputstream用于文件下载