Struts当中Action的用法研究及实例代码分析,使用三种作用域分别传递参数

Test-actionContext.jsp的页面代码

clip_image001

网页显示效果

clip_image003

拦截器处理参数传递的代码

clip_image005

这个是最关键的,必须要得到对象

,通过ActionContext容器对象的getContext()方法

然后添加三种容器分别对应的Map对象.

ApplicationMap用getApplication方法

SessionMap用getSession方法

RequestMap用get(“request”)方法.

设置值都很简单,用Map集合的put方法就行.

附完整代码:

Index.jsp

<%–

Created by IntelliJ IDEA.

User: 18010

Date: 2018/6/22

Time: 18:24

To change this template use File | Settings | File Templates.

–%>

<%@ page contentType=”text/html;charset=UTF-8″ language=”java” %>

<html>

<head>

<title>首页</title>

</head>

<body>

<h1>Struts中的Action详解及测试</h1>

<a href=”TestActionContext.action?name=atguigu”>Test ActionContext</a>

<br>

<br>

</body>

</html>

TestActionContextAction.java

package com.atguigu.struts2.action;

import com.opensymphony.xwork2.ActionContext;

import java.util.Map;

public class TestActionContextAction {

public String execute(){

ActionContext actionContext=ActionContext.getContext();//得到对象

//获取对应的map并添加对象

Map<String,Object> applicationMap=actionContext.getApplication();

//设置属性

//applicationMap.put(“applicationKey”,”applicationValue”);

applicationMap.put(“applicationKey”,”通过applicationMap设置的值能够被全局引用”);

//获取一个时间的属性

Object date=applicationMap.get(“date”);

System.out.println(“时间:”+date);

//测试

System.out.println(applicationMap.values());

//利用session来设置属性

Map<String ,Object> sessionMap=actionContext.getSession();

sessionMap.put(“sessionKey”,”通过session设置的值”);

System.out.println(sessionMap.getClass());

//通过request来设置属性

Map<String ,Object> requestMap= (Map<String, Object>) actionContext.get(“request”);

requestMap.put(“requestKey”,”通过request设置的值”);

//这个值是一个数组

Map<String,Object> parameters=actionContext.getParameters();

//返回执行结果

return “success”;

}

}

Test-actionContext.jsp

<%–

Created by IntelliJ IDEA.

User: 18010

Date: 2018/6/22

Time: 18:49

To change this template use File | Settings | File Templates.

–%>

<%@ page contentType=”text/html;charset=UTF-8″ language=”java” %>

<html>

<head>

<title>actionContext测试</title>

<style type=”text/”>

</style>

</head>

<body>

<h4>Test ActionContext Page</h4>

<table align=”center”>

<tr>

<th>application: </th>

<td>${applicationScope.applicationKey}</td>

</tr>

<tr>

<th>

session:

</th>

<td>

${sessionScope.sessionKey}

</td>

</tr>

<tr>

<th>

request:

</th>

<td>

${requestScope.requestKey}

</td>

</tr>

</table>

<br>

<br>

</body>

</html>

配置文件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>

<!–配置Struts可以受理的请求的扩展名–>

<constant name=”struts.action.extension” value=”action,do,”></constant>

<package name=”default” namespace=”/” extends=”struts-default”>

<action name=”TestActionContext”

class=”com.atguigu.struts2.action.TestActionContextAction”>

<result name=”success”>/test-actionContext.jsp</result>

</action>

</package>

</struts>

完整的Struts2入门案例,附完整源代码

说明:

Struts2比Struts1优秀了很多,总得来说,这就是一个写好了很多通用功能提供给我们调用的框架,帮我们节省了很多写重复代码的时间.

这个案例依旧是一个表单案例,实现的思路非常简单,我这里画图进行分析.

clip_image002

几乎没有任何技术难度,所以特别适合Struts2的入门,作为第一次学习并体验的我,真的感受到了框架的强大,只需要简单的几个配置,根本不用写太多的代码,神器之说,莫过于如此.

有了框架,我们只需要专注于功能的实现就行了.

这里对源码进行分析一下.

这个案例总共用到5个页面,贴一下目录结构图.

clip_image003

下面分别说一下每个页面的功能和代码:

Index.jsp

首页,这个很简单,就是一个超链接,通过拦截器处理以后转发到input.jsp页面

源代码:

<%–

Created by IntelliJ IDEA.

User: 18010

Date: 2018/6/21

Time: 20:10

To change this template use File | Settings | File Templates.

–%>

<%@ page contentType=”text/html;charset=UTF-8″ language=”java” %>

<html>

<head>

<title>$Title$</title>

</head>

<body>

<a href=”product-input.action”>Product Input</a>

<br><br>

<a href=”test.action”>Test</a>

</body>

</html>

Input.jsp

表单填写页面,这个就是一个简单表单,通过拦截器处理以后转发到details.jsp

完整源码:

<%–

Created by IntelliJ IDEA.

User: 18010

Date: 2018/6/21

Time: 21:07

To change this template use File | Settings | File Templates.

–%>

<%@ page contentType=”text/html;charset=UTF-8″ language=”java” %>

<html>

<head>

<title>input</title>

</head>

<body>

<form action=”product-save.action” method=”post”>

ProductName: <input type=”text” name=”productName”>

<br><br>

ProductDesc: <input type=”text” name=”productDesc”>

<br><br>

ProductPrice: <input type=”text” name=”productPrice”>

<br><br>

<input type=”submit” name=”Submit”>

<br><br>

</form>

</body>

</html>

Details.jsp

这个页面是表单信息展示页面,没有复杂的代码,只是对对象类的内容进行了展示.

完整代码:

<%–@elvariable id=”productId” type=””–%>

<%–

Created by IntelliJ IDEA.

User: 18010

Date: 2018/6/21

Time: 21:07

To change this template use File | Settings | File Templates.

–%>

<%@ page contentType=”text/html;charset=UTF-8″ language=”java” %>

<%–<%@taglib prefix=”s” uri=”/struts-tags” %>–%>

<html>

<head>

<title>details</title>

</head>

<body>

ProductId: ${productId}

<br><br>

ProductName: ${productName}

<br><br>

ProductDesc: ${productDesc}

<br><br>

ProductPrice: ${productPrice}

<br><br>

</body>

</html>

Product.java

这是一个对象类,里面声明了一个save方法,可以当做是简单的拦截器方法.

完整代码:

package com.lxgyx.helloworld;

public class Product {

private Integer productId;

private String productName;

private String productDesc;

private double productPrice;

public Integer getProductId() {

return productId;

}

public void setProductId(Integer productId) {

this.productId = productId;

}

public String getProductName() {

return productName;

}

public void setProductName(String productName) {

this.productName = productName;

}

public String getProductDesc() {

return productDesc;

}

public void setProductDesc(String productDesc) {

this.productDesc = productDesc;

}

public double getProductPrice() {

return productPrice;

}

public void setProductPrice(double productPrice) {

this.productPrice = productPrice;

}

@Override

public String toString() {

return “Product{” +

“productId=” + productId +

“, productName='” + productName + ‘\” +

“, productDesc='” + productDesc + ‘\” +

“, productPrice=” + productPrice +

‘}’;

}

public String save(){

System.out.println(“save:”+this);

return “details”;

}

public String test(){

System.out.println(“Test”);

return “success”;

}

public Product(){

System.out.println(“Product’s constructor”);

}

}

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: 包. struts2 使用 package 来组织模块.

name 属性: 必须. 用于其它的包应用当前包.

extends: 当前包继承哪个包, 继承的, 即可以继承其中的所有的配置. 通常情况下继承 struts-default

struts-default 这个包在 struts-default.xml 文件中定义.

namespace 可选, 如果它没有给出, 则以 / 为默认值.

若 namespace 有一个非默认值, 则要想调用这个包里的Action,

就必须把这个属性所定义的命名空间添加到有关的 URI 字符串里

http://localhost:8080/contextPath/namespace/actionName.action

–>

<package name=”helloWorld” extends=”struts-default”>

<!–

配置一个 action: 一个 struts2 的请求就是一个 action

name: 对应一个 struts2 的请求的名字(或对一个 servletPath, 但去除 / 和扩展名), 不包含扩展名

class 的默认值为: com.opensymphony.xwork2.ActionSupport

method 的默认值为: execute

result: 结果.

–>

<action name=”product-input”

class=”com.opensymphony.xwork2.ActionSupport”

method=”execute”>

<!–

result: 结果. 表示 action 方法执行后可能返回的一个结果. 所以一个 action 节点可能会有多个 result 子节点.

多个 result 子节点使用 name 来区分

name: 标识一个 result. 和 action 方法的返回值对应. 默认值为 success

type: 表示结果的类型. 默认值为 dispatcher(转发到结果.)

–>

<result name=”success” type=”dispatcher”>/WEB-INF/pages/input.jsp</result>

</action>

<action name=”product-save” class=”com.atguigu.struts2.helloworld.Product”

method=”save”>

<result name=”details”>/WEB-INF/pages/details.jsp</result>

</action>

<action name=”test” class=”com.atguigu.struts2.helloworld.Product” method=”test”>

<result>/index.jsp</result>

</action>

</package>

</struts>

clip_image005

从批量转移选择器内容总结一下JS的使用技巧和基本思路,附实例和源代码

选择器源代码

clip_image002

这个太简单,没什么好说的,本文主要讲一下JS的使用技巧和基本思路

首先来看双击右移选择器内容的代码

clip_image004

总共就三行代码.

1. 添加双击事件

2. 通过索引找到选中的项

3. 转移被选中的项

思路非常清晰,总的来说就是给选择器添加一个双击被选中的索引就转移到另一个选择器.

注意:

这里的appendChild是转移子元素的意思,而不是附加的意思.

所谓转移,就是直接移动了,原来的就不存在了,而附加就是复制的意思,两者不一样.

通过这个简单的例子,我们得到简单的思路,下面复杂一点.

批量右移:

clip_image006

批量右移稍微复杂一点,因为选择的不是一个元素,多个元素通用思路就是用数组.

这里的却用到了数组.

先分析一下这个程序的思路.

1. 对批量右移这个按钮添加一个单击事件

2. 得到要转移的选择器对象,这里通过id找到

3. 得到选择器里面的所有元素的一个数组并得到其长度

4. 遍历整个数组

5. 得到数组中被选中的元素的索引

6. 将所有被选中的元素转移到目标选择器

这里需要注意的是被选中元素一定要是索引,也就是说必须用selectedIndex而不是selected,否则就会不报错但是达不到效果.

这里我有个粗浅的看法,那就是这里既然是数组,那么元素类型都是数,selectedIndex满足元素类型,而selected不满足.所以才有这种结果.

下面是全部转移的源代码,更简单

clip_image008

思路

1. 对按钮添加点击事件

2. 得到选择器

3. 得到选择器所有元素 .options

4. 得到选择器元素数组长度

5. 遍历并全部转移 这里的数组索引填[0]而不是[i],这点我暂时还没有搞明白,不过java中很多程序也是这样写的,先记着就行.

Ok,附上完整源代码,喜欢的朋友新建一个html文件直接复制粘贴,然后参考一下:

<!DOCTYPE html>

<html lang=”en”>

<head>

<meta charset=”UTF-8″>

<title>test</title>

</head>

<body>

<div>

<select name=”leftID” id=”leftID” multiple size=”10″ >

<option value=””>选项A</option>

<option value=””>选项B</option>

<option value=””>选项C</option>

<option value=””>选项D</option>

<option value=””>选项E</option>

<option value=””>选项F</option>

<option value=””>选项G</option>

<option value=””>选项H</option>

<option value=””>选项I</option>

<option value=””>选项J</option>

</select>

</div>

<div style=”position: absolute;left: 100px;top: 40px;”>

<input type=”button” value=”批量右移” id=”rightMoveID”>

</div>

<div style=”position: absolute;left: 100px;top: 70px;”>

<input type=”button” value=”全部右移” id=”rightMoveAllID”>

</div>

<div style=”position: absolute;left: 100px;top: 100px;”>

<input type=”button” value=”批量左移” id=”leftMoveID”>

</div>

<div style=”position: absolute;left: 100px;top: 130px;”>

<input type=”button” value=”全部左移” id=”leftMoveAllID”>

</div>

<div style=”position: absolute;left: 100px;top: 160px;”>

<input type=”button” value=”左边颠倒” id=”leftReverseAllID”>

</div>

<div style=”position: absolute;left: 220px;top: 20px;”>

<select name=”rightID” id=”rightID” multiple size=”10″ style=”width: 60px;”></select>

</div>

<script type=”text/javascript”>

//双击右移

document.getElementById(“leftID”).ondblclick=function () {

var optionElement=this[this.selectedIndex];//通过索引找到所有被选中的项

document.getElementById(“rightID”).appendChild(optionElement);//在右边添加子元素

}

//批量右移

document.getElementById(“rightMoveID”).onclick=function () {

var leftSelectElement=document.getElementById(“leftID”);//得到”leftID”这个选择器的对象

var leftOptionElementArray=leftSelectElement.options;//这个得到选择器里面的所有元素的一个数组

var size=leftOptionElementArray.length;//得到数组长度

for (var i = 0; i < size; i++) {

//取得选中的<option>元素

var leftOptionElement=leftSelectElement[leftSelectElement.selectedIndex];//数组中被选中的索引

document.getElementById(“rightID”).appendChild(leftOptionElement);//将被选中的元素赋值给右边

}

}

//全部右移

document.getElementById(“rightMoveAllID”).onclick=function () {//给按钮添加点击事件

var leftSelectElement=document.getElementById(“leftID”);//左边选择器

var leftOptionElementArray=leftSelectElement.options;//选择器所有元素

var size=leftOptionElementArray.length;

for (var i= 0; i < size; i++) {

document.getElementById(“rightID”).appendChild(leftOptionElementArray[0]);

//将左边所有元素赋值给右边所有元素

}

}

//appendChild是一种转移元素的方式,而不是复制的方式,这点需要注意

//双击左移

/*

* 步骤分析:

* 1添加点击事件

* 2得到选择器

* 3得到选择器所有元素

* 4得到选择器的长度

*

* 遍历整个选择器数组,转移需要转移的元素

* */

//要实现双击左移,先添加双击事件dbonclick

document.getElementById(“rightID”).ondblclick=function () {//右边选择器双击事件

//得到被双击的元素

var optionElement=this[this.selectedIndex];//被选中的元素

//转移到左边

document.getElementById(“leftID”).appendChild(optionElement);

}

//批量左移

//对”批量左移”添加单击事件

document.getElementById(“leftMoveID”).onclick=function () {

//得到被选中的选择器

var rightSelectElement=document.getElementById(“rightID”);//右边的选择器

//得到选择器中的所有元素

var rightOptionElementArray=rightSelectElement.options;//元素数组

//得到数组的长度

var size=rightOptionElementArray.length;

//遍历数组

for (var i = 0; i < size; i++) {

//将所有被选中的元素转移到左边

//得到被选中的元素 选择器中被选择的索引,数组只是为了得到长度

var leftOptionElement=rightSelectElement[rightSelectElement.selectedIndex];

//选中的元素索引,而不是元素,填元素错了

//转移被选中的元素

document.getElementById(“leftID”).appendChild(leftOptionElement);

}

}

//全部左移

//对全部左移添加单击事件

document.getElementById(“leftMoveAllID”).onclick=function () {

//得到选择器

var rightSelectOptions=document.getElementById(“rightID”);

//得到选择器中的所有元素

var rigtOptions=rightSelectOptions.options;

//得到数组长度

var size=rigtOptions.length;

for (var i = 0; i < size; i++) {

//全部转移

document.getElementById(“leftID”).appendChild(rigtOptions[0]);

}

//alert(“啊啊”);

}

</script>

</body>

</html>

clip_image010

jQuery显示-隐藏图片的小案例,适合入门

这个案例代码很少,主要讲解jQuery这个框架的用法,初学者一定要注意,jQuery第一个字母是小写的,一旦大小,不会报错,但是会出不来效果.

这是一个显示和隐藏图片的小案例.

点击显示,就会显示图片:

image

点击隐藏,就会隐藏图片

image

这样的功能一旦配合时间函数用起来就能够达到很多很厉害的效果了,所以不要小看了这个功能.

这个功能用到了两个函数,一个是show(),另一个是hidden();

函数方法和java语言非常类似,直接.方法名就行

在使用jQuery框架之前,需要先引入jQury,然后创建一个关于jQuery的实例.

语法是:

var person=new jQuery();

image

完整源码:

<!DOCTYPE html>

<html lang=”en”>

<head>

<meta charset=”UTF-8″>

<title>显示隐藏案例</title>

<script src=”js/jquery-1.0.js”></script>

<link rel=”stylesheet” href=”css/showHidden_test.css”>

</head>

<body>

<div class=”myClass”>

<img src=”images/zgl.jpg” height=”220″ width=”200″/></div>

<div class=”myClass1″>

<input type=”button” value=”显示” id=”showID”>

<input type=”button” value=”隐藏” id=”hiddenID”>

</div>

<script type=”text/javascript”>

//创建对象

var person=new jQuery();//这里是小写的j 一定要注意

//单击显示按钮

$(“showID”).onclick=function () {

//调用方法

person.show();

}

//单击隐藏按钮

$(“hiddenID”).onclick=function () {

//调用方法

person.hidden();

}

</script>

</body>

</html>

利用Js来对表单进行验证的注册页面小案例,附完整源码和讲解

利用JS来对表单进行验证.

在Struts框架当中,都是用Validation这个工具类来验证的,需要自己配置,不过实际开发中,一般都是通过JS来进行验证.

这里举一个例子:

我写了两个页面,一个Html页面,用来显示,表达,一个Js页面,用来控制表单数据验证.

附上源代码,供大家参考学习.

html源代码

image

完整源码(可直接复制粘贴)

<!DOCTYPE html>

<html lang=”en”>

<head>

<meta charset=”UTF-8″>

<title>register</title>

<script src=”js/validateForm_test.js”></script>

</head>

<body>

<form action=”#” method=”post” name=”myform”>

<table align=”center” border=”1″>

<caption><h3>基于JS的验证</h3></caption>

<tr>

<th>用户名</th>

<td>

<input type=”text” name=”username”>

</td>

</tr>

<tr>

<th>密码</th>

<td>

<input type=”password” name=”password”>

</td>

</tr>

<tr>

<th>邮箱</th>

<td>

<input type=”text” name=”email”>

</td>

</tr>

<tr>

<td colspan=”2″ align=”center”>

<input type=”submit” value=”提交”>

</td>

</tr>

</table>

</form>

</body>

</html>

JS页面核心源码

image

完整源码(可直接复制粘贴)

function validateForm(){

var flag=false;

//定位到第一个form元素

var formElement=document.forms[0];

//依次取出用户名,密码和邮箱

var username=trim(formElement.username.value);

var password=trim(formElement.password.value);

var email=trim(formElement.email.value);

//判断用户名必填

if (username.length==0){

alert(“用户名必填”);

//将光标定位于用户名输入框

formElement.username.focus();

}else if (!/^[a-zA-Z0-9]+$/.test(username)){

alert(“用户名必须是英文数字”);

} else if (password.length==0){

alert(“密码必填”);

} else if (!/^[0-9]{6}$/.test(password)){

alert(“密码必须是6位数字”);

} else if (email.length==0){

alert(“邮箱必填”);

} else if (!/^\w+@+(\.\w+)+$/.test(email)){

alert(“邮箱格式不合法”);

} else {

alert(“可以提交”);

flag=true;

}

return flag;

}

//自定一个去空格的函数

function trim(s) {

s=s.replace(/^\s*$/,””);

return s;

}

//当该页面一加载,就会出发该匿名函数

window.onload=function () {

var myform=document.forms[0];

myform.onsubmit=validateForm;//这里不能填括号

}

最后这个匿名函数一定要注意,myform.onsubmit=validateForm;是没有括号的,一定要注意,一旦加上括号,就等于直接在加载的时候调用函数,会不断弹出”用户名不能为空”的提示.原因是页面加载的时候没有任何数据就进行了验证.

希望大家喜欢,创业和学习都不容易,支持我的朋友麻烦打赏一下.

Struts1回显表单数据,解决中文乱码,重复提交等技巧

*1 struts1标签回显表单项数据

a)传统方式数据回显:

<input ${fn:contains(fn:join(registerForm.likes,”#”),”sing”)==true?’checked’:”}

type=”checkbox” name=”likes” value=”sing”/>唱歌

b)使用struts1标签来完成数据回显:

>>将register.jsp中的所有标签使用struts1的html标签,例如:<html:form/>,<html:text/>….

c)struts1的标签不是一个基本标签,底层都是处理类,在使用struts1标签时,可以省略当前web应用的名称和请求的扩展名

d)原理

<html:form/>标签会自动从域中检索ActionForm,如果域中没有ActionForm,则会创建一个空的ActioForm,再将数据

装入ActionForm中;如果有,由以”BEAN”为关键字,取出ActionForm,由<html:text/>之类的标签取得数据进行回显

通常<html:form/>和<html:text/>配合使用

可以明显的发现,完全不用掌握EL表达式的知识,也不用掌握Jsp脚本语言的知识,简单的时候用Struts标签就能够实现强大的表单效果.

*2 struts1中文乱码解决方案

a)Filter

filter-name

filter-class

url-pattern

b)扩展ActionServlet,覆写doXxxx()方法,要在web.xml文件中配置

需要在web.xml修改核心控制器

c)扩展RequestProcessor,覆写process()方法,要在struts-config.xml文件中配置

<controller processorClass=”cn.itcast.web.struts1.core.MyRequestProcessor”/>

注意:项目中,通常不采用该二种做法

d)ActionForm的何作用

请求参数收集器/参数验证器/doXxx()编码转换器

e)通过ActionForm来完成编码转换

reset(post)

setXxxx(get)

clip_image002

*3 表单重复提交

开发步骤:

a)用户首先访问Action,在该Action中,通过this.saveToken(request);

b)在Jsp中使用<html:form/>标签,该标签具有自动发送隐藏数据的功能

c)在处理的Action中,使用this.isTokenValid(request)判段表单是否重复提交,true表示成功,false表示重复提交

d)在提交成功后,通过this.resetToken(request)删除HttpSession中原标识符的值

e)request.getSession()和request.getSession(false)

含义如下:如果使用空参方法创建session,表示一定会返回session

如果使用false参数的方法创建session,表示有可能返回null

*4 表单数据业务逻辑校验

a)在Action中的验证,称之为业务逻辑检证

b)当通过JS方法传中文时,一定在通过encodeURI()对中文编码,在Action中,通过URL解码

c)项目中,每种不同的业务使用各自独立的ActionForm

5 使用DispatchAction

a)当需要在一个Action中处理多个类似的业务方法时

b)该Action同时只能使用一个ActionForm

c)<action parameter=”method”/>表示参数的名字,对应的参数值即为Action中方法的名字

d)DispatchAction是Action的子类,因此在DispatchAction的子类中无需重写execute()方法,只需增加多个类似方法签名的

业务方法

*6 使用MappingDispatchAction

a)当需要在一个Action中处理多个类似的业务方法时,同时又需要使用1个或多个ActionForm时

b)<action parameter=”loginMethod”/>表示需要执行的业务方法

c)项目中优先使用MappingDispatchAction

clip_image004

通过Struts1自带的validate验证表单数据功能实现Ajax的效果(登录案例)

这个案例是入门以后的第一个案例,主要讲解了Struts1的Validate数据处理的用法.

先上效果图:

clip_image001

接下来说一下实现步骤.

MVC-V 第一步:先写视图

clip_image003

写一个register.jsp页面,这个页面主要负责控制注册信息,也就是用户能够直接看到的界面.写一个表单,里面包括姓名,密码,生日,邮箱,爱好,城市等信息.

上完整代码:

<%@ page language=”java” pageEncoding=”UTF-8″%>

<%@ page isELIgnored=”false” %>

<%@ page import=”org.apache.struts.action.*” %>

<%@ page import=”java.util.*” %>

<%@ page import=”com.lxgyx.struts1.domain.*” %>

<%@ taglib uri=”http://struts.apache.org/tags-html” prefix=”html” %>

<%@ taglib uri=”http://java.sun.com/jsp/jstl/core” prefix=”c” %>

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN”>

<html>

<body>

<%–

ActionErrors errors = (ActionErrors)request.getAttribute(“org.apache.struts.action.ERROR”);

if(errors!=null){

Iterator<ActionMessage> it = errors.get(“username”);

while(it.hasNext()){

ActionMessage am = it.next();

String info = am.getKey();

out.write(“<font color=’red’>”+info+”</font>”);

}

}

–%>

<form action=”${pageContext.request.contextPath}/register.do” method=”post”>

<table border=”1″ align=”center”>

<caption>用户注册(struts1版本)</caption>

<tr>

<th>用户名</th>

<td><input type=”text” name=”username” value=”${registerForm.username}”/></td>

<td>

<html:errors property=”username”/>

</td>

</tr>

<tr>

<th>密码</th>

<td><input type=”password” name=”password1″/></td>

<td>

<html:errors property=”password1″/>

</td>

</tr>

<tr>

<th>确认密码</th>

<td><input type=”password” name=”password2″/></td>

<td>

<html:errors property=”password2″/>

</td>

</tr>

<tr>

<th>性别</th>

<td>

<input checked type=”radio” name=”gender” value=”male”/>男

<input type=”radio” name=”gender” value=”female”/>女

</td>

</tr>

<tr>

<th>生日</th>

<td>

<input type=”text” name=”birthday”/>

</td>

<td>

<html:errors property=”birthday”/>

</td>

</tr>

<tr>

<th>城市</th>

<td>

<select name=”city”>

<c:forEach var=”city” items=”<%=City.values()%>”>

<option value=”${city.value}”>${city.desc}</option>

</c:forEach>

</select>

</td>

<td>

<html:errors property=”city”/>

</td>

</tr>

<tr>

<th>月收入</th>

<td>

<input type=”text” name=”income”/>

</td>

<td>

<html:errors property=”income”/>

</td>

</tr>

<tr>

<th>爱好</th>

<td>

<c:forEach var=”like” items=”<%=Like.values()%>”>

<input type=”checkbox” name=”like” value=”${like.value}”/>${like.desc}

</c:forEach>

</td>

<td>

<html:errors property=”like”/>

</td>

</tr>

<tr>

<th>邮箱</th>

<td>

<input type=”text” name=”email”/>

</td>

<td>

<html:errors property=”email”/>

</td>

</tr>

<tr>

<td colspan=”2″ align=”center”>

<input type=”submit” value=”提交”/>

</td>

</tr>

</table>

</form>

</body>

</html>

MVC-M 第二步:再写模型

由于这个表单信息较多,所以用了三个模型来控制.

分别是:

1. City用来存储城市信息

源码截图:

clip_image004

这个是一个枚举类,枚举类用enum表示而不是用class

写枚举类的基本步骤

先写枚举值->再写枚举键值对->再设置键值对的get方法

完整源码:

package com.lxgyx.struts1.domain;

public enum City {

bj(“bj”,”北京”),

sh(“sh”,”上海”),

sz(“sz”,”深圳”),

gz(“gz”,”广州”),

tj(“tj”,”天津”);

private String value;

private String desc;

City(String value, String desc) {

this.value = value;

this.desc = desc;

}

public String getValue() {

return value;

}

public String getDesc() {

return desc;

}

}

2. Like 用来存储兴趣爱好

源码截图:

clip_image005

完整源码:

package com.lxgyx.struts1.domain;

public enum Like {

//自定义枚举类

read(“read”,”阅读”),sing(“sing”,”唱歌”),

dance(“dance”,”跳舞”),net(“net”,”跳舞”),play(“play”,”游戏”);

private String value;//传到后台的值

private String desc;//传到前台显示的值

Like(String value, String desc) {

this.value = value;

this.desc = desc;

}

public String getValue() {

return value;

}

public String getDesc() {

return desc;

}

}

3. Student 用来存储学生基本信息

源码截图:

clip_image006

完整源码:

package com.lxgyx.struts1.domain;

public class Student {

public Student() {

}

private int id;

private String username;

private String password;

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

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;

}

}

MVC-C 第三步:最后写控制器

控制器有两个,一个是RegisterForm.java,这个控制器主要作用是像对象模型一样的东西,同时也具有验证数据的功能.

源码较多,直接上完整源码:

package com.lxgyx.struts1.form;

import com.lxgyx.struts1.domain.City;

import com.lxgyx.struts1.domain.Like;

import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;

import org.apache.struts.action.ActionErrors;

import org.apache.struts.action.ActionForm;

import org.apache.struts.action.ActionMapping;

import org.apache.struts.action.ActionMessage;

import org.apache.taglibs.standard.lang.jstl.ELEvaluator;

import javax.servlet.http.HttpServletRequest;

import java.util.Locale;

//参数收集器

//参数格式验证器

public class RegisterForm extends ActionForm {

private String username;

private String password1;

private String password2;

private String birthday;

private String city;

private String income;

private String[] like;

private String email;

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

public String getPassword1() {

return password1;

}

public void setPassword1(String password1) {

this.password1 = password1;

}

public String getPassword2() {

return password2;

}

public void setPassword2(String password2) {

this.password2 = password2;

}

public String getBirthday() {

return birthday;

}

public void setBirthday(String birthday) {

this.birthday = birthday;

}

public String getCity() {

return city;

}

public void setCity(String city) {

this.city = city;

}

public String getIncome() {

return income;

}

public void setIncome(String income) {

this.income = income;

}

public String[] getLike() {

return like;

}

public void setLike(String[] like) {

this.like = like;

}

public String getEmail() {

return email;

}

public void setEmail(String email) {

this.email = email;

}

@Override

public ActionErrors validate(ActionMapping mapping,

HttpServletRequest request) {

//创建一个错误消息的集合

ActionErrors errors=new ActionErrors();

//用户名[必填+英文数字]

if (this.username!=null&&this.username.trim().length()>0){

if (this.username.matches(“[a-zA-Z0-9]+]”)){

;

}else {

ActionMessage am=new ActionMessage(“username.english”,true);

errors.add(“username”,am);

}

}else{

//创建一个错误消息

ActionMessage am=new ActionMessage(“username.required”,true);

//将错误信息加入集合

errors.add(“username”,am);

}

//密码1[必填+6位数字]

if (this.password1!=null&&this.password1.trim().length()>0){

if (this.password1.matches(“[0-9]{6}”)){

;

}else{

ActionMessage am=new ActionMessage(“password1.number”,true);

errors.add(“password1”,am);

}

}else{

ActionMessage am=new ActionMessage(“password1.required”,true);

errors.add(“password1”,am);

}

//密码2[必填+6位数字 与password1相同]

if (this.password2!=null&&this.password2.trim().length()>0){

if (this.password2.matches(“[0-9]{6}”)){

if (this.password2.equals(password1)){

}else {

ActionMessage am=new ActionMessage(“二次密码不一致”,false);

errors.add(“password2”,am);

}

}else{

ActionMessage am=new ActionMessage(“password2.number”,true);

errors.add(“password2”,am);

}

}else {

ActionMessage am=new ActionMessage(“password2.required”,true);

errors.add(“password2”,am);

}

//生日[必填+符合yyyy-MM-dd格式]

if (this.birthday!=null&&this.birthday.trim().length()>0){

try {

DateLocaleConverter dlc=new DateLocaleConverter(Locale.CHINA);

dlc.convert(this.birthday);

}catch (Exception e){

ActionMessage am=new ActionMessage(“生日格式非法”,false);

errors.add(“birthday”,am);

}

}else {

ActionMessage am=new ActionMessage(“生日必填”,false);

errors.add(“birthday”,am);

}

//收入[必填+每位必须是数字]

if (this.income!=null&&this.income.trim().length()>0){

if (this.income.matches(“[0-9]{4}”)){

;

}else {

ActionMessage am=new ActionMessage(“收入必须是数字”,false);

errors.add(“income”,am);

}

}else {

ActionMessage am=new ActionMessage(“收入必填”,false);

errors.add(“income”,am);

}

//邮箱[必填=符合邮件格式]

if (this.email!=null&&this.email.trim().length()>0){

if (this.email.matches(“\\w+@\\w+(\\.+\\w+)+”)){

;

}else {

ActionMessage am=new ActionMessage(“邮箱格式非法”,false);

errors.add(“email”,am);

}

}else {

ActionMessage am=new ActionMessage(“邮箱必填”,false);

errors.add(“email”,am);

}

//爱好[必填=取值必须是枚举值之一]

if (this.like!=null&&this.email.trim().length()>0){

for (String aLike:like){

//判断该值是否是枚举值之一

try {

Like.valueOf(aLike);

}catch (Exception e){

ActionMessage am=new ActionMessage(“爱好取值非法”,false);

errors.add(“like”,am);

}

}

}else {

ActionMessage am=new ActionMessage(“爱好必选”,false);

errors.add(“like”,am);

}

//城市[必填+取值必须是枚举值之一]

if (this.city!=null&&this.city.trim().length()>0){

try {

City.valueOf(this.city);

}catch (Exception e){

ActionMessage am=new ActionMessage(“城市取值非法”,false);

errors.add(“city”,am);

}

}else {

ActionMessage am=new ActionMessage(“城市必填”,false);

errors.add(“city”,am);

}

//返回集合

return errors;

}

}

另一个是RegisterAction.java,这个是一个纯粹的控制器,控制数据的分发.

完整源码:

package com.lxgyx.struts1.action;

import com.lxgyx.struts1.form.RegisterForm;

import org.apache.struts.action.Action;

import org.apache.struts.action.ActionForm;

import org.apache.struts.action.ActionForward;

import org.apache.struts.action.ActionMapping;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

//分控制器

public class RegisterAction extends Action {

//重写execute()方法

@Override

public ActionForward execute(ActionMapping mapping,

ActionForm form,

HttpServletRequest request,

HttpServletResponse response)

throws Exception {

request.setCharacterEncoding(“UTF-8”);

//复制ActionForm强转

RegisterForm rf= (RegisterForm) form;

String username=rf.getUsername();

String password1=rf.getPassword1();

return mapping.findForward(“toSuccessJsp”);

}

}

Struts1登录案例及其源码分析

Login.jsp

clip_image002

完整代码

<%–

Created by IntelliJ IDEA.

User: 18010

Date: 2018/6/12

Time: 19:38

To change this template use File | Settings | File Templates.

–%>

<%@ page contentType=”text/html;charset=UTF-8″ language=”java” %>

<html>

<head>

<title>login</title>

</head>

<body>

<form action=”/login.do” method=”post”>

<table align=”center” border=”1″>

<caption><h1>用户登录</h1></caption>

<tr>

<th>用户名</th>

<td>

<input type=”text” name=”username”>

</td>

</tr>

<tr>

<th>密码</th>

<td>

<input type=”password” name=”password1″>

</td>

</tr>

<tr>

<th>重复密码</th>

<td>

<input type=”password” name=”password2″>

</td>

</tr>

<tr>

<td colspan=”2″ align=”center”>

<input type=”submit” value=”登录”>

</td>

</tr>

</table>

</form>

</body>

</html>

如果登录验证成功,转发到success.jsp

clip_image003

完整代码

<%–

Created by IntelliJ IDEA.

User: 18010

Date: 2018/6/12

Time: 19:38

To change this template use File | Settings | File Templates.

–%>

<%@ page contentType=”text/html;charset=UTF-8″ language=”java” %>

<%@page isELIgnored=”false” %>

<html>

<head>

<title>success</title>

</head>

<body>

欢迎${loginForm.username}登录

<br>

test

</body>

</html>

失败则转到fail.jsp页面

clip_image004

面对对象的模型 LoginForm.java

clip_image006

完整代码

package com.lxgyx.struts1.form;

import org.apache.struts.action.ActionForm;

public class LoginForm extends ActionForm {

//表单 对象模型

private String username;

private String password1;

private String password2;

public LoginForm() {

}

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

public String getPassword1() {

return password1;

}

public void setPassword1(String password1) {

this.password1 = password1;

}

public String getPassword2() {

return password2;

}

public void setPassword2(String password2) {

this.password2 = password2;

}

}

通过DB类来验证用户输入

clip_image008

通过一个分控制器来实现信息过滤

clip_image010

这个地方非常坑,笔者错了好几次.

在使用IDEA的时候,这里会有两个重写方法,一个是带Http的,一个是不带Http的,如果重写了不带Http的,不会报错,但是也不会成功.

所以,需要特别注意.

配置代码

clip_image012

Struts1框架的原理,开发流程,配置与入门案例

0 准备

a)将Servlet中大量的请求分发的代码写入一个外部文件中,便于灵活配置请求和响应资源

b)将Servlet中大量分散的方法,使用不同的分控制器类来替代,便于按类型集中控制

1 框架的定义

a)别人写好的软件,主要是从事基础性的工作,需要程序员自行修改配置,因此框架是个半成品

b)该软件是类的集合,主要为某一功能服务

c)框架只适合于一定的领域范围,Struts1框架只适合于Web领域

2 Struts1开发步骤

a)参见<<Struts1开发步骤.txt>>

1 创建day27的web应用

2 加入strust1.3相关的jar包到WEB-INF/lib/目录下(至少10个)

3 修改WEB-INF/web.xml和struts-config.xml文件

web.xml文件内容如下:

<web-app>

<servlet>

<servlet-name>action</servlet-name>

<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>

<init-param>

<param-name>config</param-name>

<param-value>/WEB-INF/struts-config.xml</param-value>

</init-param>

<load-on-startup>2</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>action</servlet-name>

<url-pattern>*.do</url-pattern>[Struts1核心控制器默认接收的请求为*.do]

</servlet-mapping>

</web-app>

struts-config.xml文件内容如下:

<struts-config>

<action-mappings>

<action

path=”/register”(用户请求的路径,/表示当前web应用,无需写.do)

type=”cn.itcast.web.struts1.action.RegisterAction”/>(该请求由哪个分控制器处理)

</action-mappings>

</struts-config>

4 写一个register.jsp页面

<form action=”/day27/register.do” method=”post”>

5 写一个分控制器RegisterAction.java,该分控制器一定要扩展Action类,覆写execute()方法

//分控制器

public class RegisterAction extends Action{

//覆写execute()方法

@Override

public ActionForward execute(

ActionMapping mapping,

ActionForm form,

HttpServletRequest request,

HttpServletResponse response)

throws Exception {

request.setCharacterEncoding(“UTF-8”);

String username = request.getParameter(“username”);

System.out.println(“用户名:” + username);

return null;

}

}

6 部置该Web应用,访问register.jsp页面

*3 自动封装用户的请求数据

开发RegisterForm的步骤:

a)写一个类扩展ActionForm

b)写实例变量,该实例变量与参数名一致,大小写不同

c)为每个实例变量提交setter和getter方法,框架会使用setter方法将参数传入,在Action中使用getter方法取

出参数值

d)在struts-config.xml文件中配置

<form-beans>

<form-bean

name=”registerForm”(RegisterForm的在域中名字)

type=”cn.itcast.web.struts1.form.RegisterForm”/>(RegisterForm的全路径名)

</form-beans>

<action-mappings>

<action

path=”/register”

type=”cn.itcast.web.struts1.action.RegisterAction”

name=”registerForm”(表示使用哪个ActionForm的名字)/>

</action-mappings>

*4 基于struts-config.xml的配置转发或重定向

return ActionForward(“需要跳转的页面”,”false表示转发”或”true表示重定向”)

ActionForm默认放置在request域中。

<action

path=”/register”

type=”cn.itcast.web.struts1.action.RegisterAction”

name=”registerForm”

scope=”request”>

<forward

name=”toSuccessJsp(与Action一致的普通字符串)”

path=”/success.jsp(跳转的真实路径)”

redirect=”false”(false转发true重写,默认为false)/>

注意:在struts-config.xml文件中,/表示当前web应用,即day27

</action>

*5 读struts源码和描述struts工作流

a)struts1的核心控制器本质上就是一个标准的HttpServlet。

b)参见<<struts1工作流.JPG和struts1代码创建图.JPG>>

clip_image002

clip_image004

clip_image006

6 struts-config.xml配置文件常用属性的使用

<action

path=“/register(用户请求的路径) 在jsp中使用“

type=“cn.itcast.RegisterAction(该请求对应的分控制器全路径)控制器的相对位置”

name=“UserFormBean(需要使用的ActionForm的名字)“

scope=”request(ActionForm放置在哪个域对象中)”

attribute=“myformbean”(绑定到域对象中ActionForm的名字,不写的话,默认与name属性值一致)

include=”welcome.jsp(包含的页面”

forward=“welcome.jsp(转发的页面) 在浏览器直接输入*.do可以转发到配置的页面“

unknown= “true(表示如果所有的path路径都配对,执行unknown为true所在的页面,类似于省略的Servlet配置)”

parameter=“method(请求参数)”类似于,href=”/day27/findAllType?method=findAllType”

classname=“<action标签底层处理类>,一般不用变”

input=”register.jsp(如果验证错误,则进入input属性所指示的页面)”

validate=”true(true表示需要验证(数据格式)ActionForm,false表示无需验证ActionForm)” >

如果验证正确,则进入Action对应的execute()方法

如果验证错误,则进入input属性所指示的页面

<forward name=”hello(跳转的字符串,与Action中一致)”

path=”/success.jsp(跳转的真实页面路径)”

redirect=”false”(跳转的方式,要么重定向,要么转发,默认false转发)/>

</action>

7 struts专用标签<html:link/>的使用

a)导入struts标签包 IDEA中会自动导入

b)在需要使用标签的jsp页面通过<@taglib%>引入

c)<html:link>标签的好处如下:

>>具有<a>标签功能

>>具有URL重写功能,即当浏览器禁用Cookie时,依然可以使用

>>具有非英文URL自动编码,自动域中检索

*8 表单项数据格式校验

a)写一个类扩展ActionForm

b)重写validate()方法

c)ActionErrors表示错误集合

d)ActionMessage(“显示的错误消息”,false)表示一个错误消息

e)ActionMessage(“显示的消息的key,value要么查询资源文件”,true)表示一个错误消息

*9 错误信息显示[传统/现代]

a)传统:

ActionErrors errors = (ActionErrors)request.getAttribute(“org.apache.struts.action.ERROR”);

if(errors!=null){

Iterator<ActionMessage> it = errors.get(“username”);

while(it.hasNext()){

ActionMessage am = it.next();

String info = am.getKey();

out.write(“<font color=’red’>”+info+”</font>”);

}

}

b)现代:

使用<html:errors/>一次性将所有的错误消息显示出来

注意:需要使用message.properties属性资源文件,在struts-config.xml文件中配置如下代码:

<message-resources parameter=”cn/itcast/web/struts1/config/message”/>

c)对于日期检证,需要使用

DateLocaleConverter dlc = new DateLocaleConverter(Locale.CHINA,”yyyy-MM-dd”);

dlc.convert(this.birthday);

思考:

1)如何对中文乱码进行处理

2)如何进行数据显示,例如:下拉框,复选框。

分而治之:

不同的控制器有不同的功能

0准备

a)将Servlet中大量的请求分发的代码写入一个外部文件中,便于灵活配置和响应需求

b)

1.框架的定义

a)别人写好的软件,主要是从事基础性工作,需要程序员做配置功能

b)该软件是类的集合,主要为某一功能服务

c)框架只适合于某一领域范围

2.Struts1的开发步骤

a)参见文末

3.自动封装用户的请求数据

开发参数收集器的步骤:

a)写一个类扩展ActionForm

b)写一个实例变量,该实例变量与参数名一致,大小写相同

c)为每个实例变量提交setter和getter方法,框架会使用setter方法将参数传入

4.基于struts-config的重定向

6.Struts的工作流程

背景:

2001年 Web框架,基础性服务 程序员在基础服务上定制服务 1.0 祖先

WebWord框架

2007,8年 Struts2框架=Struts1(40%)+WebWork(60%)[流行]

1.2

2011年 JSF框架(JavaEE5规范之一) 经过三个版本的革命 1.3

问题:

特点

好处

不足

例子:

注册

jsp-> 核心控制器->struts-config.xml

->分控制器 RegisterAction

实战:

10个lib包

开发步骤

1.创建一个day27的web应用

2.将struts1.3相关的jar包加载到lib目录下

3.修改web.xml 和struts-config.xml

注意:Struts1核心控制器默认接收的请求是*.do

1 创建day27的web应用

2 加入strust1.3相关的jar包到WEB-INF/lib/目录下(至少10个)

3 修改WEB-INF/web.xml和struts-config.xml文件

web.xml文件内容如下:

<web-app>

<servlet>

<servlet-name>action</servlet-name>

<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>

<init-param>

<param-name>config</param-name>

<param-value>/WEB-INF/struts-config.xml</param-value>

</init-param>

<load-on-startup>2</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>action</servlet-name>

<url-pattern>*.do</url-pattern>[Struts1核心控制器默认接收的请求为*.do]

</servlet-mapping>

</web-app>

struts-config.xml文件内容如下:

<struts-config>

<action-mappings>

<action

path=”/register”(用户请求的路径,/表示当前web应用,无需写.do)

type=”cn.itcast.web.struts1.action.RegisterAction”/>(该请求由哪个分控制器处理)

</action-mappings>

</struts-config>

4 写一个register.jsp页面

<form action=”/day27/register.do” method=”post”>

5 写一个分控制器RegisterAction.java,该分控制器一定要扩展Action类,覆写execute()方法

//分控制器

public class RegisterAction extends Action{

//覆写execute()方法

@Override

public ActionForward execute(

ActionMapping mapping,

ActionForm form,

HttpServletRequest request,

HttpServletResponse response)

throws Exception {

request.setCharacterEncoding(“UTF-8”);

String username = request.getParameter(“username”);

System.out.println(“用户名:” + username);

return null;

}

}

6 部置该Web应用,访问register.jsp页面

传统转发方法

request.getRequestDispatcher().forward(request,response);

struts框架的方法

配置一个action,使用false表示转发,true表示重定向

EL表达式使用方法 ${registerForm.参数}

维护的最高目标是不修改任何源代码

作业:

clip_image008

Struts2入门案列及其源码分析

1. 目录结构

clip_image001

源码文件:2个:Product对象映射文件,FilterDispatcher过滤器文件

Jsp文件3个,detail细节处理文件,input信息输入文件,index首页文件

配置文件:最重要的文件web.xml,没有这个配置文件,无法实现各种反射效果

2. 各文件源码

过滤器文件源代码

clip_image003

package com.lxgyx.struts2.helloworld;

import javax.servlet.*;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

public class FilterDispatcher implements Filter {

public FilterDispatcher() {

}

@Override

public void init(FilterConfig filterConfig) throws ServletException {

}

@Override

public void doFilter(ServletRequest servletRequest, ServletResponse

servletResponse, FilterChain filterChain) throws IOException,

ServletException {

HttpServletRequest request= (HttpServletRequest) servletRequest;

HttpServletResponse response= (HttpServletResponse) servletResponse;

//1获取servletPath

String servletPath=request.getServletPath();

System.out.println(servletPath);

String path=null;

//2判断ServletPath,若其等于”/product-input.action”,这转发到

///WEB-INF/pages/input.jsp

if (“/product-input.action”.equals(servletPath)){

path=”/WEB-INF/pages/input.jsp”;

}

//若其等于”/product-save.action”,则

if (“/product-save.action”.equals(servletPath)){

//获得请求参数

String productName=request.getParameter(“productName”);

String productDesc=request.getParameter(“productDesc”);

String productPrice=request.getParameter(“productPrice”);

//把请求信息封装为一个 Product对象

Product product=new Product(null,productName,productDesc,

Double.parseDouble(productPrice));

//执行保存操作

System.out.println(“Save Product:”+product);

product.setProductId(1001);

//把对象保存到request中.. ${param.productName} -> ${requestScope.product.productName}. ${param.productName} -> ${requestScope.product.productName}

request.setAttribute(“product”,product);

path=”/WEB-INF/pages/detail.jsp”;

}

if (path!=null){

request.getRequestDispatcher(path).forward(request,response);

return;

}

filterChain.doFilter(request,response);

}

@Override

public void destroy() {

}

}

Product映射文件源代码

clip_image005

package com.lxgyx.struts2.helloworld;

public class Product {

private Integer productId;

private String productName;

private String productDesc;

private double productPrice;

public Product() {

}

public Product(Integer productId, String productName, String productDesc,

double productPrice) {

this.productId = productId;

this.productName = productName;

this.productDesc = productDesc;

this.productPrice = productPrice;

}

public Integer getProductId() {

return productId;

}

public void setProductId(Integer productId) {

this.productId = productId;

}

public String getProductName() {

return productName;

}

public void setProductName(String productName) {

this.productName = productName;

}

public String getProductDesc() {

return productDesc;

}

public void setProductDesc(String productDesc) {

this.productDesc = productDesc;

}

public double getProductPrice() {

return productPrice;

}

public void setProductPrice(double productPrice) {

this.productPrice = productPrice;

}

@Override

public String toString() {

return “Product{” +

“productId=” + productId +

“, productName='” + productName + ‘\” +

“, productDesc='” + productDesc + ‘\” +

“, productPrice=” + productPrice +

‘}’;

}

}

首页index.jsp文件源代码

clip_image007

<%–

Created by IntelliJ IDEA.

User: 18010

Date: 2018/6/10

Time: 20:01

To change this template use File | Settings | File Templates.

–%>

<%@ page contentType=”text/html;charset=UTF-8″ language=”java” %>

<html>

<head>

<title>input</title>

</head>

<body>

<a href=”product-input.action”>Product Input</a>

</body>

</html>

Detail.jsp详情展示文件源代码

clip_image009

<%–

Created by IntelliJ IDEA.

User: 18010

Date: 2018/6/10

Time: 21:05

To change this template use File | Settings | File Templates.

–%>

<%@ page contentType=”text/html;charset=UTF-8″ language=”java” %>

<html>

<head>

<title>detail</title>

</head>

<body>

ProductId:${requestScope.product.productId}

<br>

<br>

ProductName:${requestScope.product.productName}

<br>

<br>

ProductDesc:${requestScope.product.productDesc}

<br>

<br>

ProductPrice:${requestScope.product.productPrice}

<br>

<br>

</body>

</html>

Input输入文件源代码

clip_image011

Web.xml文件源代码

clip_image013

<?xml version=”1.0″ encoding=”UTF-8″?>

<web-app xmlns=”http://xmlns.jcp.org/xml/ns/javaee”

xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”

xsi:schemaLocation=”http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd”

version=”4.0″>

<filter>

<display-name>FilterDispatcher</display-name>

<filter-name>FilterDispatcher</filter-name>

<filter-class>com.lxgyx.struts2.helloworld.FilterDispatcher</filter-class>

</filter>

<filter-mapping>

<filter-name>FilterDispatcher</filter-name>

<url-pattern>*.action</url-pattern>

</filter-mapping>

</web-app>

3. 整体预览

首页

clip_image015

点击链接跳转到信息输入页

clip_image017

点击Submit跳转到信息展示页

clip_image019

通过以上完整案例,实现一个基本的Struts2入门案列效果.

不会的朋友多看看源代码,刚入门的萌新直接将各个目录文件先创建好,然后将源代码复制进去直接运行即可.

建议学习方法:

第一遍:完整复制,实现效果

第二遍:模仿抄写,可以多抄几遍,就像抄作业一样

第三遍:自己理解代码以后开始按照自己的思路和总结,将代码写出来,实现效果,期间有不会的地方可以查看一下源代码.