day25_Struts2学习笔记_01
一、框架概述
把重复性的繁琐的代码封装
起来。使程序员在编码中把更多的精力放业务需求的分析
和理解
上面。
特点
:封装了很多细节,程序员在使用的时候会非常简单。
三大框架:Struts2、Spring、Hibernate
二、三层架构与Struts2
- 表现层:M model V view C control
- 业务层:Service
- 持久层:Dao data access object
Struts2
在三层架构中的位置是处于表现层
。注意它只是一个表现层框架
。
三、MVC与Struts2
M:Model 模型,封装数据。javabean
V:View 视图,展示界面。jsp
C:Controller 控制器,控制程序流程。Servlet
控制器:Servlet
init(ServletConfig config)
destroy()
service(ServletRequest req, ServletResponse resp)
过滤器:Filter 它也可以作为控制使用。
init(FilerConfig filterConfig)
destroy()
doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
Servlet能做的Filter都可以做,并且比Servlet功能更强大,它多了一个放行的功能。即:过滤器同样也适合做控制器。
注意:Struts1的核心就是一个控制器,Struts2的核心就是一个过滤器。
四、案例中存在的一些问题
规律:
- 获取请求正文,用户要做什么事情。
- 根据不同的请求,做出不同的判断。
- 执行具体的方法代码(
动作
)。 - 转向页面,展示给用户。
缺陷:
-
重复性
劳动太多,具体的执行代码也有冗余代码
。 -
全是硬编码
,像用户要做什么事情,对应执行什么代码,可以写在配置文件
中。 - 具体的代码方法放到了
控制器
中,过于臃肿
。
五、Struts2简介
1、Struts2概述
Struts2是Apache发行的MVC开源框架。注意:它只是表现层(MVC)框架。
2、Struts2的来历
Struts1:也是apache开发的一套mvc的开源框架。在2005年之前非常流行。
弊端:Struts1的核心控制器就是一个Servlet。随着使用者的增多,弊端开始出现。
Struts2:在long long ago,有一个设计超前的框架XWork,后来推出了XWork1和WebWork2。Struts2就是apache和OpenSymphony组织合并开发出来。
Struts2里面包含了WebWork2的核心及Struts的一些特性和功能。除此之外,和Struts1没有任何关系了。
六、搭建开发环境
-
开发包目录结构
-
搭建开发环境
拷贝必要jar包到classpath中(即拷贝jar包到WebRoot/WEB-INF/lib中),原则是:用哪个拷贝哪个。注意:新老版本的区别
:
旧版本的struts2
新版本的struts2
-
建立Struts2的配置文件
at the top of classpath(在最顶层的构建路径),建立一个默认名称为struts.xml的配置文件。
注意:- 文件名大小写。
- 创建位置。
- 该文件名称允许修改,但是我们一般不改。
-
在web.xml中配置控制器
a、配置位置:在web.xml中
b、配置什么: struts2已经写好了的一个过滤器。
结论:struts2比struts1优秀的一个体现就是:它用了更为强大的过滤器作为控制器。 -
验证是否搭建环境成功
部署应用后,启动Tomcat,不报错表示搭建成功。 -
关于struts.xml没有提示的问题
分析原因:没有找到对应的dtd约束文件。
解决办法:
a.开发时联网
b.开发时不能上网咋办呢?那就手动添加该约束文件,过程如下:
附上:上述的struts.xml和web.xml文件
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>
web.xml文件(注意:新版本的区别)
if you are using struts2 version 2.5 you need to change from
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
to
org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter
是的,去掉了中间.ng文件空间名,原因是在整合xwork的时候,同时简化了不必要的包名空间。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>day25_00_struts2Template</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<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>
</web-app>
七、Struts2入门案例
以下步骤是日后实际开发中经常重复的。
- 建立一个访问视图的.jsp文件
- 在struts.xml文件中配置
- 建立动作类和动作方法
- 结果视图页面
- 测试
- 小问题解决
上面的模板我们做好了,就可以复制使用该模班,注意:复制该模板后,必须要修改 Web Context Root的内容,否则部署的时候会报错(会出现跟模板名称一样的应用),步骤如下:在新项目上右键 --> Properties --> 在搜索框中输入 Web --> 在web Context Root 中 --> Config…,如下图所示:
八、第一个案例的执行过程
客户浏览器index.jsp --> Tomcat服务器 --> 我们的应用 --> web.xml --> struts.xml --> HelloAction动作类和sayHello()动作方法 --> success.jsp
如下图所示:
struts2的体系结构图如下:
九、Struts2的配置文件的加载时机和加载顺序
加载时机:当应用被tomcat加载的时候,struts2的配置文件就已经被加载过了。
加载顺序:default.properties --> struts-default.xml --> plugins配置 --> struts.xml --> struts.properties --> web.xml
加载顺序 | 配置文件名 | 所在位置 | 说明 |
---|---|---|---|
1 | default.properties | struts2-core-2.5.16.jar\org\apache\struts2 | 不能修改 |
2 | struts-default.xml | struts2-core-2.5.16.jar | 不能修改 |
3 | strtuts-plugin.xml | 在struts2提供的插件jar包中,名为struts2-convention-plugin-2.5.16.jar | 不能修改 |
4 | struts.xml |
我们的应用中,该文件是web应用默认的struts配置文件 | 我们修改的:推荐修改这里 |
5 | struts.properties |
我们的应用中,该文件是Struts的默认配置文件 | 我们修改的 |
6 | web.xml |
我们的应用中,该文件是Web应用的配置文件 | 我们修改的,可以给过滤器配置参数 |
- 注意:
1、Struts2提供了两种配置的方式。一种是key=value的方式,即使用.properties文件。另一种是xml文件配置。我们推荐使用xml文件(因为它能描述层级关系
)。
2、如果多个文件配置了同一个struts2常量,则后一个文件中配置的常量值会覆盖前面文件配置的常量值。
十、Struts2中的常量
1、常用的常量
常量定义在了default.properties
配置文件中,体现形式都是key=value
。所有的struts2应用都会用到这些常量。
常量名 | 常量值(默认值) | 说明 |
---|---|---|
struts.i18n.encoding | UTF-8 | 应用中使用的编码 |
struts.objectFactory.spring.autoWire | name | 和spring框架 整合有关 |
struts.multipart.parser | jakarta | 指定文件上传用的组件 |
struts.multipart.maxSize | 2097152 | 文件上传总文件大小限制:2M |
struts.action.extension | action | 能进入Struts2框架内部的url地址后缀名。多个值用逗号分隔。 |
struts.enable.DynamicMethodInvocation | false | 是否允许动态方法调用 |
struts.devMode | false | 是否是开发模式。开发模式:改了配置文件,不需要重启。输出更多的错误信息。开发阶段建议为true。 |
struts.ui.theme | xhtml | 页面展示用的主题 |
2、在struts.xml中覆盖常量(即修改struts中default.properties定义的常量值)
3、依次类推,三个文件的配置如下图所示:
十一、Struts2中配置文件元素的详解
1、package元素:
package元素:作用是定义一个struts的包,它是把配置文件按照面向对象的思想来管理。分模块开发。
即在struts2的配置文件中引入了面向对象思想,使用了分包管理。易于管理动作类。便于模块化开发动作类。
name属性:指定包的名称。注意:包的名称在配置文件中唯一。
extends属性:指定当前包的父包。它是按照面向对象的思想管理的体现。
一般情况下需要继承struts-default包,但不是必须的。不过如果不继承的话,将无法使用struts2提供的核心功能。
struts-default.xml 中定义着 struts-default 这个包。而 struts-default.xml 是在我们的 struts.xml 加载之前加载。
abstract属性:把包声明为一个抽象包。抽象包就是用来被继承的。
只有没有<action>元素的包,才能被定义为抽象包。
namespace属性:名称空间。当指定了名称空间之后,访问路径就变成了:
访问路径 = 名称空间 + 动作名称
当不指定该属性时,该属性有默认值,默认值是""。注意:不是"/"!!!
名称空间的搜索顺序:
第一步:先去找对应的名称空间
在指定的名称空间下找到了:就执行第二步。
在指定的名称空间下没找到:按照名称空间结构向上追溯,一直到根名称空间,只要在任何一级找到了,就执行第二步。
第二步:找动作名称
先在指定的名称空间下,搜索对应的动作名称:找到了就执行动作类的动作方法。
在指定的名称空间下没找到对应的动作名称:就前往默认的名称空间下,找动作名称。注意:它只找动作名称。
package的namespace的执行顺序,如下图所示:
示例代码:
<package name="p1" extends="struts-default" namespace="/user"> <!-- 名称空间(namespace="/user") -->
<!--
<action name="action1" class="com.itheima.web.action.Demo1Action" method="saveUser" >
<result name="success">/success.jsp</result>
</action>
-->
</package>
<package name="p2" extends="struts-default"> <!-- 默认的名称空间(namespace=""或者不写该属性) -->
<action name="action2" class="com.itheima.web.action.Demo1Action" method="saveUser2" >
<result name="success">/success.jsp</result>
</action>
</package>
访问:http://localhost:8080/day25_04_struts2_package/user/action2.action,可以找得到,查找过程:
1、先查找名称空间/user,有/user名称空间;
2、再在该名称空间查找动作名称action2.action,没有该动作名称;
3、再去默认的名称空间查找,有默认的名称空间;
4、再在该名称空间查找动作名称action2.action,有该动作名称,则执行该动作。
2、action元素:
action元素:是用于定义动作名称,动作类和动作方法的映射,即配置动作用的。以及当出现不同情况时前往指定的结果视图 。
name属性:动作的名称。和jsp页面上的请求url中的名称对应起来。注意在此处不能写.action。
class属性:指定动作类,即动作类全名。
method属性:指定要执行的动作方法,即动作类中的方法名称。默认是public String execute() { }
方法要求:
1. public的
2. 返回值必须是String
3. 没有参数
可以修改默认动作类,注意:我们一般不改
<default-class-ref class="你自己的动作类" />
默认的动作类是:com.opensymphony.xwork2.ActionSupport 是在struts-default.xml中定义的。
3、编写动作类的三种方式:
a.方式一:动作类就是一个POJO(Plain Old Java Object: 原始的老的java对象),是非常简单的JavaBean。示例代码如下:
package com.itheima.web.action;
/**
* 创建动作类的第一种方式:
* 创建一个普通的java类。
* 它就是一个POJO,是非常简单的javabean。
* 原始的 老的 java 对象
* Plain Old Java Object
* POJO类是指没有实现任何接口以及除了Object类以外,没有继承任何父类。
* struts2通过获取struts.xml获取到完全的类名,然后底层通过反射,执行方法。
* 该创建动作类的方式的特点:一点也看不到有struts2的痕迹。
*
* @author cmj
*/
public class Demo1Action {
public String hello() {
System.out.println("动作类执行了");
return "success";
}
}
b.方式二:动作类实现com.opensymphony.xwork2.Action接口。示例代码如下:
package com.itheima.web.action;
import com.opensymphony.xwork2.Action;
/**
* 创建动作类的第二种方式:
* 动作类实现com.opensymphony.xwork2.Action接口。
* 创建一个普通类,实现Action接口,实现接口中的方法。
*
* Action接口中的常量:
* 常量名 默认常量值 说明
* SUCCESS "success" 当动作执行成功后,前往指定的位置
* NONE "none" 不返回任何结果视图,和 return null; 效果是一样的
* ERROR "error" 当执行动作方法,出现异常后,前往指定的位置
* INPUT "input" 数据回显
* LOGIN "login" 一般用于返回登录页面
*
* @author cmj
*/
public class Demo2Action implements Action {
public String execute() throws Exception {
System.out.println("动作类执行了");
return null;
}
}
c.方式三:动作类继承com.opensymphony.xwork2.ActionSupport类。推荐使用方式三。示例代码如下:
package com.itheima.web.action;
import com.opensymphony.xwork2.ActionSupport;
/**
* 创建动作类的第三种方式:
* 创建一个动作类,继承com.opensymphony.xwork2.ActionSupport类。推荐使用方式三。
* 意义:提供了一些基本的功能。比如验证和国际化消息提示等。
* 我们在开发中采取这种方式,来创建我们的动作类。
*
* @author cmj
*/
public class Demo3Action extends ActionSupport{
// 当我们在该类中什么都不写,一个动作方法都不提供时:
// 有一个默认的动作方法:public String execute() throws Exception { return SUCCESS; }
}
4、动作的调用:
a.使用通配符:
优先级:绝对匹配优先。使用通配符的按照在配置文件中的先后顺序进行匹配的。
b.使用动态方法调用:
示例代码如下:
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>
<!-- 先设置为开发者模式 -->
<constant name="struts.devMode" value="true" />
<!-- 开启动态方法调用 -->
<constant name="struts.enable.DynamicMethodInvocation" value="true"/>
<package name="p1" extends="struts-default">
<!-- 动作方法调用的配置
<action name="addUser" class="com.itheima.web.action.UserAction" method="addUser">
<result name="success">/addUser.jsp</result>
</action>
<action name="updateUser" class="com.itheima.web.action.UserAction" method="updateUser">
<result name="success">/updateUser.jsp</result>
</action>
<action name="deleteUser" class="com.itheima.web.action.UserAction" method="deleteUser">
<result name="success">/deleteUser.jsp</result>
</action>
<action name="findUser" class="com.itheima.web.action.UserAction" method="findUser">
<result name="success">/findUser.jsp</result>
</action>
-->
<!-- 使用通配符,配置动作方法
*表示的是动作的名称,当有和动作名称相匹配的时候可以用{出现的位置}来代替
<action name="*_*" class="com.itheima.web.action.{2}Action" method="{1}{2}">
<result name="success">/{1}{2}.jsp</result>
</action>
-->
<!-- 动态方法调用的配置 -->
<action name="user" class="com.itheima.web.action.UserAction">
<result name="success">/success.jsp</result>
</action>
</package>
</struts>
inex.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>title</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">