一,Model2结构里的过滤器例子:
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;
public class FilterDispat implements Filter {
private FilterConfig filterConfig;
@Override
public void destroy() {
this.filterConfig=null;
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig=filterConfig;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req=(HttpServletRequest) request;
HttpServletResponse res=(HttpServletResponse) response;
String uri=req.getRequestURI();
if(uri.endsWith(".action")){
int lastIndex=uri.lastIndexOf("/");
String action=uri.substring(lastIndex+1);
if(action.equals("Product_input.action")){
}else if(action.equals("Product_save.action")){
Product product=new Product();
product.setProductName(request.getParameter("productName"));
product.setDescription(request.getParameter("description"));
product.setPrice(request.getParameter("price"));
product.save();
request.setAttribute("product", product);
}
String dispatchUrl=null;
if(action.equals("Product_input.action")){
dispatchUrl="/jsp/ProductForm.jsp";
}else if(action.equals("Product_save.action")){
dispatchUrl="/jsp/ProductDetails.jsp";
}
if(dispatchUrl!=null){
RequestDispatcher rd=request.getRequestDispatcher(dispatchUrl);
rd.forward(request, response);
}else if(uri.indexOf("/css/")!=-1&&req.getHeader("referer")==null){
res.sendError(HttpServletResponse.SC_FORBIDDEN);
}else{
filterChain.doFilter(request, response);
}
}
}
}
从上面的例子中,可以知道MVC model2中的控制器,需要做很多工作,比如,获得用户请求,处理用户请求带来的数据,实例化模型,数据添加到请求对象,转发请求控制权等等很多。往往过滤器调度程序会变得很复杂
二,基于上面过滤器需要完成很多的任务,基于MVC模式思想的struts2框架采用了一种简化思想:
把原来Model2中要完成全部任务的过滤器调度程序“分解出”一系列的“拦截器”组件(程序),分别负责各自要完成的任务(这些任务大都不是控制逻辑的部分)。而过滤器剩下的核心任务则为控制逻辑。
三,动作处理流程:
1,struts2框架中,提供了很多预定义的过滤器,我们只需要在xml文件中注册即可使用。
2,struts2中的动作方法,将在属性被填充好后才会执行,执行的结果是String类型的值,struts框架将根据这个值来决定将控制权转交到哪个视图或者下载文件等等。
3,动作处理流程:
过滤器调度程序做的第一件事:对表示某种请求的uri进行字符串检查,并判断应该调用哪个动作和对哪个java动作类进行实例化。这里需要使用一个struts.xml的配置文件,在这个文件里对应用程序所有的动作做出定义。
动作类必须至少有一个结果告诉struts,在它执行完动作方法后应该做什么。struts会在启动时读取struts.xml文件来检查动作执行完该做什么。另外指出,在开发模式下,struts在处理每一个请求时,都会检查一遍这个文件的时间戳,只要这个文件的时间戳从最后一次呗加载以来发生了变化,struts就会重新加载这个文件,因此,在开发模式下,修改了struts.xml问价你,用不着重新启动web容器,就可以运行。
程序启动---读取配置文件---查询配置管理器,根据请求uri识别调用哪个动作----运行为该动作注册的每一个拦截器,每一个拦截器会各自完成各自所划分的任务---执行先骨干的动作方法------执行相关的动作结果
四,拦截器
1,拦截器之美:
原来的Model2控制器程序必须做很多任务,把其中主要的控制逻辑划给过滤器来负责处理,而没有划分在过滤器器调度程序内部的代码被模块化为一系列拦截器。它优美之处在于,可以通过编辑struts配置文件实现拦截器的随意插入或拔出。这些拦截器通常注册给相应的动作,以来处理各类任务的动作。struts框架中提供了很多默认的预定义拦截器,所以我们简单注册一下就可以拿来使用,而不用自己写拦截器。当然对于非标准的动作,我们也可以自定义拦截器。
五,struts配置文件
1,最基本的配置文件:struts.xml和struts.properties
2,struts.xml文件,对应用程序的所有动作做出定义,包括动作,每个动作调用的拦截器,每个动作的各种结果,等等。
六,配置文件一:struts.xml
1,package元素
struts考虑到模块分问题,把不同的动作类可以划归到不同的package。
一个struts.xml可以有一个或者多个package,根据动作的类别和开发者的喜好划分。
例子:
<package name="package-n" namespace="package-n" extends="struts-default">
</package>
namespace是可选属性,如果没写,默认的namespace=“/”,;
注意:这里涉及到调用动作的路径问题,不含命名空间的直接路径访问;含有命名空间的,路径的必须 为/context/namespace/xxx.action
2,include元素
为了让大型应用中的复杂的struts.xml文件更便于管理,可以把一个struts.xml文件划分为一些小的xml文件,最好是每个小的xml文件里面只有一个package,或者有几个彼此相关的package。
<include file="module-1.xml"/>
3,action元素
在package元素内部,可以有也可以没有与之对应的动作类,没有的话默认的动作类为ActionSupport,有的话还需要用class属性写上其完全限定名。
4,result元素
result是action的子元素,告诉struts动作执行完后控制权转移到哪个视图。
其中,同一个action可以有多个result,分别对应动作方法的每个返回值。
5,global-results元素
一个package元素可以包含一个global-results元素,其中包含一些通用的结果。如果某个动作在它的动作声明里无法找到匹配的结果,它将搜索global-results元素。
6,与拦截器有关的元素:
interceptors,interceptor,interceptor-ref,interceptor-stack,default-interceptor-ref
(1)action元素必须包含一系列负责对动作对象进行处理的拦截器。一个包里的所有拦截器可以被包里的所有动作使用。但是必须在包里为这个动作注册拦截器intercepor。每当一个动作被调用时,为这个动作的注册的拦截器们则将获得一次对该动作进行处理的机会。注意:这个动作的拦截器的使用,是按注册顺序调用的。
例子:
<package>
<interceptors>
<interceptor name="alias" class="...."/>
<interceptor name="il8n" class="...."/>
</interceptors>
<action name="Product_delete" class="....">
<interception-ref name="alias"/>
<interception-ref name="il8n"/>
</action>
</package>
(2)观察上面例子,大部分的struts应用程序都会有多个action元素,反复为每个动作列出一份拦截器清单会很麻烦。为了简化这个问题,struts允许创建一个或者多个拦截器栈,对需要的拦截器进行分组。这样只需在action里面列出拦截器栈即可。下面是创建的一个interceptor-stack
<interceptor-stack name="basicStack">
<interceptor-ref name="exception">
<interceptor-ref name="prepare">
<interceptor-ref name="params">
</interceptor-stack>
在用到这些拦截器的action里这样写:
<action>
<interceptor-ref name="basicStack">
<result name="input">xxxx</result>
</action>
7,param元素
8,constant元素
在struts.xml文件里利用这个元素可以覆盖default.properties文件的某个设置。
例如:可以在struts.xml 可以改变默认为false的开发模式struts.devMode
七,配置文件一:struts.properties
1,一般我们不需要写这个文件,因为默认的default.properties文件已经够用,除非想改变默认文件的一些配置。但是也可以不用覆盖,来达到此目的;方法:
(1)在struts.xml文件里使用constant元素
(2)在过滤器声明里使用init-param元素
八,入门案例
1,两个配置文件:
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<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>
<!--
这里是Model1模式的配置
<servlet>
<servlet-name>Controller</servlet-name>
<servlet-class>ControllerServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Controller</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name>JSPs</web-resource-name>
<url-pattern>/jsp/*</url-pattern>
</web-resource-collection>
<auth-constraint/>
</security-constraint> -->
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="app01a" namespace="/" extends="struts-default">
<action name="Product_input">
<result>/jsp/ProductForm.jsp</result>
</action>
<action name="Product_save" class="Product">
<result>/jsp/ProductDetails.jsp</result>
</action>
</package>
</struts>
2,动作类-模型
import java.io.Serializable;
public class Product implements Serializable {
private String productName;
private String description;
private String price;
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String execute(){
return "success";
}
/*public String save(){
return "success";
}*/
}
3,jsp文件--视图
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'ProductForm.jsp' starting page</title>
<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">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
<style type="text/css">@import url(css/main.css)</style>
</head>
<body>
<div id="global">
<h3>Add a product</h3>
<form action="Product_save.action" method="post">
<table>
<tr>
<td>Product Name:</td>
<td><input type="text" name="productName"/></td>
</tr>
<tr>
<td>Description:</td>
<td><input type="text" name="description"/></td>
</tr>
<tr>
<td>Price:</td>
<td><input type="text" name="price"/></td>
</tr>
<tr>
<td><input type="reset" /></td>
<td><input type="submit" value="Add a product"/></td>
</tr>
</table>
</form>
</div>
</body>
</html>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'ProductDetails.jsp' starting page</title>
<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">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
<style type="text/css">@import url(css/main.css)</style>
</head>
<body>
<div id="global">
<h3>The product has been saved</h3>
<p>
<h5>details:</h5>
name:${product.productName }
description:${product.description }
price:${product.price }
</p>
</div>
</body>
</html>
运行结果:
特别说明:这里是初学,书上例子好像有点偏差,这里数据没有带过来显示,是不是因为还需要一个拦截器进行初始化然后把数据带到显示页面?
1,往后学的过程中,我会接着解答。
2,有大神看到了,也可以帮忙解答,谢谢啦