Java Struts2 学习

Struts2

Struts2 简介

Struts2 实战

我们主要的学习资料和代码来自how2java

Hello world!

对于一个Struts2的web项目,我们首先得配置一个web.xml。
其中,定义了一个filter过滤器,所有的请求都会通过该过滤器的过滤。

<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>
		<dispatcher>FORWARD</dispatcher>
		<dispatcher>REQUEST</dispatcher>		
		<url-pattern>/*</url-pattern>
	</filter-mapping>

</web-app>

下面是一个简单struct2配置文件:
其中,该文件告诉我们,当我们请求index的时候,给它跳转到index.jsp文件。

<?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>
  <package name="basicstruts" extends="struts-default">

  <action name="index">
    <result>index.jsp</result>
  </action>    

</package>

</struts>

将model传递给jsp

model层

一个简单的Product类:

package com.how2java.bean;
 
public class Product {
 
    int id;
    String name;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
Controllor 控制器

一个简单的ProductAction控制类:

package com.how2java.action;
 
import com.how2java.bean.Product;
 
public class ProductAction {
    private Product product;
 
    public String show() {
        product = new Product();
        product.setName("iphone7");
        return "show";
    }
 
    public Product getProduct() {
        return product;
    }
 
    public void setProduct(Product product) {
        this.product = product;
    }
}

下面是Sturts的配置文件

<?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>
  <package name="basicstruts" extends="struts-default">
  
  <action name="showProduct" class="com.how2java.action.ProductAction" method="show">
    <result name="show">show.jsp</result>
  </action>   
  
</package>
  
</struts>

一个简单的网页jsp

<%@page isELIgnored="false"%>
${product.name}

最后,启动服务器,访问网站:
在这里插入图片描述
那么这一过程发生了什么呢?

  • 用户通过浏览器访问/showProduct
  • 用户访问的方式被过滤器过滤给了struct
  • stuct发现/showProduct抛给了ProductAction控制器的show方法
  • show方法 为该类设置了Product的值,然后转到了show.jsp页面
  • show.jsp 中有${product.name}于是调用了控制器中的get方法获取product,然后获取到其名字,在我们的网页中显示出来了。

数据提交

首先是一个简单的前端表单

<html>
<form action="addProduct">
 <input type="text" name="product.name">
    <br/>
 <input type="submit" value="submit">
</form>
</html>

配置一个URL:addProduct

<action name="addProduct" class="com.how2java.action.ProductAction" method="add">
    <result name="show">show.jsp</result>
  </action>   

为我们的控制器ProductAction,添加一个add()方法:

 public String add(){
        System.out.println("product.name:"+product.getName());
        return "show";
    }

总的来说,因为提交的时候,它的提交名为product.name 所以很智能,我们的struts框架,已经调用了setProduct()方法完成了注入。

编码问题

下面以utf-8编码为例
首先是jsp文件:<%@ page language="java" contentType="text/html; charset=UTF-8"
表单使用post方法即可。

其次配置struct的编码:

<struts>
  <constant name="struts.i18n.encoding" value="UTF-8"></constant>
<\struts>

日志输出

有时候,我们遇到问题输出的信息非常有限。可以使用log4j来进行日志记录。
只需要添加这么一个配置文件即可:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration PUBLIC "-//log4j/log4j Configuration//EN" "log4j.dtd">
 
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
     
    <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
       <layout class="org.apache.log4j.PatternLayout">
          <param name="ConversionPattern" value="%d %-5p %c.%M:%L - %m%n"/>
       </layout>
    </appender>
  
    <!-- specify the logging level for loggers from other libraries -->
    <logger name="com.opensymphony">
        <level value="DEBUG" />
    </logger>
 
    <logger name="org.apache.struts2">
         <level value="DEBUG" />
    </logger>
   
   <!-- for all other loggers log only debug and above log messages -->
     <root>
        <priority value="INFO"/>
        <appender-ref ref="STDOUT" />
     </root>
     
</log4j:configuration>

获取request 和response

只需要在ProductAction 的相应处理的函数中添加下面两句即可:
其中request和response都被封装过了。

HttpServletRequest request = ServletActionContext.getRequest();
        HttpServletResponse response = ServletActionContext.getResponse();
      

获取session

Map m = ActionContext.getContext().getSession();

往session中添加属性:

Map m = ActionContext.getContext().getSession();
        m.put("name", product.getName());

文件上传

首先书写一个简单的前端页面:
其中,enctype="multipart/form-data指定了上传类型为二进制文件。

<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8" isELIgnored="false"%>
  
<%@page isELIgnored="false" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
  
<html>
<body>
 
<form action="upload" method="post" enctype="multipart/form-data">
 
  上传文件 : <input type="file" name="doc" /> <br>
  <input type="submit" value="上传">
</form>
 
</body>
</html>

下面是一个简单的上传控制器:
包含文件、文件名、文件类型三个必备属性和相关的处理方法。
框架会根据doc,匹配到三个名字,直接进行set方法注入。

package com.how2java.action;
 
import java.io.File;
import java.io.IOException;
import java.util.UUID;
 
import org.apache.commons.io.FileUtils;
import org.apache.struts2.ServletActionContext;
 
public class UploadAction {
 
    File doc;
    String docFileName;
    String docContentType;
 
    public File getDoc() {
        return doc;
    }
 
    public void setDoc(File doc) {
        this.doc = doc;
    }
 
    public String getDocFileName() {
        return docFileName;
    }
 
    public void setDocFileName(String docFileName) {
        this.docFileName = docFileName;
    }
 
    public String getDocContentType() {
        return docContentType;
    }
 
    public void setDocContentType(String docContentType) {
        this.docContentType = docContentType;
    }
 
    public String upload() {
        System.out.println(doc);
        System.out.println(docFileName);
        System.out.println(docContentType);
        return "success";
    }
}

在struts中配置相应的url配置:

<action name="upload" class="com.how2java.action.UploadAction" method="upload">
    <result name="success">success.jsp</result>
  </action>  

配置上传文件的最大值

struts中默认上传文件的最大值为2m,可以通过下面配置解决:

<constant name="struts.multipart.maxSize" value="10240000"/>

s标签

form标签

如下面表单的代码:

<%@ taglib prefix="s" uri="/struts-tags" %>
 
<html>
 
<body>
 
<s:form action="addProduct">
 
  <s:textfield name="product.name" label="product name" />
  <s:submit value="Submit" />
 
</s:form>
 
</body>
</html>

然后我们查看到,其中已经被Struts转化为table 表格了。

<form id="addProduct" name="addProduct" action="addProduct.action" method="post">
<table class="wwFormTable">
 
  <tr>
    <td class="tdLabel"><label for="addProduct_product_name" class="label">product name:</label></td>
    <td
><input type="text" name="product.name" value="" id="addProduct_product_name"/></td>
</tr>
 
  <tr>
    <td colspan="2"><div align="right"><input type="submit" id="addProduct_0" value="Submit"/>
</div></td>
</tr>
 
</table></form>

iterator 标签

首先为我们的ProductAction控制器中添加一个Product的list列表和相应的get、set方法,然后编写下面的前端页面:

相当于for循环,把返回得到的List列表展示出来。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" isELIgnored="false"%>
 
<%@ taglib prefix="s" uri="/struts-tags"%>
 
<style>
table {
    border-collapse: collapse;
}
 
td {
    border: 1px solid gray;
}
</style>
 
<table align="center">
    <tr>
        <td>id</td>
        <td>name</td>
        <td>st.index</td>
        <td>st.count</td>
        <td>st.first</td>
        <td>st.last</td>
        <td>st.odd</td>
        <td>st.even</td>
 
    </tr>
 
    <s:iterator value="products" var="p" status="st">
        <tr>
            <td>${p.id}</td>
            <td>${p.name}</td>
            <td>${st.index}</td>
            <td>${st.count}</td>
            <td>${st.first}</td>
            <td>${st.last}</td>
            <td>${st.odd}</td>
            <td>${st.even}</td>
        </tr>
    </s:iterator>
 
</table>

check标签

在ProductAction中添加一个int类型的选择List列表,然后在前端中会选择int列表中的id。
下面是一个简单的checklist展示:

  • value:哪些被选中
  • name:提交到服务端用的名称
  • list:用于遍历的集合
  • listValue:显示的checkbox的名称
  • listKey:checkbox的value
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" isELIgnored="false"%>
 
<%@ taglib prefix="s" uri="/struts-tags"%>
 
<%@page isELIgnored="false"%>
 
<s:checkboxlist value="selectedProducts" name="product.id"
    list="products" listValue="name" listKey="id" />

radio 标签

上面实现了一个简单的多选框,下面是一个单选框的实现。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" isELIgnored="false"%>
 
<%@ taglib prefix="s" uri="/struts-tags"%>
 
<%@page isELIgnored="false"%>
 
<s:radio name="product.id" value="2" list="products" listValue="name"
    listKey="id" />

select 标签

除了radio的简单实现,下面展示一下select的简单实现。
有两个新属性注意一下:

  • multiple:true表示可以选中多行
  • size="3"表示默认显示3行
<s:select label="products"
       name="product.id"
       list="products"
       listKey="id"
       listValue="name"
       multiple="true"
       size="3"
       value="selectedProducts"
/>

多重iterator 遍历

如之前的Category 包含了很多Product,其实应该不难。

<table border="1" cellspacing="0">
 
    <tr>
        <td>id</td>
        <td>name</td>
        <td>products</td>
    </tr>
     
    <s:iterator value="categories" var="c">
        <tr>
            <td>${c.id}</td>
            <td>${c.name}</td>
            <td>
                <s:iterator value="#c.products" var="p">
                    ${p.name}<br/>
                </s:iterator>        
            </td>
        </tr>
    </s:iterator>
 
</table>
 
<s:debug/>

调试

调试页面

需要导入相应的jar包。
登陆http://127.0.0.1:8080/struts/config-browser/actionNames之类,即可看到我们配置了哪些action。

前端调试

添加<s:debug/>在末尾,即可看到很多调试信息。

其他

通配符

所有以Prodcut结尾的URL的action都会被匹配,匹配的方法使用{1}为第一个*的内容。即如addProduct使用add的方法。

<action name="*Product" class="com.how2java.action.ProductAction" method="{1}">
    <result name="show">show.jsp</result>
    <result name="list">list.jsp</result>
  </action>   

拦截器

通过创建一个拦截器,给它拦截下来,然后添加一个日期属性。

package com.how2java.interceptor;
 
import java.util.Date;
 
import com.how2java.action.ProductAction;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
 
public class DateInterceptor extends AbstractInterceptor {
 
    public String intercept(ActionInvocation invocation) throws Exception {
       ProductAction action = (ProductAction)invocation.getAction();
       action.setDate(new Date());
       return invocation.invoke();
    }
}

然后按照下面的配置,配置我们的拦截器给ProductAction即可:
首先是创建一个拦截器。
由于添加了新的拦截器, 默认拦截器失效了,所以给它补充回去。

<?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.i18n.encoding" value="UTF-8"></constant>
 
    <package name="basicstruts" extends="struts-default">
        <interceptors>
            <interceptor name="dateInterceptor" class="com.how2java.interceptor.DateInterceptor" />
        </interceptors>
 
        <action name="*Product*" class="com.how2java.action.ProductAction"
            method="{1}">
            <interceptor-ref name="dateInterceptor" />
            <interceptor-ref name="defaultStack" />  
            <result name="show">show.jsp</result>
            <result name="list">list.jsp</result>
        </action>
 
    </package>
 
</struts>

客户端跳转(重定向)

在控制器中添加:

  public String addPage(){
        return "addPage";
    }

然后在配置文件配置一下即可:

<action name="addPageProduct" class="com.how2java.action.ProductAction" method="addPage">
    <result name="addPage" type="redirect">addProduct.jsp</result>
  </action> 

当我们输入URL:addPageProduct,抛给控制器的addpage函数,addpage返回结果,重定向给addProduct.jsp。

重定向传参

添加一个name属性:

private String name;
     
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }

重定向的url中传入特定的参数:

 <result name="addPage" type="redirect">addProduct.jsp?name=${name}</result>

表单验证

添加一个验证的函数:

public void validate(){
        if ( product.getName().length() == 0 ){
            addFieldError( "product.name", "name can't be empty" );
        }
    }  

然后添加一个错误返回的网页:

<result name="input">addProduct.jsp</result>

如果,验证失败,那么会直接跳转到input,其中的过程,struts自动生成。

通过xml来实现表单验证

下面是一个表单验证的配置文件:
使用的文件命名方法为:{actionname}-validation.xml

<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator 1.0.2//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
 <validator type="requiredstring">
    <param name="fieldname">product.name</param>
    <message>name is required.</message>
 </validator>
</validators>

action多实例

在我们每一次访问页面的过程中,struts默认地都会生成不同的对象实例来执行action的功能。

注解

首先将配置文件中的包的内容给注释掉。

示例

@Namespace("/"):表示URL的根路径。
@ParentPackage("struts-default"):表示设置一个默认的拦截器。
@Results({@Result(name="show", location="/show.jsp"), @Result(name="home", location="/index.jsp")}):表示返回值对应的资源路径。
@Action("showProduct"):action行为showProduct,对应的函数。

package com.how2java.action;
 
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
 
import com.how2java.bean.Product;
 
@Namespace("/")
@ParentPackage("struts-default")
@Results({@Result(name="show", location="/show.jsp"),
        @Result(name="home", location="/index.jsp")})
 
public class ProductAction {
    private Product product;
    @Action("showProduct")
    public String show() {
        product = new Product();
        product.setName("iphone7");
        return "show";
    }
 
    public Product getProduct() {
        return product;
    }
 
    public void setProduct(Product product) {
        this.product = product;
    }
}

参考

主要资料和代码来源

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值