1Structs2
Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。
2MVC模式过程
JSP + JavaBean = Model1
JSp + Servlet + JavaBean = Model2(典型的MVC)
3Jar 包下载
4配置Structs核心文件
web.xml,只要和web应用整合,就要运用到这个文件
JSP+servlet+javaBean 就需要把servlet在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>structs-timer</display-name>
<filter>
<filter-name>struts2</filter-name>
<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>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
struts.xml
The content of element type “package” must match “(result-types?,interceptors?,default-
interceptor-ref?,default-action-ref?,default-class-ref?,global-results?,global-exception-
mappings?,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">
<!--引入其他配置文件,可以把每个功能模块独立到一个xml配置文件中-->
<include file="structs-User.xml"></include>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="true" />
<!-- name Package的表示,为了让其他的package引用,继承 -->
<package name="default" namespace="/" extends="struts-default">
<!--包的命名空间,对应路径,/test,则action都在 localhost:8080/projectname/test/xx.action,可包含多个action -->
<action name="action名称" class="类的路径com.peng.action.TimerAction">
<!-- 默认成功 -->
<result>/success.jsp</result>
</action>
</package>
</struts>
配置 action 之后,可以通过路径后加入路径访问
http://localhost:8080/structs-timer/timer.action
http://localhost:8080/structs-timer/timer
其他的一些配置
<!--常量值-->
<constant name="struts.devMode" value="true" />
<constant name="struts.action.extension" value="action" />
<package name="default" namespace="/" extends="struts-default">
<!-- 注册拦截器 -->
<interceptors>
<interceptor name="mytimer"
class="com.peng.interceptor.TimerInterceptor"></interceptor>
</interceptors>
<!-- 全局 result 配置 -->
<global-results>
<result name="inplut">/error.jsp</result>
<result name="error">/error.jsp</result>
</global-results>
<action name="timer" class="com.peng.action.TimerAction">
<!-- 默认成功 -->
<result>/success.jsp</result>
<!-- 为Action显式引用拦截器后,默认的拦截器defaultStack不再生效,需要手工引用 -->
<interceptor-ref name="defaultStack"></interceptor-ref>
<!-- 引用拦截器 -->
<interceptor-ref name="mytimer"></interceptor-ref>
<!-- 参数设置,对应action中的get/set方法 -->
<param name="url">http:www.qq.com</param>
</action>
</package>
常量值
<!-- 指定全局国际化资源文件mess。mess.properties在src目录下 -->
<constant name="struts.custom.i18n.resources" value="mess"/>
<!-- 指定默认编码集,作用于HttpServletRequest的setCharacterEncoding方法 和freemarker 、velocity的输出-->
<constant name="struts.i18n.encoding" value="UTF-8"/>
<!-- 自定义后缀修改常量,*.do,*.action都会被识别。无后缀不能被识别-->
<constant name="struts.action.extension" value="do,go"/>
<!-- 如果想将无后缀也识别,请在上处常量设置value="do,go," --
<!-- 设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭-->
<constant name="struts.serve.static.browserCache" value="false"/>
<!-- 当struts的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开 -->
<constant name="struts.configuration.xml.reload" value="true"/>
<!-- 开发模式下使用,这样可以打印出更详细的错误信息 -->
<constant name="struts.devMode" value="true" />
<!-- 默认的视图主题 -->
<constant name="struts.ui.theme" value="simple" />
<!-- 与spring集成时,指定由spring负责action对象的创建 -->
<constant name="struts.objectFactory" value="spring" />
<!-- 该属性设置Struts 2是否支持动态方法调用,该属性的默认值是true。如果需要关闭动态方法调用,则可设置该属性
为 false-->
<constant name="struts.enable.DynamicMethodInvocation" value="false"/>
<!-- 上传文件的40M大小限制-->
<constant name="struts.multipart.maxSize" value="41943040"/>
5Structs的过滤器
在 web.xml 中配置的
<filter>
<filter-name>struts2</filter-name>
<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项目启动的时候,过滤器就生效
2.1.3版本后
StrutsPrepareAndExecuteFilter,可以在执行action之前,添加自己的过滤器
6回顾在页面中访问Servlet
TestServlet.java
//package com.peng.servlet;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@SuppressWarnings("serial")
@WebServlet("/pppp")//注解的方式
public class TestServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("成功了到达action....pppp ");
RequestDispatcher rd = req.getRequestDispatcher("mypage.jsp");//跳转到mypage.jsp
rd.forward(req, resp);
}
}
另一种方式:注册servlet的方式
<servlet>
<servlet-name>TestServlet</servlet-name>
<servlet-class>com.peng.servlet.TestServlet</servlet-class>
</servlet>
<!-- servlet映射 -->
<servlet-mapping>
<servlet-name>TestServlet</servlet-name>
<url-pattern>/pppp</url-pattern>
</servlet-mapping>
通过下面的路径访问
http://localhost:8080/ServletTest/pppp
7在Structs中访问 servlet
Structs本来就是servlet的升级产品,控制Action的使用本来就是Structs的功能,因为Structs的拦截,直接访问servlet是不能成功的
解决方式
一.修改web.xml 文件配置
原来是
<url-pattern>/*</url-pattern>
修改为
<url-pattern>*.action</url-pattern>
即不对action进行拦截
方法二
在struts.xml中的的节点下面添加struts2处理的请求后缀 常量:
<!--
该属性指定需要Struts 2处理的请求后缀,该属性的默认值是action,即所有匹配*.action的请求都由Struts 2处理。
如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。
-->
<constant name="struts.action.extension" value="action" />
这样的话,每个 action 都必须加后缀 xxx.action,才能正常访问,当然你也可以设置其他的后缀,servlet也可以正常访问了
http://localhost:8080/structs-timer/TestServlet
http://localhost:8080/structs-timer/timer.action
http://localhost:8080/structs-timer/timer.action 不能访问
更多方法:http://blog.sina.com.cn/s/blog_7ffb8dd50101aw8l.html
8 Action的搜索顺序
如果这个路径可以
http://localhost:8080/struts2/helloworld.action
则
http://localhost:8080/struts2/aaa/bbb/helloworld.action
也可以
9 动态方法调用
动态方法调用就是为了解决一个Action对应多个请求的处理时Action太多
一个Action就一个execute()方法,一个模块写一个action,action只有一个默认的execute()方法,那action多的不是上天了吗
三种方式解决
1.指定method属性
2.感叹号方式
3.通配符方式
1.指定method属性
建立一个action包,存放action,src下存放structs.xml.在WebContent下建立相应的jsp文件
action中加入了两个方法 add ,update,都返回SUCCESS
HelloWorldAction.java
//package com.struts2.action;
import com.opensymphony.xwork2.ActionSupport;
public class HelloWorldAction extends ActionSupport {
public String add(){
return SUCCESS;
}
public String update(){
return SUCCESS;
}
@Override
public String execute() throws Exception {
System.out.println("执行Actoin");
return SUCCESS;
}
}
structs.xml文件中做相应的更改
..
<action name="helloworld" class="com.struts2.action.HelloWorldAction">
<result >/result.jsp</result>
</action>
<action name="addAction" method="add" class="com.struts2.action.HelloWorldAction">
<result >/add.jsp</result>
</action>
<action name="updateAction" method="update" class="com.struts2.action.HelloWorldAction">
<result >/update.jsp</result>
</action>
..
http://localhost:8080/Struts2_Test/addAction 访问的是add.jsp
http://localhost:8080/Struts2_Test/updateAction 访问的是update.jsp
方法多的时候,也不方便啊,不推荐使用,看其他的
2感叹号方式
首先在structs.xml中开启一个常量
<!-- 动态调用方法 -->
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
更改struct.xml文件的action
<action name="helloworld_*" method="{1}" class="com.struts2.action.HelloWorldAction">
<result >/result.jsp</result>
<result name="add">/add.jsp</result>
<result name="update">/update.jsp</result>
</action>
更改HelloWorldAction ,注意方法的return值要相应改变
public class HelloWorldAction extends ActionSupport {
public String add(){
return "add";
}
public String update(){
return "update";
}
@Override
public String execute() throws Exception {
System.out.println("执行Actoin");
return SUCCESS;
}
}
http://localhost:8080/Struts2_Test/helloworld.action 访问的是result.jsp
http://localhost:8080/Struts2_Test/helloworld!add.action 访问的是add.jsp
http://localhost:8080/Struts2_Test/helloworld!update.action 访问的是update.jsp
官方不推荐使用
3通配符方式
关闭感叹号的方式,设为 false
<constant name="struts.enable.DynamicMethodInvocation" value="false"></constant>
统配符的方式
<action name="helloworld_*" method="{1}" class="com.struts2.action.HelloWorldAction">
<result >/result.jsp</result>
<result name="add">/{1}.jsp</result>
<result name="update">/{1}.jsp</result>
</action>
public class HelloWorldAction extends ActionSupport {
public String add(){
return "add";
}
public String update(){
return "update";
}
@Override
public String execute() throws Exception {
System.out.println("执行Actoin");
return SUCCESS;
}
}
http://localhost:8080/Struts2_Test/helloworld.action 访问的是result.jsp
http://localhost:8080/Struts2_Test/helloworld_add.action 访问的是add.jsp
当然action也可匹配多个
<action name="*_*" method="{2}" class="com.struts2.action.{1}Action">
<result >/result.jsp</result>
<result name="add">/{2}.jsp</result>
<result name="update">/{2}.jsp</result>
</action>
http://localhost:8080/Struts2_Test/HelloWorld_add.action 访问的是add.jsp
大写的HelloWorld,因为是类的路径啊
11默认Action
..
<default-action-ref name="index"></default-action-ref>
<action name="index">
<result>/error.jsp</result>
</action>
12Structs后缀
<!-- 不加后缀,不用加后缀就能访问,加了,就一定要后缀,因为默认为action啊 -->
<constant name="struts.action.extension" value="html"></constant>
13处理结果类型
return 类型
1返回input的示例
配置Action
<action name="LoginAction" method="login" class="com.struts2.action.LoginAction">
<result >/success.jsp</result>
<result name="input">/login.jsp</result>
</action>
有类型转换等错误时(表单验证不正确),返回input,在登录界面登录时,还是会返回登录界面
User.java
//package com.struts2.po;
import java.util.List;
public class User {
private String username;
private String password;
private int age;
private List<User> bookList;
//getter and setter
}
<form action="LoginAction.action" method="post">
用户名:<input type="text" name="username"><%-- <s:fielderror name="username"></s:fielderror> --%><br>
书籍1:<input type="text" name="bookList[0].username"><br>
书籍2:<input type="text" name="bookList[1].username"><br>
密码:<input type="password" name="password"><br>
年龄:<input type="text" name="age"><br>
<input type="submit" value="提交"/>
</form>
LoginAction.jsp
//package com.struts2.action;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.struts2.po.User;
public class LoginAction extends ActionSupport
implements ModelDriven<User>{
private User user = new User();
public String login(){
System.out.println(user.getUsername());
System.out.println(user.getBookList().get(0).getUsername());
System.out.println(user.getBookList().get(1).getUsername());
return SUCCESS;
}
@Override
public User getModel() {
return user;
}
}
即使没有在 LoginAction 中,显式的声明格式类型错误,structs自动检测
显式声明校验条件
LoginAction.jsp
package com.struts2.action;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.struts2.po.User;
public class LoginAction extends ActionSupport
implements ModelDriven<User>{
private User user = new User();
public String login(){
if(user.getUsername()==null
||"".equals(user.getUsername())){
this.addFieldError("username", "用户名为空");
return INPUT;
}
System.out.println(user.getUsername());
System.out.println(user.getBookList().get(0).getUsername());
System.out.println(user.getBookList().get(1).getUsername());
return SUCCESS;
}
@Override
public User getModel() {
return user;
}
}
运用structs的
<s:fielderror ></s:fielderror>
标签显示全部错误信息
想显示特定指定的错误信息,如上文的this.addFieldError("username", "用户名为空");
则可以用
<s:fielderror fieldName="username"/>
<s:fielderror>
<s:param>username</s:param> <!--显示指定的 username字段的 错误消息-->
<s:fielderror/>
<%@ taglib prefix="s" uri="/struts-tags"%>
...
<form action="LoginAction.action" method="post">
用户名:<input type="text" name="username"> <s:fielderror ></s:fielderror><br>
书籍1:<input type="text" name="bookList[0].username"><br>
书籍2:<input type="text" name="bookList[1].username"><br>
密码:<input type="password" name="password"><br>
年龄:<input type="text" name="age"><br>
<input type="submit" value="提交"/>
</form>
运行结果:
首先是类型检查,之后才是自己声明的校验
2全局结果和局部结果
有很多时候一个< result>可供很多< action>使用,这时可以使用< global-results>标签来定义全局的< result>
<package name=".." namespace="/" extends="struts-default">
<global-results>
<result name="mainpage">/main.jsp</result>
</global-results>
</package>
3处理结果的type类型
<result name="success" type="">/success.jsp</result>
默认为 dispatcher 支持 JSP 技术
<package name="struts-default" abstract="true">
<result-types>
<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
<result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/>
<result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
<result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/>
<result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/>
<result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>
<result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>
<result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/>
<result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
<result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" />
<result-type name="postback" class="org.apache.struts2.dispatcher.PostbackResult" />
</result-types>
</package>
默认 dispatcher 跳转的方式请求不变–>可以去WEB-INF下面的页面
redirect 重定向—>请求发生了改变,不能去WEB-INF下面的页面
redirectAction 跳转到另一个Action下
plainText 查看原文
<action name="source">
<result type="plainText">
<param name="charSet">utf-8</param>
<param name="location">/login.jsp</param>
</result>
</action>