本文是基于慕课网的《Struts2入门》视频教程笔记。
一.MVC模式=control+view+model
1、jsp+javaBean=model
jsp里会嵌入大量的js片段和java代码,可读性变差。
2、jsp+servlet+javaBean
典型的MVC模式
二.MVC流程
在Struts2中,action就是Controller。
三.搭建struts2的环境步骤
1、下载相关jar包
struts基础jar包
2、创建Web项目
3、创建并完善相关配置
4、创建action并测试启动
创建一个action类,继承ActionSupport类。(继承本项目的)
四.struts2核心文件
1、web.xml
Web项目启动第一个加载的就是web.xml。
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_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>struts</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 加过滤器 -->
<filter>
<filter-name>struts</filter-name>
<!--指定struts的过滤器 -->
<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>
2、struts2.xml
2.1.struts2.xml中包含的内容
全局属性
用户请求和相应Action之间的对应关系
Action可能用到的参数和返回结果
各种拦截器的配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<!--include节点是strut2中组件化的方式,可以将每个功能模块独立到一个xml配置文件中,然后用include节点引用 -->
<include file="struts-default.xml"></include>
<!-- package提供了将多个Action组织为一个模块的方式
package的名字必须是唯一的,package可以扩展,当 一个package扩展自另一个package时,该package会在
本身配置的基础上加入扩展package的配置,父package必须在子package前配置
name:package的名称
extents:继承父package的名称
abstract:设置package的属性为抽象的package不能定义action,值true/false
namespace:定义package的命名空间,该命名空间影响到url的地址,例如命名空间为/test,那么访问的是地址
http://localhost:8080/struts2/test/XX.action
-->
<package name="default" namespace="/" extends="struts-default">
<interceptors>
<!-- 定义拦截器
name:拦截器名称
class:拦截器类路径
-->
<interceptor name="" class=""></interceptor>
<!-- 定义拦截器栈 -->
<interceptor-stack name="">
<interceptor-ref name=""></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 定义默认的拦截器,每个Action都会自动引用
如果Action中引用了其他拦截器,默认拦截器将无效 -->
<default-interceptor-ref name=""></default-interceptor-ref>
<!-- 全局result配置 -->
<global-results>
<result name="">/error.jsp</result>
</global-results>
<!-- Action配置,一个Action可以被多次映射(只要action配置中的name不同)
name:action名字
class:对应的类的路径
method:调用Action中的方法名
-->
<action name="helloworld" class="src.action.HelloWorldAction" method="">
<!-- 引用拦截器
name:拦截器名称或者拦截器栈名称
-->
<interceptor-ref name=""></interceptor-ref>
<!-- 节点配置
name:result名称和Action中返回的值相同
type:resultl类型不写则选择superPackage的type struts-default.xml中默认为dispatcher -->
<result name="" type="">/result.jsp</result>
<!-- 参数设置
name:对应action中的get/set方法
-->
<param name=""></param>
</action>
</package>
</struts>
3、struts2.properties
struts2框架的全局属性文件,自动加载。与struts2.xml放在一个目录下就可以了。该文件包含很多key-value对。
该文件完全可以配置在struts2.xml文件中,使用constant元素。
示例:
<constant name="struts.devMode" value="true“>
五.深入struts2
1、访问Servlet API
1.1、doGet和doPost方法里的两个参数就是Servlet API
HttpServletRequest
HttpServletResponse
1.2、Struts2中的Action的excute方法
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
return super.execute();
}
Action的excute方法没有参数,不与servlet API耦合,但是不去访问不去用request也是不可能的,所以struts2提供了三种方式求访问servlet API。
(1)ActionContext
(2)实现**Aware接口
(3)ServletActionContext
2、Action搜索方式
(1)判断package是否存在
(2)如果存在,判断action是否存在,如果不存在,则去默认的namespace的package里面寻找action,如果还没有则报错
(3)检查上一级路径的package是否存在(知道默认的namespace),重复第(1)步。
3、动态方法调用
动态方法调用是为了解决一个Action对应多个请求的处理,以免Action太多,调用方法有以下三种:
(1)制定method属性
<action name="addAction" method="add" class="com.yan.action.HelloWorldAction">
<result>/result.jsp</result>
</action>
(2)感叹号方式(不建议)
先配置Struts.xml,开启一个功能
<action name="addAction" method="add" class="com.yan.action.HelloWorldAction">
访问的时候,加感叹号,感叹号后面加方法名,例如:
http://localhost:8080/HelloWorld!add.action
(3)通配符方式
<action name="helloworld_*" method={1} class="com.yan.action.HelloWorldAction">
<result>/result.jsp</result>
<result name="add">/{1}.jsp</result>
<result name="error">/{1}.jsp</result>
</action>
{1}匹配*
<action name="*_*" method={2} class="com.yan.action.{1}Action">
<result>/result.jsp</result>
<result name="add">/{2}.jsp</result>
<result name="error">/{2}.jsp</result>
</action>
这种方式,那么整个项目配置一个action就可以了。
4、指定多个配置文件
<include file="helloWorld.xml"></include>
不同的模块使用不同的配置文件。
配置编码:
<constant name="struts.i18n.encoding" value="UTF-8"></constant>
当有编码问题时可以试试把这个加上。
5、默认Action
当访问不到对应的网页,系统会报错,默认Action就是解决这个问题。
<default-action-ref name="index"></default-action-ref>
<action name="index">
<result>/error.jsp</result>
</action>
当访问不存在的网页时,都将访问error.jsp
6、更改Struts2后缀(.action)
<constan name="struts.action.extentsion" value="html"></constan>
上例将后缀名改为.html。如果不想要后缀,直接将value值设置为空。
7、在action中接收参数
(1)使用Action的属性接收参数
form表单提交的方式:在action类中定义想对应的属性,并且生成对应的get/set方法。即可提取参数。
注:也可以把这些属性放到一个类中,使用面向对象的思想。即第(2)中方式。
(2)使用DomainModel接收参数
前后台的对象要对应。
例:后台Action类中有属性
Private User user;(可不实例化)
注:下面也必须有对应的get/set方法。
那么前台文本框里必须命名为如下:
<input type="text" name="user.username">
<input type="text" name="user.password">
(3)使用ModelDriven接收参数
必须先实现ModelDriven的接口,即
implements ModelDriven
以及生成方法getModel(),实现接口:
@Override
public User getModel() {
// TODO Auto-generated method stub
return user;
}
注:user必须实例化
优点:不需要生成get/set方法,且当后台对象名改变时,不需要更改前台的对象名。是推荐使用的一种传参方式。
public class HelloWorldAction extends ActionSupport implements ModelDriven<User>{
private User user=new User();
@Override
public String execute() throws Exception {
System.out.println("执行Action");
return SUCCESS;
}
@Override
public User getModel() {
// TODO Auto-generated method stub
return user;
}
}
复杂类型接收参数:
例1:
<input type="text" name="booklist[0]">
<input type="text" name="booklist[1]">
例2:
<input type="text" name="list[0].username">
<input type="text" name="list[1].username">
8、处理结果类型
8.1 struts2的处理流程:
用户请求->Struts框架->控制器(Action)->Struts框架->视图资源
<result name="" type="">/result.jsp</result>
如果省略name属性,系统将采用默认的name属性值success.
注:带“/”表示绝对路径,开始就是项目的上下文路径
不带“/”表示相对路径,开始是action的namespace指定的路径。
关于input代码演示:
<result name="input">/login.jsp</result><s:fielderror name="username"></s:fielderror>
struts2的默认标签添加:
<%@ taglib prefix="s" uri="/struts-tags"%>
当表单验证不正确的时候,就会跳转到login.jsp页面。
<input type="text" name="user.username">
if(user.getUsername()==null||"".equals(user.getUsername())){
this.addFieldError("username","用户名不能为空!");
return INPUT;
}
注:这种方法必须写return INPUT,才能跳转到错误界面,如果不想这样的写的话,我们需要重写validate()方法,如下:
public void validate() { if(user.getUsername()==null||"".equals(user.getUsername())){
this.addFieldError("username","用户名不能为空!");
}
}
8.2 处理结果根据位置不同,可以分为两种结果:
(1)局部结果:将作为元素的子元素配置
(2)全局结果:将作为元素的子元素配置
8.3 struts2支持多种视图技术,例如jsp、Valocity、FreeMarker等 。
<result name="" type="">/result.jsp</result>
result标签里的type属性就是为了定义支持的视图技术。
补充:重定向会丢失请求参数。