Struts2的概述
一、Struts2的概述
1、什么是Struts2
2、常见的web层框架
3、Struts2特点:Web层框架基于前端控制器模型设计
Struts2的入门
一、Struts2的入门
1、下载Struts2的开发包(环境)
2、解压Struts2开发包
-
apps :Struts2提供的应用,war文件:web项目打成war包。直接放入到tomcat可以允许。
-
docs :Struts2的开发文档和API
-
lib :Strtus2框架的开发的jar包
-
src :Struts2的源码
3、创建web项目,引入jar包
4、创建一个JSP页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>Struts2的一个入门</h1>
<h3><a href="${pageContext.request.contextPath }/hello.action">struts2的入门</a></h3>
</body>
</html>
5、编写Action的类
package com.heer.struts.demo1;
/**
* Struts2的入门Action类
* @author hand
* 2018年11月26日 下午3:32:34
*/
public class HelloAction {
/**
* 提供一个方法
* *方法签名是固定的execute()
* *public共有的 返回值是String类型 方法名为execute 在这个方法中不能传递参数(因为底层需要反射执行此方法)
*/
public String execute() {
System.out.println("HelloAction执行了。。。");
return null;
}
}
6、对Action类进行配置
-
在src下创建(提供)名称叫做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> <!-- Struts2为了管理Action的配置,是通过包进行管理 --> <!-- 配置Struts2的包 --> <!-- name:名字随便起,只要自己不混淆就行,但是之后的package>name不能重复,也就是一个名称只能出现一次; extend:继承的是struts2-core-2.3.24.jar包下的struts-default.xml文件里面的struts-default, 只有继承了struts-default,才会有struts2里面的一些基本功能 namespace: --> <package name="demo1" extends="struts-default" namespace="/"> <!-- 配置Action: name:跟jsp页面中的访问链接路径.action前的名字对应 class:对应的类的全类名 --> <action name="hello" class="com.heer.struts.demo1.HelloAction"> </action> </package> </struts>
7、配置前端控制器(核心过滤器)
<?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_day01</display-name>
<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的核心过滤器 -->
<filter>
<!-- 上下名字一致即可 -->
<filter-name>struts2</filter-name>
<!-- filter-class名称就是在struts2-core-2.3.24.jar下的org.apache.struts2.dispatcher.ng.filter的StrutsPrepareAndExceuteFilter.class中的类名 -->
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<!-- 上下名字一致即可 -->
<filter-name>struts2</filter-name>
<!-- 让所有的请求都要经过核心过滤器,就配成/* -->
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
8、改写Action中的方法的返回值
package com.heer.struts.demo1;
/**
* Struts2的入门Action类
* @author hand
* 2018年11月26日 下午3:32:34
*/
public class HelloAction {
/**
* 提供一个方法
* *方法签名是固定的execute()
* *public共有的 返回值是String类型 方法名为execute 在这个方法中不能传递参数(因为底层需要反射执行此方法)
*/
public String execute() {
System.out.println("HelloAction执行了。。。");
// 要字符串,就给它返回一个字符串
return "success";
}
}
9、改写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>
<!-- Struts2为了管理Action的配置,是通过包进行管理 -->
<!-- 配置Struts2的包 -->
<!--
name:名字随便起,只要自己不混淆就行,但是之后的package>name不能重复,也就是一个名称只能出现一次;
extend:继承的是struts2-core-2.3.24.jar包下的struts-default.xml文件里面的struts-default,
只有继承了struts-default,才会有struts2里面的一些基本功能
namespace:
-->
<package name="demo1" extends="struts-default" namespace="/">
<!--
配置Action:
name:跟jsp页面中的访问链接路径.action前的名字对应
class:对应的类的全类名
-->
<action name="hello" class="com.heer.struts.demo1.HelloAction">
<!--
配置页面的跳转:
name:就是返回的字符串名称;
result:中间写的是返回的页面路径;
-->
<result name="success">/demo1/success.jsp</result>
</action>
</package>
</struts>
10、编写success.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>跳转成功页面!!</h1>
</body>
</html>
Struts2的执行流程
一、分析Struts2的执行流程
1、Struts2的执行流程
-
当用户请求访问某一个Action的时候,会先经过核心过滤器,然后在核心过滤器中执行一组拦截器(这组拦截器实现部分功能),然后再执行下一个拦截器,如果下一个拦截器没有的话,就执行目标Action,根据Action的Result返回值,进行页面跳转。
Struts2的常见配置
一、XML的提示问题
1、配置XML的提示(不联网也可以进行提示)
二、Struts2的配置文件的加载顺序(了解)
1、Struts2的配置文件加载顺序
为什么要谈这个问题,因为我们发现在struts里面的很多地方都能配置struts的常量,但是最终哪个会生效呢,这就与Struts2的配置文件加载顺序有关。
struts核心配置文件是在服务器启动之后就会进行创建和加载的;init方法就会被执行,下面的方法也就会被执行;
-
init_DefaultProperties() ;----加载default.properties
-
init_TraditionalXmlConfigurations(); ----加载struts-default.xml、struts-plugin.xml、struts.xml
-
init_LegacyStrutsProperties();----加载struts.properties
-
init_CustomConfigurationProviders(); ----加载配置提供类
-
init_FilterInitParameters() ; ----加载web.xml中过滤器初始化参数
-
init_AliasStandardObjects() ; ----加载Bean对象
2、加载顺序
三、Action的配置
1、package相关配置
-
package标签称为包,这个包与Java中的包的概念不一致。这个包是为了更好管理action的配置。
-
package标签的属性
2、action相关配置
四、常量的配置
1、Struts2的常量配置(constant配置)
在Struts2的框架中,提供了非常多的常量:(在default.properties里)
-
struts.i18n.encoding=UTF-8 ----Struts2中所有的post请求的中文乱码不用处理。
-
struts.action.extension=action, ----Struts2请求的默认的扩展名。默认扩展名是.action或什么都不写,但是习惯性加上,便于识别是struts2框架。
在Struts2中修改一些常量的值:
-
修改常量的值,可以有三个位置进行修正
-
在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> <!-- 一般设置struts2常量,写在最上面,这样别人一打开就知道你设置了常量 --> <!-- 配置struts2的常量,扩展名为.action,也可以自定义名称,但此时不写后缀的话就会报错 --> <constant name="struts.action.extension" value="action"/> <!-- Struts2为了管理Action的配置,是通过包进行管理 --> <!-- 配置Struts2的包 --> <!-- name:名字随便起,只要自己不混淆就行,但是之后的package>name不能重复,也就是一个名称只能出现一次; extend:继承的是struts2-core-2.3.24.jar包下的struts-default.xml文件里面的struts-default, 只有继承了struts-default,才会有struts2里面的一些基本功能 namespace: --> <package name="demo1" extends="struts-default" namespace="/"> <!-- 配置Action: name:跟jsp页面中的访问链接路径.action前的名字对应 class:对应的类的全类名 --> <action name="hello" class="com.heer.struts.demo1.HelloAction"> <!-- 配置页面的跳转: name:就是返回的字符串名称; result:中间写的是返回的页面路径; --> <result name="success">/demo1/success.jsp</result> </action> </package> </struts>
-
在struts.properties中进行修改
-
在web.xml中进行修改
-
-
通过过滤器的初始化参数来进行修改。
<!-- 配置Struts2的核心过滤器 --> <filter> <!-- 上下名字一致即可 --> <filter-name>struts2</filter-name> <!-- filter-class名称就是在struts2-core-2.3.24.jar下的org.apache.struts2.dispatcher.ng.filter的StrutsPrepareAndExceuteFilter.class中的类名 --> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> <!-- 修改常量 --> <init-param> <param-name>struts.action.extension</param-name> <param-value>xyz</param-value> </init-param> </filter>
注意:如果这三个位置都进行了常量的修改,那么最后生效的是web.xml文件,但是我们习惯上在struts.xml文件里进行修改。
五、分模块开发的配置
1、include的配置(在一个配置文件当中,引入其他配置文件)
用与引入其他路径下的配置文件,多用于团队开发的情况下。
<?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>
<!-- 一般设置struts2常量,写在最上面,这样别人一打开就知道你设置了常量 -->
<!-- 配置struts2的常量,扩展名为.action,也可以自定义名称,但此时不写后缀的话就会报错 -->
<constant name="struts.action.extension" value="action"/>
<!-- 引入其他的配置文件 -->
<include file="com/heer/struts/demo1/struts_demo1.xml"/>
</struts>
Action的访问
一、Action的写法
1、Action类是POJO的类
POJO:(Plain Ordinary Java Object)简单的java对象,实际就是普通JavaBeans,是为了避免和EJB混淆所创造的简称。
package com.heer.struts.demo2;
/**
* Action的编写方式:Action类是一个POJO的类
* @author hand
* 2018年11月26日 下午3:47:58
*/
public class ActionDemo1 {
public String execute() {
System.out.println("ActionDemo1执行了");
return null;
}
}
2、Action类实现一个Action的接口
package com.heer.struts.demo2;
import com.opensymphony.xwork2.Action;
/**
* Action的编写方法2:实现一个Action的接口
* 实现接口的这种方式:提供了五个常量(五个逻辑视图的名称,不是一个真实的视图名称)
* SUCCESS :成功
* ERROR :失败
* LOGIN :登录出错页面跳转
* INPUT :表单校验的时候出错
* NONE :不跳转
* @author hand
* 2018年11月26日 下午4:05:36
*/
public class ActionDemo2 implements Action{
@Override
public String execute() throws Exception {
System.out.println("ActionDemo2执行了。。。");
return null;
}
}
3、Action类继承ActionSupport类
package com.heer.struts.demo2;
import com.opensymphony.xwork2.ActionSupport;
/**
* Action的编写方式3:Action类继承ActionSupport类
* * 推荐使用继承ActionSupport方式
* * ActionSupport中提供了数据校验、国际化等一些列操作的方法。
* @author hand
* 2018年11月26日 下午4:16:05
*/
public class ActionDemo3 extends ActionSupport{
@Override
public String execute() throws Exception {
System.out.println("ActionDemo3执行了。。。");
// 这里想让它不跳转,故设置为NONE
return NONE;
}
}
二、Action的访问
1、通过method设置(稍微有点麻烦,不太建议)
<?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 name="demo3" extends="struts-default" namespace="/">
<!--
配置Action:
name:跟jsp页面中的访问链接路径.action前的名字对应
class:对应的类的全类名
-->
<action name="userFind" class="com.heer.struts.demo3.UserAction" method="find"></action>
<action name="userUpdate" class="com.heer.struts.demo3.UserAction" method="update"></action>
<action name="userDelete" class="com.heer.struts.demo3.UserAction" method="delete"></action>
<action name="userSave" class="com.heer.struts.demo3.UserAction" method="save"></action>
</package>
</struts>
2、通过通配符的方式进行配置(重要)经常使用
<!--
通配符方式访问:
name:可以将一样的先写上,不一样的用*号代替;
class:对应的类的全类名
method:*号所在的个数位置,写上大括号,里面写上对应数字
-->
<action name="product_*" class="com.heer.struts.demo3.ProductAction" method="{1}"></action>
通配符方式配置
3、动态方法访问(也有公司使用,但是比较少)
<!-- 动态方法访问的方式 -->
<action name="customer" class="com.heer.struts.demo3.CustomerAction"></action>
-
开启动态方法访问
<!-- 开启动态方法访问方式 --> <constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
-
编写访问路径
<h3>通过动态方法方式访问</h3> <a href="${ pageContext.request.contextPath }/customer!find.action">客户查询</a><br> <a href="${ pageContext.request.contextPath }/customer!update.action">客户修改</a><br> <a href="${ pageContext.request.contextPath }/customer!delete.action">客户删除</a><br> <a href="${ pageContext.request.contextPath }/customer!save.action">客户保存</a><br>
CRM的客户列表显示
一、搭建开发环境
1、创建web项目,引入jar包
2、引入配置文件
3、创建数据库和表
CREATE TABLE `cst_customer` (
`cust_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',
`cust_name` varchar(32) NOT NULL COMMENT '客户名称(公司名称)',
`cust_source` varchar(32) DEFAULT NULL COMMENT '客户信息来源',
`cust_industry` varchar(32) DEFAULT NULL COMMENT '客户所属行业',
`cust_level` varchar(32) DEFAULT NULL COMMENT '客户级别',
`cust_phone` varchar(64) DEFAULT NULL COMMENT '固定电话',
`cust_mobile` varchar(16) DEFAULT NULL COMMENT '移动电话',
PRIMARY KEY (`cust_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
4、创建包结构
5、引入相应页面
二、代码实现
1、修改请求路径
<TR>
<TD class=menuSmall><A class=style2 href="/struts2_crm/customer_find.action"
target=main>- 客户列表</A></TD>
</TR>
2、编写Action、Service、DAO
-
action.java
package com.heer.web.action; import java.util.List; import org.apache.struts2.ServletActionContext; import com.heer.domain.Customer; import com.heer.service.CustomerService; import com.heer.service.impl.CustomerServiceImpl; import com.opensymphony.xwork2.ActionSupport; /** * * @author hand * 2018年11月26日 下午5:23:46 */ public class CustomerAction extends ActionSupport { public String find() { // 调用业务层 CustomerService customerService = new CustomerServiceImpl(); List<Customer> list = customerService.find(); // 带到页面上,页面跳转 ServletActionContext.getRequest().setAttribute("list", list); return "findSuccess"; } }
-
CustomerService.java
package com.heer.service; import java.util.List; import com.heer.domain.Customer; /** * * @author hand * 2018年11月26日 下午5:25:52 */ public interface CustomerService { public List<Customer> find(); }
-
CustomerServiceImpl.java
package com.heer.service.impl; import java.util.List; import com.heer.dao.CustomerDao; import com.heer.dao.impl.CustomerDaoImpl; import com.heer.domain.Customer; import com.heer.service.CustomerService; /** * * @author hand * 2018年11月26日 下午5:30:17 */ public class CustomerServiceImpl implements CustomerService { @Override public List<Customer> find() { // 调用Dao CustomerDao customerDao = new CustomerDaoImpl(); return customerDao.find(); } }
-
CustomerDao.java
package com.heer.dao; import java.util.List; import com.heer.domain.Customer; /** * * @author hand * 2018年11月26日 下午5:32:11 */ public interface CustomerDao { /** * @return */ List<Customer> find(); }
-
CustomerDaoImpl.java
package com.heer.dao.impl; import java.util.List; import org.hibernate.Session; import org.hibernate.Transaction; import com.heer.dao.CustomerDao; import com.heer.domain.Customer; import com.heer.utils.HibernateUtils; /** * * @author hand * 2018年11月26日 下午5:32:43 */ public class CustomerDaoImpl implements CustomerDao { @Override public List<Customer> find() { Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); List<Customer> list = session.createQuery("from Customer").list(); transaction.commit(); return list; } }
3、配置Action
<?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>
<!-- 一般设置struts2常量,写在最上面,这样别人一打开就知道你设置了常量 -->
<!-- 配置struts2的常量,扩展名为.action,也可以自定义名称,但此时不写后缀的话就会报错 -->
<constant name="struts.action.extension" value="action"/>
<package name="crm" extends="struts-default" namespace="/">
<action name="customer_*" class="com.heer.web.action.CustomerAction" method="{1}">
<result name="findSuccess">/jsp/customer/list.jsp</result>
</action>
</package>
</struts>
4、编写页面
-
index.htm
<FRAMESET frameSpacing=0 frameBorder=0 cols=220,*> <FRAME name=menu src="menu.htm" frameBorder=0 noResize> <FRAME name=main src="welcome.htm" frameBorder=0> </FRAMESET>
-
menu.htm
<TR> <TD class=menuSmall><A class=style2 href="/Struts2_crm/customer_find.action" target=main>- 客户列表</A></TD> </TR>
-
list.htm
<TABLE id=grid style="BORDER-TOP-WIDTH: 0px; FONT-WEIGHT: normal; BORDER-LEFT-WIDTH: 0px; BORDER-LEFT-COLOR: #cccccc; BORDER-BOTTOM-WIDTH: 0px; BORDER-BOTTOM-COLOR: #cccccc; WIDTH: 100%; BORDER-TOP-COLOR: #cccccc; FONT-STYLE: normal; BACKGROUND-COLOR: #cccccc; BORDER-RIGHT-WIDTH: 0px; TEXT-DECORATION: none; BORDER-RIGHT-COLOR: #cccccc" cellSpacing=1 cellPadding=2 rules=all border=0> <TBODY> <TR style="FONT-WEIGHT: bold; FONT-STYLE: normal; BACKGROUND-COLOR: #eeeeee; TEXT-DECORATION: none"> <TD>客户名称</TD> <TD>客户级别</TD> <TD>客户来源</TD> <TD>客户所属行业</TD> <TD>电话</TD> <TD>手机</TD> <TD>操作</TD> </TR> <c:forEach items="${list }" var="customer"> <TR style="FONT-WEIGHT: normal; FONT-STYLE: normal; BACKGROUND-COLOR: white; TEXT-DECORATION: none"> <TD>${customer.cust_name }</TD> <TD>${customer.cust_level }</TD> <TD>${customer.cust_source }</TD> <TD>${customer.cust_industry }</TD> <TD>${customer.cust_phone }</TD> <TD>${customer.cust_mobile }</TD> <TD> <a href="${pageContext.request.contextPath }/customerServlet?method=edit&custId=${customer.cust_id}">修改</a> <a href="${pageContext.request.contextPath }/customerServlet?method=delete&custId=${customer.cust_id}">删除</a> </TD> </TR> </c:forEach> </TBODY> </TABLE>