Struts2入门学习笔记详解:

osc_bvincwvq 2020-11-10 12:48:15
Java EE


Struts2 入门学习笔记详解:

Struts2起源与背景:

学习一个技术就要了解它的历史, 知道它的背景 出现的因素… 这是我学习的习惯
在以前很久一段时间曾经出现过一种框架Struts1
Struts1
在很长一段时间, 在MVC框架中处于绝对的统治地位…大概04年吧… 我才上幼稚园…
Struts1:可以很好的实现 控制与业务逻辑的分离…
但自身也存在一些缺陷:
表现层单一: 只支持表现层使用, 限制了Struts1 的发展;
对Servlet APl 的依赖: Struts1 框架基于 Model2 模式开发, 因此其中需要涉及大量的Servlet APl 进一步对Web容器产生了依赖;
不利于代码重用::在代码开发中除了自己定义了类外 还必须使用Struts1 中的类; 类型之间的耦合严重!








WebWork
为了解决此类问题, 又出现了一种新的技术WebWork
它更加强调 系统之间的松耦合:使用拦截器来实现控制, 由此不在依赖于web容器
松耦,表现层支持更多的视图,使开发更加灵活; 但由于宣传不高 使用率并不多…名气并不大!! 为了提高访问度 改了个名字 Struts2 出现了;



Struts2
以WebWork框架的设计思想为核心,吸收了Struts 1的部分优点;
WebWork + Struts1 = Sturts2
在这里插入图片描述


Struts 2的获取

Struts 2官方地址:http://struts.apache.org
本次选取Struts 2.3.16.3进行讲解
在这里插入图片描述

Struts2 应用:

引入Struts2 Jar

新建Java Web项目, 引入Jar文件添加至项目中lib
Struts2项目基础jar文件:

文件明 说明
struts2-core-xxx.jar Struts 2框架的核心类库
xwork-core-xxx.jar XWork类库,Struts 2的构建基础
ognl-xxx.jar Struts 2使用的一种表达式语言类库
freemarker-xxx.jar Struts 2的标签模板使用类库
javassist-xxx.GA.jar 对字节码进行处理
commons-fileupload-xxx.jar 文件上传时需要使用
commons-io-xxx.jar Java IO扩展
commons-lang-xxx.jar 包含了一些数据类型的工具类
…jar 这里仅是一些基础的Jar 随着程序扩展还有很多个jar 要不停学习哦~

开始第一个Struts2 项目:

在这里插入图片描述

配置web.xml

编写web项目, Struts2框架所需要的过滤器:web.xml (个人喜欢先弄配置, 一般都是cope)
注意:
目前由于开发工具的进步, 可能有些web项目默认不会在显示 web.xml文件但一定不是手创的!可以设置工具项目版本——myelicpse
在这里插入图片描述


web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<!-- 项目名 -->
<display-name>Struts2</display-name>
<!-- web文件指定的默认访问页面.. -->
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<!-- Struts2过滤器 -->
<!-- 作用:启动加载struts.xml文件-->
<filter>
<filter-name>struts</filter-name>
<!-- Struts2核心控制器类:
早期还是:org.apache.struts2.dispatcher.FilterDispatcher
-->
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> <!-- 现在! -->
</filter>
<filter-mapping>
<filter-name>struts</filter-name>
<url-pattern>/*</url-pattern> <!-- /*: 任何请求都要经过.. -->
</filter-mapping>
</web-app>

编写页面 :

这里只是先单纯的学习Struts 并不会与数据库打交道访问数据库啥的…
Struts 就像之前学习SpringMVC一样, 相当于一个控制器 Servlet一样 接收页面请求响应结果数据
(一般搭配Hibernate 进行数据库交互这里暂时不讲解 欢迎可以观赏以下我之前的博客有详细讲解… );
这里页面使用: JSP


HelloWord.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %> <!-- 引入Struts2标签库 -->
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<p>${msg }</p> <!-- 单纯直接使用EL是获取不到滴...EL是获取作用域中的数据都没有存哦~ -->
<h1>
<s:property value="msg"/> <!-- 使用Struts2标签库,可以直接获取到响应action的全局变量的数据; -->
</h1>
<!-- 表单: name="name" 可以用于传递参数.. -->
<form action="hello" method="post">
名字: <input type="text" name="name"> <input type="submit"value="提交">
</form>
</body>
</html>

编写Action Java类;(相当于控制器的操作)

个人喜欢在编写时, 专门建一个包 action包 用于专门存在 action类;
这里先介绍一下最基础的实现Action接口方式来实现,重写 execute();
根据返回值String 找到对应的响应页面…
仔细一看有点像Servlet了,对于多种不同请求如果采用该方式不是很方便, 多重判断执行 返回不同结果页面…
后面会深入扩展多种的Action实现方式…



HelloWordAction.java

package com.wsm.action;
//注意别倒错包了
import com.opensymphony.xwork2.Action;
/*Action:
* Struts中用于接收响应,请求的Java类,相当于 "控制器"
*
* 全局变量:
* Struts中用于 "接收"或"显示" 数据;
* 需要给其提供给get/set();
* 接收页面信息: 变量名要和表单name名相同;
* 向页面输出: 页面可以通过: Struts2表达式/或存在作用域中通过EL表达式取出进性数据展示;
*/
public class HelloWordAction implements Action {

//获取页面表单名字;
private String name;
//等会向页面输出的变量...
private String msg;
//Struts2 还支持使用复杂的数据类型: 集合 数组 对象...
//实现方法
@Override
public String execute() throws Exception {

System.out.println(name);
msg="hello:"+name; //拼接向页面输出的信息;
return "hello"; //返回 "逻辑视图名",struts.xml根据:<result name="返回的逻辑视图名" >找到最后的响应页面</result>
}
/*
对于return "逻辑视图名"; Action接口中还提供了5个字符串类型静态常量:
用于更加规范的,指定对应的 "逻辑视图";
其实也就是普通的字符串,并无特殊机制.. 逻辑视图指定的页面也还是要自己定义的,只是Struts2的一种完善机制吧;
*/
//get/set
public String getName() {

return name;
}
public void setName(String name) {

this.name = name;
}
public String getMsg() {

return msg;
}
public void setMsg(String msg) {

this.msg = msg;
}
}

Action接口常量字符串逻辑含义

常量 逻辑含义
SUCCESS “success” 表示程序处理正常, 并返回给用户成功的结果;
NONE “none” 表示程序处理正常,但不返回给用户任何显示…
ERROR “error” 返回处理结果失败…
INPUT “input” 表示需要更多用户输入才能顺利执行
LOGIN “login” 表示用户需要正确登录后才能顺利执行

创建Struts2 配置文件:

页面发送请求——经过web,xml过滤——Struts2配置文件: 处理——
找到对应的xxaction类 一系列操作后返回一个"逻辑视图名"——至Struts2配置文件根据result 找到对应响应页面…;
注意: 该文件必须建在 项目的Src文件下,部署服务器时候才会在: WEB-INF/classes 目录下的,才可以正确获取执行…
一般取名:struts.xml


struts.xml
在 src 目录下新建一个名称为 struts.xml 的文件

<?xml version="1.0" encoding="UTF-8"?>
<!-- struts.xml声明部分,工具没有配置的DTD文件,可以直接cope下面的... -->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<!-- struts.xml根节点 -->
<struts>
<!-- 创建: 一个default包名, namespace命名空间 "/"表示寻找根目录下请求action.., 继承struts-default(Struts2底层的...) 后面详细讲解...-->
<package name="default" namespace="/" extends="struts-default" >
<!-- action:用于接收页面的请求,指定对应的action类中执行...(package中可以配置多个)
name:根据页面请求根据name找到指定的action class:指定对于action java类进行执行;
-->
<action name="hello" class="com.wsm.action.HelloWordAction" >
<result name="hello" >/HelloWord.jsp</result> <!-- 根据 xxxaction类,返回的逻辑视图名指定对于的响应页面... -->
<!-- 如果没有指定 name默认值就是success,所以action returu "success"; 可以不指定name -->
</action>
</package>
</struts>

Struts2使用对象接收用户输入数据 / 访问Servlet Apl

使用Struts2实现登录功能:

在上一项目基础上扩展…
在这里插入图片描述

扩展一个实体类(对象数据传输);

User .Java

package com.wsm.entity;
public class User {

//属性
private String userName;
private String userPwd;
//无参构造
public User(){
};
//带参构造
public User(String userName, String userPwd) {

super();
this.userName = userName;
this.userPwd = userPwd;
}
//get/set
public String getUserName() {

return userName;
}
public void setUserName(String userName) {

this.userName = userName;
}
public String getUserPwd() {

return userPwd;
}
public void setUserPwd(String userPwd) {

this.userPwd = userPwd;
}
}

登录所需的login 页面;

login.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<form action="login" method="post">
<!-- 对于对象类型的,读取通过action类中: 对象名.属性 进行赋值读取-->
名字<input type="text" name="user.userName"> <!-- 对于属性名要和Java类一致 且区分大小写-->
密码<input type="text" name="user.userPwd" >
<input type="submit" value="提交">
</form>
<!-- 因为控制器request中存储了登录失败信息,EL表达式查看~ -->
<p>${shibai }</p>
</body>
</html>

index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<p>登录成功!${user.userName }</p>
</body>
</html>

登录的action 及struts2访问ServletApl对象;

struts2 访问ServletApl对象

在Struts2 概述中介绍过, Struts2的Action 没有与ServletApl 发送耦合;从而可以轻松实现Action 的测试;
但是在web 开发过程中, 无法避免需要使用 ServletApl中的对象;
Struts2提供了多种方式实现ServletApl的访问:(两大类)

解耦方式操作ServletAPl 对象 两种实现 (下面实例就是一种解耦形式) ;

  1. 使用ActionContext 类获取ServletApl对象 (Map对象)
    Struts2 框架使用普通的Map对象替代了:HttpServletRequest HttpSession ServletContext …
    Action类中 ,可以轻易的获取对应的Map类型的替代对象, 实现了解耦的形式…
    解耦方式获得作用域对象,如下代码案例


  2. Action类实现特定接口来实现 ServletApl 对象; (即采用注入方式实现)
    好处: 这种方式有利于单元测试, 因为ActionContext需要借助框架进行初始化, 而这种方式无须初始化直接获取使用…
    如下实例

Action类实现特定接口来实现 ServletApl 对象ServletAction.java

package com.wsm.action;
//注意导入对应的包~
import java.util.Map;
import org.apache.struts2.interceptor.ApplicationAware;
import org.apache.struts2.interceptor.RequestAware;
import org.apache.struts2.interceptor.SessionAware;
import com.opensymphony.xwork2.Action;
public class ServletAction implements Action, RequestAware,SessionAware,ApplicationAware {

//注意这里定义的也是一个 Action;
//只不过本次只是为了让你们知道,可以通过实现对应接口,解耦获得对应的 Servlet对象,所以没有什么特定的实现功能...别搞混~
//自定义解耦的作用域对象;
Map request;
Map session;
Map application;
//action:实现的方法..这里没有使用不详细介绍了...
@Override
public String execute() throws Exception {

// TODO Auto-generated method stub
return null;
}
//实现对应的方法,每一个接口都只有一个实现方法(); 用户返回对应的Map类型,模拟作用域对象;
@Override
public void setApplication(Map<String, Object> appliction) {

this.application = appliction;
}
@Override
public void setSession(Map<String, Object> session) {

this.session = session;
}
@Override
public void setRequest(Map<String, Object> request) {

this.request = request;
}
}

耦合方式操作ServletAPl 对象;
直接访问 Servlet API将使Action类与Servlet API耦合在一起;
Servlet API对象均由Servlet容器来构造,与这些对象绑定在一起,测试过程中就必须有Servlet容器,这样不便于Action类的测试
但有时候,确实需要访问这些对象,Struts2同样提供了直接访问ServletAPI对象的方式。
要直接获取Servlet API对象可以使用org.apache.struts2.ServletActionContext类,该类是ActionContext类的子类。
//导包
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.struts2.ServletActionContext;









HttpServletRequest request=ServletActionContext.getRequest(); //获取requset
ServletContext application=ServletActionContext.getServletContext(); //获取appliction
HttpSession session=request.getSession(); //根据requset 获取session;
除了直接使用 ServletActionContext 来直接获取Servlet Apl对象; 还可以通过实现接口注入ServletApl对象...省略了;


LoginAction.java

package com.wsm.action;
//注意别倒错包了
import java.util.Map;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.wsm.entity.User;
public class LoginAction implements Action {

//全局变量
public User user; //对象类型,页面通过 对象名.属性名 可进行读取操作...
//解耦方式获得作用域对象
ActionContext ac = ActionContext.getContext();
Map<String,Object> request = (Map<String,Object>)ac.get("request"); //获取request
Map<String,Object> session = ac.getSession(); //获取session
Map<String,Object> appliction = ac.getApplication(); //获取appliction
@Override
public String execute() throws Exception {

//验证登录成功/失败! admin 123
if("admin".equals(user.getUserName()) && "123".equals(user.getUserPwd()) ){

//登录成功!用户存session
session.put("user",user);
return "index";
}
//往request 存储失败信息;
request.put("shibai","登录失败");
return "login"; //失败回到登录页面~
}
//get/set
public User getUser() {

return user;
}
public void setUser(User user) {

this.user = user;
}
}

action都写好,最后一定不要忘记 struts2的配置文件!

就不写全了…直接在 package 中加一组 action 即可~
struts.xml

<action name="login" class="com.wsm.action.LoginAction" >
<result name="index" >/index.jsp</result>
<result name="login" >/login.jsp</result>
</action>

Struts2 数据校验:

对于一个web 应用而言, 所有的用户数据都是通过浏览器, 收集的;
用户的输入信息非常复杂多变,如果过程中 : 硬件设备/网络/用户恶意破坏…输入的信息可能导致程序异常…
对于这种问题应用程序需要能够在控制层, 处理异常的输入…
通常的做法是, 控制层发现异常, 直接返回回浏览器, 提示异常用户必须重新输入合法的…
对于这种操作,可以通过Struts2数据效验机制,进行完善…
使用Struts2的数据校验, action类将不再通过实现Action接口来实现..而是通过继承 ActionSupport类来完善数据校验操作
ActionSupport类
是一个默认的 Action接口的实现类。
这个类提供了很多默认的方法 :国际化信息 数据校验 默认处理用户请求…等方法;
因为ActionSupport类 是Struts2的默认实现类. 所以Struts.xml 中 < action > 可以不指定 class属性
ActionSupport类中的 validate() 实现数据校验, 所以需要重写…









给用户登录操作加非空验证:

需要修改LoginAction
LoginAction.java

package com.wsm.action;
//注意别倒错包了
import java.util.Map;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.wsm.entity.User;
public class LoginAction extends ActionSupport {
 //继承ActionSupport
//全局变量
public User user; //对象类型
//解耦方式获得作用域对象
ActionContext ac = ActionContext.getContext();
Map<String,Object> request = (Map<String,Object>)ac.get("request"); //获取request
Map<String,Object> session = ac.getSession(); //获取session
Map<String,Object> appliction = ac.getApplication(); //获取appliction
@Override
public String execute() throws Exception {

//验证登录成功/失败! admin 123
if("admin".equals(user.getUserName()) && "123".equals(user.getUserPwd()) ){

//登录成功!用户存session
session.put("user",user);
return "index";
}
//往request 存储失败信息;
request.put("shibai","登录失败");
return "login"; //失败回到登录页面~
}
//重写 validate(); 数据效验的方法;
@Override
public void validate() {

if(user.getUserName().length()==0){

super.addFieldError("username", "用户名不能为空");
}
if(user.getUserPwd().length()==0){

super.addFieldError("userpwd", "密码不能为空");
}
}
/*
当页面,发送一个请求,找对对应的action 时,最先进入就是 validate();方法中进行数据校验..
如果在验证过程中 addFieldError(); 添加了验证信息,那么就不会在进入execute(); 方法;
而是直接返回一个 "input"逻辑视图名,去struts.xml 找到指定的一个页面...
所以一定要在 struts.xml对应action标签中配置一个: <result name="input" >响应页面</result>
页面上可以通过:Struts2标签来讲校验异常信息展示..
*/
//get/set
public User getUser() {

return user;
}
public void setUser(User user) {

this.user = user;
}
}

struts.xml

 <action name="login" class="com.wsm.action.LoginAction" >
<result name="index" >/index.jsp</result>
<result name="login" >/login.jsp</result>
<result name="input" >/login.jsp</result> <!-- input:表示数据异常返回回登录页面; -->
</action>

修改页面展示校验结果:login.jsp

注意:别忘了导入 <%@ taglib prefix=“s” uri="/struts-tags" %> < !-- Struts2标签库 -->
可以通过 <s:fielderror></s:fielderror> 进行数据异常信息展示…

%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %> <!-- Struts2标签库 -->
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<!-- 数据效验异常信息输出展示.. -->
<div>
<s:fielderror></s:fielderror>
</div>
<form action="login" method="post">
<!-- 对于对象类型的,读取通过action类中: 对象名.属性 进行赋值读取-->
<!-- 对于属性名要和Java类一致 且区分大小写-->
名字<input type="text" name="user.userName"> <s:fielderror fieldName="username" ></s:fielderror> <!-- 根据fieldName指定显示异常的信息.. -->
<hr/>
密码<input type="text" name="user.userPwd" > <s:fielderror fieldName="userpwd" ></s:fielderror>
<input type="submit" value="提交">
</form>
<!-- 因为控制器request中存储了登录失败信息,EL表达式查看~ -->
<p>${shibai }</p>
</body>
</html>

Struts2标签:

Struts2 中提供了很多功能强大的标签库, 并且远远超出了传统的标签库的基本功能:(上面校验信息就是一种…)
主要分为两大类:UI标签 通用标签
使用前需要导入 Struts2标签库: <%@ taglib prefix=“s” uri="/struts-tags" %>

UI标签

UI标签可以分为三大类:表单标签 非表单标签 Ajax标签

Struts2常用表单标签:

标签 说明
<s:form>…</s:form> 表单标签
<s:textfield>…</s: textfield> 文本输入框
<s:password>…</s: password> 密码输入框
<s:textarea>…</s: textarea> 文本域输入框
<s:radio>…</s: radio> 单选按钮
<s:checkbox>…</s: checkbox> 多选框
<s:submit/> 提交标签
<s:reset/> 重置标签
<s:hidden/> 隐藏域标签
<s:actionerror/> 显示Action错误
<s:actionmessage/> 显示Action消息
<s:fielderror/> 显示字段错误,输出addFieldError("",""); 存储的信息… 一般用于 数据校验!

这些标签会被浏览器, 翻译加载运行, 可能会以一种 <table/><tr/><td/> 形式包装输出…
这是Struts2的默认格式:可以在struts.xml 对其默认风格进行修改:

<struts>
<!-- 设置用户界面默认XHTML风格:value="值可选.." -->
<constant name="struts.ui.thems" value="simple" />
</struts>

通用标签

Struts2 UI标签主要用于视图的设计,在视图的设计过程中还往往伴随着一些业务控制行为;
eg:判断Action中读取的集合是否为空,对集合进行 遍历!

Struts2常用的通用标签:

在这里插入图片描述

if/else if/else标签
三个都是条件判断 分支控制标签,几乎于Java类似:

三个标签中只有 <s:if /> 可以单独使用
<s:elseif /> <s:else /> 可以和 <s:if /> 搭配使用,但不能单独使用!
在这里插入图片描述

iterator迭代标签
在这里插入图片描述

实例Demo

登录成功, 查询所有用户信息遍历,并且隔行变色
修改LoginAction.java

//修改execute();
@Override
public String execute() throws Exception {

//验证登录成功/失败! admin 123
if("admin".equals(user.getUserName()) && "123".equals(user.getUserPwd()) ){

//登录成功!用户存session
session.put("user",user);
//存储几个用户,模拟查询,页面测试 struts2标签库,别忘了给实体类加一个带参构造函数(name,pwd);
List<User> users = new ArrayList<User>();
users.add(new User("张三1", "123"));
users.add(new User("张三2", "123"));
users.add(new User("张三3", "123"));
users.add(new User("张三4", "123"));
request.put("users",users);
return "index";
}
//往request 存储失败信息;
request.put("shibai","登录失败");
return "login"; //失败回到登录页面~
}

index.jsp 页面输出:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<p>登录成功!${user.userName }</p>
<!-- s:iterator:迭代遍历,获取request中数据!都已经requset了其实也可以直接使用JSTL了..感觉鸡肋了... -->
<s:iterator var="user" value="#request.users" status="status">
<!-- 判断元素下标隔行变色 -->
<s:if test="#status.index % 2==0">
<div style="background-color: red">
<s:property value="#user.userName"/>---<s:property value="#user.userPwd"/>
</div>
</s:if>
<s:else>
<div style="background-color: blue;">
<s:property value="#user.userName"/>---<s:property value="#user.userPwd"/>
</div>
</s:else>
</s:iterator>
</body>
</html>

终于写完了,感谢观看,最后实例的隔行颜色有点丑,别建议~


版权声明
本文为[osc_bvincwvq]所创,转载请带上原文链接,感谢
https://my.oschina.net/u/4405936/blog/4711082

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云