Java学习大全 之 Struts2

来源:互联网 发布:安装示意图制作软件 编辑:程序博客网 时间:2024/05/22 03:21

1、struts2是在WebWork2基础发展而来的,是轻量级的框架也是属于MVC框架,特点:多action实例的、不依赖servlet和struts1 API。
2、struts2的配置文件默认是struts.xml,由于struts2通过filter启动的所以配置文件放在类路径下,struts1是通过servlet启动所以配置文件放在WEB-INF下。
 servlet过滤器实在java servlet规范定义的,能过对url请求和响应进行检查和修改。
 <filter>
     <filter-name>struts2</filter-name>
     <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
   <!-- 自从Struts 2.1.3以后,上面的FilterDispatcher已经标注为过时,下面的为新的filter -->
     <!--<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、自定义过滤器
 步骤
 一、实现javax.servlet.Filter接口
  public void init(FilterConfig config) throws ServletException;//servlet容器创建过滤器实例后调用
  //完成实际的过滤操作,返回响应之前的会调用doFilter方法
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain filter) throws IOException, ServletException;
  public void destroy();//容器在销毁过滤器前调用
 二、在web.xml配置
  <filter>
      <filter-name>过滤器名字</filter-name>
      <filter-class>过滤器类</filter-class>
      <init-param>
       <param-name>参数名字</param-name>
       <param-value>参数值</param-value>
      </init-param>
  </filter>
  <filter-mapping>
      <filter-name>过滤器名字</filter-name>
      <url-pattern>url</url-pattern>
  </filter-mapping>
4、配置action
 package元素是用来把actoin分类进行的管理,还可以重用。
 package的name属性是不选的,表示该package的名称
 package的extends属性是可选的,允许一个包继承一个或者多前面定义的包
 package的abstract属性是可选的,设置为true表示抽象包,抽象包不需要action定义,被其他包所继承
 package的namespace属性是可选的,将action配置为不同的命名空间。默认命名空间是"/",如果指定了命名空间,请求先去指定的命名空间找action,如果找不到则去默认的命名空间找。
 例子:
 配置文件
  <!--声明抽象包-->
  <package name="default" abstract="true" extends="struts-default">
  </package>
  <!--继承抽象包-->
  <package name="package1" extends="default">
   <!--没有配置method属性表示执行Action类的默认的方法execute()-->
   <action name="default" class="com.TestAction">
    <result name="success">/index.jsp</result>
   </action>
   <!--指明该action执行add方法-->
   <action name="add" class="com.TestAction" method="add">
    <result name="success">/index.jsp</result>
   </action> 
  </package>
  <!--指定命名空间的action,那么访问delete需要加上命名空间:admin/delete-->
  <package name="package2" extends="struts-default" namespace="/admin">
   <action name="delete" class="com.TestAction" method="delete">
    <result name="success">/index.jsp</result>
   </action> 
  </package>
 TestAction.java类
  public class TestAction extends ActionSupport {
   @Override
   public String execute() throws Exception {
    System.out.println("默认的处理方法");
    return SUCCESS;
   }
   public String add(){
    System.out.println("add处理方法");
    return SUCCESS;
   }
   public String delete(){
    System.out.println("delete处理方法");
    return SUCCESS;
   }
  }
 index.jsp页面
  <%
  String path = request.getContextPath();
  String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
  %> 
    <a href="<%=path %>/default">不指定method属性执行默认的方法</a><br/>
    <a href="<%=path %>/add">指定执行add方法</a><br/>
    <a href="<%=path %>/admin/delete">指定指定命名空间的action</a><br/>

5、result元素
 location:指定逻辑视图
 parse:是否允许在实际视图中使用ongl表达式,参数默认为true
 success:表示请求处理成功
 error:表示请求失败
 none:表示请求完成后不跳转任何页面
 input:表示输入时如果验证失败调到什么地方
 login:表示登录失败时候跳转的目标
 chain:用来处理action链
 chart:用来整合JFreeChart的结果类型
 dispatcher:用来转向页面
 freemarker:处理FreeMark模板
 httpheader:控制特殊HTTP行为的结果类型
 jasper:用于JasperReports整合的结果类型
 jsf:JSF整合的结果类型
 redirect:重定向到一个url
 redirect-action:重定向一个action
 stream:向浏览器发送InputStream对象,通常用来处理文件下载的,还可以用于返回ajax数据
 titles:与Title整合的结果类型
 velocity:处理Velocity模板
 xslt:处理XML/XSLT模板
 plaintext:显示原始文件内容,如下载源代码
 全局result的配置使得连接得到共享
  <package ....>
   <global-results>
    <result name="success">/success.jsp</result>
   </global-results>
  </package>

6、struts.properties配置
 struts.action.extension: 指明action的后缀,如action,do,"struts.action.extension=action,do,"表示后缀为action或者do或者不用点后缀
 struts.configuration:配置文件管理器默认为org.apache.struts2.config.DefaultConfiguration类
 struts.configuration.files: struts自动加载的一个配置文件列表
 struts.configuration.xml.reload:是否加载xml配置值为true、false
 struts.continuations.package:含有actions的完整连续的package名称
 struts.custom.i18n.resources:指定国际化文件的前缀,多个文件用逗号分开
 struts.custom.properties:配置用户自定义配置文件的路径,若有多个可以用逗号隔开
 struts.devMode:设置是否为struts开发模式。这样会显示更多友好的错误提示
 struts.enable.DynamicMethodInvocation:是否允许动态方法调用,值为true、false
 struts.i18n.encoding:指定字符集
 struts.i18n.reload:该属性设置是否每次HTTP请求到达时,系统都重新加载资源文件。该属性默认值是false
 struts.locale:设置默认的国际化地区信息
 struts.multipart.maxSize:multipart请求信息的最大尺寸(文件上传用)
 struts.multipart.parser:专为multipart请求信息使用的org.apache.struts2.dispatcher.multipart.MultiPartRequest解析器接口(文件上传用)
 struts.multipart.saveDir:设置保存上传文件的目录
 struts.tag.altSyntax:是否能在struts2标签中使用表达式,值为true、false
 struts.serve.static:表示是否通过jar文件提供静态内容服务,默认为true
 struts.ui.templateDir:该属性指定视图主题所需要模板文件的位置,该属性的默认值是template
 struts.ui.theme:该属性指定视图标签默认的视图主题,该属性的默认值是xhtml
 struts.url.http.port设置http端口
 struts.url.https.port:设置https端口,该属性指定的是Web应用的加密服务端口
 struts.velocity.configfile:设置velocity框架配置文件路径
 struts.velocity.contexts:velocity:该属性指定Velocity框架的Context位置
 struts.velocity.toolboxlocation:指定Velocity框架的toolbox的位置

7、获得用户表单与ModelDriven<T>接口
 一、不实现ModelDriven接口的例子:
 LoginAction.java请求处理类
  public class LoginAction extends ActionSupport {
   private String username;//用户名,对应表单输入框的name属性值
   private String password;//密码,对应表单输入框的name属性值
   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;
   }
   @Override
   public String execute() throws Exception {
    System.out.println(username);
    System.out.println(password);
    return SUCCESS;
   }
  }
 action配置
  <package name="login" extends="struts-default" >
   <action name="login" class="com.LoginAction">
    <result name="success">/index.jsp</result>
   </action>
  </package> 
 index.jsp页面
  <form action="login" method="post">
   用户名<input name="username" type="text"/><br/>
   密码<input name="password" type="password"/><br/>
   <input type="submit" value="登录"/><br/>
  </form>
 二、实现ModelDriven接口的例子:
 LoginAction.java请求处理类
  public class LoginAction extends ActionSupport implements ModelDriven<User> {
   private User user = new User();//需要手动new一个User对象
   //实现接口的方法,返回User对象
   public User getModel() {
    return this.user;
   }
   @Override
   public String execute() throws Exception {
    System.out.println(user.getUsername());
    System.out.println(user.getPassword());
    return SUCCESS;
   }
  }
 action配置同上
 index.jsp页面同上,这时表单输入框的name属性值对应的是User对象的属性名
 
8、 拦截器配置
 <package name="login" extends="struts-default">
  <!--
   拦截器栈(或堆)
   拦截器栈就是将多个拦截器进行打包,
   拦截器包里还可以引用其他的拦截器栈
   如果有多个action的话,直接调用栈即可。
   比如struts1.xml中也想引用exectue_action_timer_interceptor的话,
   struts1.xml中继承login包即可
  -->
  <interceptors>
   <!--定义了一个拦截器名字为timer类型是com.opensymphony.xwork2.interceptor.TimerInterceptor,可以算出action的执行时长-->
      <interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>
      <!--interceptor-stack表示拦截器栈可以包含多个拦截器-->
   <interceptor-stack name="exectue_action_timer_interceptor">
    <interceptor-ref name="timer" /><!--引用了上面的拦截器timer-->
    <interceptor-ref name="defaultStack" /><!--默认的拦截器defaultStack-->
   </interceptor-stack>
  </interceptors>
  <action name="login" class="cn.serup.struts2.login.LoginAction">
   <result name="success">/success.jsp</result>
   <result name="input">/index.jsp</result>
   <result name="error">/error.jsp</result>
   <!--如果指定拦截器,那么默认的就没有执行,那么就获取不了表单传来的值。所以指定拦截器时候需要加上默认的拦截defaultStack-->
   <interceptor-ref name="exectue_action_timer_interceptor" />
  </action>
 </package>

9、服务端action跳转chain和客户端action跳转redirectAction
 chain例子:
  <!--
   如果使用chain来跳转到某个Action上,
   则需要指定param参数的name属性为actionName,
   不指定则默认是location,location是指定某个资源JSP/HTML
  --> 
  <action name="test1" class="cn.serup.struts2.Test1Action">
   <result name="success" type="chain">
    <!-- name="actionName"表示请求的名字,不需要加后缀 ,告诉我action名称即可-->   
    <param name="actionName">test2</param><!--服务端跳转到名字为test2的actoin-->
   </result>
  </action>
  <action name="test2" class="cn.serup.struts2.Test2Action">
   <result>/test1.jsp</result>
  </action>
 redirectAction例子
  <!--
   可以通过Result来传参,可以在struts.xml文件中 编写EL表达式 ${nane}是属性的名称
   在Test1Action中获得name的值,然后传到到Test2Action中 在Test2Action中接收
  -->
  <action name="test11" class="cn.serup.struts2.Test1Action">
   <result name="success" type="redirectAction">
    <param name="actionName">test22?name=${name}</param>
   </result>
  </action>
  <action name="test22" class="cn.serup.struts2.Test2Action">
   <!--
    这里获得了test11 请求中的属性name的值, 然后通过URL来传递参数 在页面中通过EL表达式来接收并输入${param.name}
   -->
   <!--redirect表示客户端重定向到那个页面-->
   <result type="redirect">/test1.jsp?name=${name}</result>
  </action>

10、获得非servlet绑定的request、session和application
 方法一:
 ActionContextTest.java类
 public class ActionContextTest extends ActionSupport {
  private Map request ;//request的键值对
  private Map session ;//session的键值对
  private Map application ;//application的键值对
  /**
   * 第一种获取方法:非Ioc(控制反转)
   * 通过ActionContext对象的 get(Object) 、getSession() 、getApplication()
   * 这三个方法分别能获取Map类型的request 和 session 以及 application
   * 获取是首先需要获取一个ActionContext对象,然后再调用上面三个方法
   * 注意:如果使用此方法获得,则必须在execute()方法中初始化,或构造方法
   */
  public ActionContextTest() {
   //非Ioc意思就是自己控制,自己创建对象 ActionContext.getContext();
   ActionContext c = ActionContext.getContext() ;
   request = (Map)c.get("request") ;
   session = c.getSession() ;
   application = c.getApplication() ;
  }
  @Override
  public String execute() throws Exception {
   request.put("r1","r1_value") ;
   session.put("s1","s1_value") ;
   application.put("a1","a1_value") ;
   return SUCCESS ;
  }
 }
 方法二:
 ActionContextTest2.java类
 public class ActionContextTest2 extends ActionSupport implements RequestAware,SessionAware,ApplicationAware{
  private Map request ;//request的键值对
  private Map session ;//session的键值对
  private Map application ;//application的键值对
  /**
   * 第二种获取方法:Ioc(控制反转)
   * 通过RequestAware、SessionAware、ApplicationAware
   * 这三个接口分别能获取Map类型的request 和 session 以及 application
   * 需要实现它们的方法。
   * 然后由struts容器来注入
   */
  public void setRequest(Map<String, Object> request) {
   this.request = request;
  }
  public void setSession(Map<String, Object> session) {
   this.request = session;
  }
  public void setApplication(Map<String, Object> application) {
   this.application = application;
  }
  public String execute() throws Exception {
   request.put("r1","r1_value") ;
   session.put("s1","s1_value") ;
   application.put("a1","a1_value") ;
   return SUCCESS ;
  }
 }
 页面显示
 <%@page contentType="text/html;charset=utf-8"%>
 <%@taglib prefix="s" uri="/struts-tags" %>
 request-s.tags:<s:property value="#request.r1"/><br/>
 request-el:${requestScope.r1} ;<br/>
 <p></p>
 session-s.tags:<s:property value="#session.s1"/><br/>
 session-el:${sessionScope.s1} ;<br/>
 <p></p>
 application-s.tags:<s:property value="#application.a1"/><br/>
 application-el:${applicationScope.a1} ;<br/>

11、获得与servlet绑定的request、session和application
 方法一:
 ServletActionContextTest.java类
 public class ServletActionContextTest extends ActionSupport {
  private HttpServletRequest request ;
  private HttpSession session ;
  private ServletContext application ;
  /**
   * 第一种获取方法:与servlet容器绑定
   * 通过ServletActionContext对象来获得,
   * 返回的是HttpServletRequest...
   */
  public String execute() throws Exception {
   request = ServletActionContext.getRequest() ;
   session = request.getSession() ;
   application = ServletActionContext.getServletContext() ;
   
   request.setAttribute("r1","r1_value") ;
   session.setAttribute("s1","s1_value") ;
   application.setAttribute("a1","a1_value") ;
   return SUCCESS ;
  }
 } 
 方法二:
 ServletActionContextTest2.java类
 public class ServletActionContextTest2 extends ActionSupport implements ServletRequestAware,ServletContextAware {
  private HttpServletRequest request ;
  private HttpSession session ;
  private ServletContext application ;
  /**
   * 第一种获取方法:与servlet容器绑定
   * 通过ServletActionContext对象来获得,
   * 返回的是HttpServletRequest...
   */
  public void setServletRequest(HttpServletRequest request) {
   this.request = request;
  }
  public void setServletContext(ServletContext application) {
   this.application = application;
  }
  public String execute() throws Exception {
   request.setAttribute("r1","r1_value") ;
   session.setAttribute("s1","s1_value") ;
   application.setAttribute("a1","a1_value") ;
   return SUCCESS ;
  }
 }
 页面显示同上
 
12、OGNL(Object-Graph Navigation Language)对象图导航语言
 功能一、支持对象方法调用,形式如:objName.methodName();   
 功能二、支持类静态的方法调用和值访问,表达式的格式为@[类全名(包括包路)]@[方法名 |  值名],struts.ognl.allowStaticMethodAccess=true表示允许静态方法访问。
 <s:property value="@java.lang.Math@floor(44.56)"/>调用静态方法和方法(非私有的)
 功能三、支持赋值操作和表达式串联
 功能四、访问OGNL上下文(OGNL context)和ActionContext
 功能五、操作集合对象
 
 #号用于访问非根对象(struts中值栈为根对象)
 #号用于过滤和投影集合
 #号用于构造一个map,如#{'foo1':'bar1', 'foo2':'bar2'}
 %号的用途是在标签的属性值被理解为字符串类型时,告诉执行环境%{}里的是OGNL表达式。
 $号在国际化资源文件中,引用OGNL表达式。   
 $号在Struts 2配置文件中,引用OGNL表达式。

 首先在页面中引入<%@taglib prefix="s" uri="/struts-tags" %>标签
 访问对象中的属性:
 user.name:<s:property value="user.name"/><br/>
 user.sex:<s:property value="user.sex"/><br/>
 user.addr.address:<s:property value="user.addr.address"/><br/>
 
 访问集合:
 <s:property value="arrays"/><BR/>
 访问数组某个元素:
 <s:property value="arrays[0]"/><p></p>
 
 访问Set集合:
 为什么只输出3个,但我的set集合中有6个元7D20?原因:set是无序的,重复的被覆盖<br/>
 <s:property value="set"/><br/>
 
 为什么获取不出set集合中的某个属性?原因是set是无序的
 <s:property value="set[0]"/><p></p>
 
 获取Map集合:
 <s:property value="map"/><br/>
 获取Map集合中的某个元素:
 <s:property value="map.key1"/><br/>
 获取所有Map中的所有Key值:
 <s:property value="map.keys"/><br/>
 获取所有Map中的所有value值:
 <s:property value="map.values"/><br/>
 
 集合中的伪类
 list:<s:property value="list.size"/>个<br/>
 array:<s:property value="arrays.length"/>个<br/>
 set:<s:property value="set.size"/>个<br/>
 map:<s:property value="map.size"/>个<br/>
 
 获取List中的所有对象
 <s:property value="listObject[0].name"/>
 <s:property value="listObject[0].sex"/>
 <s:property value="listObject[0].addr.address"/>
 <br/>
 <s:property value="listObject[1].name"/>
 <s:property value="listObject[1].sex"/>
 <s:property value="listObject[1].addr.address"/>
 <br/>
 使用投影来获得集合中的对象
 <s:property value="listObject.{name}"/><br/>
 <s:property value="listObject.{name}[0]"/><br/>
 <s:property value="listObject.{name}[1]"/><br/>
 
 

13、ValueStack值栈对象
 值栈(Value Stack)是Struts 2框架的核心概念,所有核心组件都以某种方式与之进行交互,它提供对上下文信息和执行环境中元素的访问机制
 值栈就是内存空间,栈在内存中是后进先出,先进后出,每个请求都会创建一个值栈。值栈的生命周期是跟request请求一致的。客户端跳转的话无法共享值栈。
 ValueStack对象贯穿整个Action的生命周期(每个Action类的对象实例会拥有一个ValueStack对象)。
 当Struts 2接收到一个.action的请求后,会先建立Action类的对象实例,但并不会调用Action方法,而是先将Action类的相应属性放到ValueStack对象的顶层节点(ValueStack对象相当于一个栈)。只是所有的属性值都是默认的值,如String类型的属性值为null,int类型的属性值为0等。
 在处理完上述工作后,Struts 2就会调用拦截器链中的拦截器,如获得请求参数的拦截器是params等,在这些拦截器内部读取相应的值,并更新ValueStack对象顶层节点的相应属性的值。
 当调用完所有的拦截器后,最后会调用Action类的Action方法,但在调用Action方法之前,会将ValueStack对象中的属性的值终值赋给Action类的相应属性。
 对于值栈,则是通过那些使用OGNL(Object Graph Navigational Language,对象图导航语言)语法所编写的特定表达式来查找,或者是在该表达式之上求值。

14、文件上传
 UploadAction.java类
 public class UploadAction extends ActionSupport {
  private List<File> upload;//上传的文件列表
  private List<String> uploadFileName;//文件的名称不能乱写,变量名= 文件变量 + FileName
  private List<String> uploadContentType;//该变量不能乱写,File对象变量+ContentType获得文件类型,由struts来填充。同上原理。
  public List<File> getUpload() {
   return upload;
  }
  public void setUpload(List<File> upload) {
   this.upload = upload;
  }
  public List<String> getUploadFileName() {
   return uploadFileName;
  }
  public void setUploadFileName(List<String> uploadFileName) {
   this.uploadFileName = uploadFileName;
  }
  public List<String> getUploadContentType() {
   return uploadContentType;
  }
  public void setUploadContentType(List<String> uploadContentType) {
   this.uploadContentType = uploadContentType;
  }
  @Override
  public String execute() throws Exception {
   if(upload!=null){
    //获得绝对目录
    String dir = ServletActionContext.getServletContext().getRealPath("upload");
    for (int i = 0; i < upload.size(); i++) {
     File file = upload.get(i);
     InputStream is = new FileInputStream(file);
     //根据要保持的文件来创建输出流
     OutputStream os = new FileOutputStream(dir + "/" + uploadFileName.get(i));
     byte[] buff = new byte[(int) file.length()];
     int len = 0;
     while((len = is.read(buff, 0, buff.length)) != -1){
      os.write(buff, 0, len);
     }
     os.close();
     is.close();
    }
   }
   return SUCCESS;
  }
 }
 index.jsp页面
   <form action="testUpload" method="post" enctype="multipart/form-data">
  <input name="upload" type="file"  /><br/>
  <input name="upload" type="file" /><br/>
  <input type="submit" value="上传"/><br/>
 </form>
 struts配置
 <package name="upload" extends="struts-default">
  <action name="testUpload" class="com.UploadAction">
   <result name="success">/index.jsp</result>
  </action>
 </package>
 <constant name="struts.multipart.saveDir" value="upload"></constant><!--表示上传文件的默认目录-->
 <constant name="struts.multipart.maxSize" value="102400000000"></constant><!--限制上传文件的大小-->

15、struts2和spring2.5整合:把struts2的创建交给spring
 需要导入struts2的包:struts2-spring-plugin.jar(用途是:在spring容器找到所需要的Action实例,通过class属性值对应bean的id来找。)
 web.xml配置文件
 <!--listener是servlet的监听器,它可以监听客户端的请求、服务器的操作等。-->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener> 
  <context-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>classpath:applicationContext.xml</param-value>
  </context-param>
  
 applicationContext.xml配置文件:监听器监听到web容器创建好了就加载applicationContext.xml,这样就加载了bean
  <bean id="loginAction" class="bean.LoginAction" scope="prototype"></bean>
  
 struts.xml配置文件:由于Action被spring创建了所以action元素的class属性值直接写bean的id就可以了
     <package name="default" extends="struts-default">
      <!--loginAction是指哪 个bean-->
      <action name="login" class="loginAction">
       <result>/index.jsp</result>
      </action>
     </package>
    
    index.jsp页面
    <form action="login" method="post" >
     <input name="username" type="text"/><br/>
     <input name="password" type="text"/><br/>
     <input type="submit"/><br/>
    </form>   
16、

 

原创粉丝点击