Struts2入门学习笔记详解:

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
Struts2入门学习笔记详解:_第1张图片

Struts 2的获取

Struts 2官方地址:http://struts.apache.org
本次选取Struts 2.3.16.3进行讲解
Struts2入门学习笔记详解:_第2张图片

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 项目:

Struts2入门学习笔记详解:_第3张图片

配置web.xml

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

web.xml


<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>Struts2display-name>
  
  
  <welcome-file-list>
    <welcome-file>index.htmlwelcome-file>
    <welcome-file>index.htmwelcome-file>
    <welcome-file>index.jspwelcome-file>
    <welcome-file>default.htmlwelcome-file>
    <welcome-file>default.htmwelcome-file>
    <welcome-file>default.jspwelcome-file>
  welcome-file-list>
  
  
  
	<filter>
		<filter-name>strutsfilter-name>
		
		<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilterfilter-class>  
	filter>
	
	<filter-mapping>
		<filter-name>strutsfilter-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" %>				

<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>


<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'index.jsp' starting pagetitle>
	<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">
	
  head>

<body>
	
	<p>${msg }p>				   	
	
	<h1>
  		<s:property value="msg"/>  
  	h1>
	
	<form action="hello" method="post">
		名字: <input type="text" name="name">   
	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根据:找到最后的响应页面
	}
/*
对于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 的文件





    
<struts>

	
	<package name="default" namespace="/" extends="struts-default" >
	
			
		<action name="hello" class="com.wsm.action.HelloWordAction" >
			<result name="hello" >/HelloWord.jspresult>		
			
		action>	
	package>
	
struts>

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

使用Struts2实现登录功能:

在上一项目基础上扩展…
Struts2入门学习笔记详解:_第5张图片

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

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+"/";
%>


<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'index.jsp' starting pagetitle>
	<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">
	
  head>
  
  <body>
    <form action="login" method="post">
    	
   		名字<input type="text" name="user.userName"> 
   		密码<input type="text" name="user.userPwd" >
   		<input type="submit" value="提交">
   	form>
   	
   	
   	<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+"/";
%>


<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'index.jsp' starting pagetitle>
	<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">
	
  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.jspresult>		
	<result name="login" >/login.jspresult>
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标签中配置一个: 响应页面 
页面上可以通过: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.jspresult>		
			<result name="login" >/login.jspresult>
			<result name="input" >/login.jspresult>		
		action>

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

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

%@ 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+"/";
%>


<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'index.jsp' starting pagetitle>
	<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">
	
  head>
  
  <body>
	
	<div>
		<s:fielderror>s:fielderror>
	div>
	
	<form action="login" method="post">
    	
   		
   		名字<input type="text" name="user.userName">	 <s:fielderror fieldName="username" >s:fielderror>  
   		<hr/>
   		密码<input type="text" name="user.userPwd" > <s:fielderror fieldName="userpwd" >s:fielderror> 
   		<input type="submit" value="提交">
   	form>
   	
   	
   	<p>${shibai }p>
  body>
html>

Struts2标签:

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

UI标签

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

Struts2常用表单标签:

标签 说明
表单标签
文本输入框
密码输入框
文本域输入框
单选按钮
多选框
提交标签
重置标签
隐藏域标签
显示Action错误
显示Action消息
显示字段错误,输出addFieldError("",""); 存储的信息… 一般用于 数据校验!

这些标签会被浏览器, 翻译加载运行, 可能会以一种

形式包装输出…
这是Struts2的默认格式:可以在struts.xml 对其默认风格进行修改:

<struts>
	
	<constant name="struts.ui.thems" value="simple" />
struts>

通用标签

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

Struts2常用的通用标签:

Struts2入门学习笔记详解:_第6张图片

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

三个标签中只有 可以单独使用
可以和 搭配使用,但不能单独使用!
Struts2入门学习笔记详解:_第7张图片

iterator迭代标签
Struts2入门学习笔记详解:_第8张图片

实例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+"/";
%>


<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'index.jsp' starting pagetitle>
	<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">
	
  head>

  <body>
   	<p>登录成功!${user.userName }p>
   	
   	
   	  <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>

URL标签和日期标签:

URL标签:
类似于HTML < a >,就可以知道这个标签的作用是构建一个URL地址
URL标签的语法如下:

<s:url value="ur1">
	<s:param name="parname" value="parvalue">
s:url>

日期标签:
日期标签用于格式化输出一个日期。
除此之外,该标签还可以计算指定日期和当前日期时刻之间的时差。
日期标签的语法法如下:

<s:date format="format" nice="truelfalse" name="name" id="1d" />

format属性:表示按照指定的格式进行日期格式化。
nice属性:该属性只有true 和false两个值,用于指定是否输出指定日期与当前时间的时差 ,默认是false
name属性:表示当前需要格式化的日期。
id属性:表示引用该元素的id值。

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


你可能感兴趣的:(SSH,java,ssh,struts2,web,软件框架)