1.1.1 框架的概述:
框架:就是一个软件的半成品,完成了一部分的功能.
Struts2框架:
Struts 2是Struts的下一代产品,是在 struts 1和WebWork的技术基础上进行了合并的全新的Struts 2框架。其全新的Struts 2的体系结构与Struts 1的体系结构差别巨大。Struts 2以WebWork为核心,采用拦截器的机制来处理用户的请求,这样的设计也使得业务逻辑控制器能够与ServletAPI完全脱离开
MVC:Model2设计模式.
* M:Model V:View C:Controller.(web开发人员)
EE的三层结构:
* web层、业务层、持久层.(SUN公司)
***** Struts2是一个基于MVC设计思想的的web层框架.
1.1.2 Web层常见框架:
Struts1:称为标签最丰富的框架.
Webwork:称为是开发最便捷框架.
Struts2:在struts1的流程的基础上.但是核心已经发生变化--webwork的核心.
SpringMVC:
1.1.3 Struts1和Struts2的区别:
Struts2本身的内核发生变化webwork.
Struts2是xwork的扩展,功能:Xwork提供了很多核心功能:前端拦截机(interceptor),运行时表单属性验证,类型转换,强大的表达式语言(OGNL – the Object Graph Navigation Language),IoC(Inversion of Control反转控制)容器等。
Web层的框架的特点:
* 每次请求会提交到前端控制器(完成部分代码功能)根据具体业务需求转发到具体的Action完成剩余代码.
1.1 Struts2的快速入门
1.1.1 Struts2入门的开发步骤:
步骤1:下载struts2的包:
* http://struts.apache.org/download.cgi
步骤2:Struts2的目录结构:
* apps:struts2提供的案例
* docs:struts2的API文档
* lib:struts2开发的jar包
* src:struts2的源代码
步骤3:创建一个web项目
步骤4:导入struts2的jar包.
* 导入11个jar包.
步骤5:设计一个页面:
<h1>Struts2的入门</h1>
<a href="${ pageContext.request.contextPath }/hello.action">访问Struts2</a>
步骤6:在web.xml中配置Struts2的前端控制器(核心过滤器)
<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>
步骤7:编写一个Action的类
public class Struts2Demo1 {
/*
* 提供一个方法:方法的格式是固定的.
* public String execute(){
*
* }
* ***** 为什么方法的格式固定?
* * 因为最终涉及到反射.
* * Class clazz = Class.forName("cn.itcast.struts2.demo1.Struts2Demo1");
* * Method method = clazz.getMethod("execute");
* * String s = (String)method.invoke(clazz.newInstance());
*/
public String execute(){
System.out.println("Hello Struts2...");
return "success";
}
}
步骤8:配置这个Action.需要在struts2的框架的配置文件中.
<struts>
<!--
package:标签主要用来管理Action的配置.
-->
<package name="demo1" extends="struts-default">
<!--
action标签中的
* name:访问路径
* class:访问那个类
-->
<action name="hello" class="cn.itcast.struts2.demo1.Struts2Demo1">
<result name="success">/demo1/success.jsp</result>
</action>
</package>
</struts>
1.2 Struts2开发流程
1.2.1 Struts2的执行流程
请求---->前端控制器(StrutsPrepareAndExecuteFilter)---->执行一组拦截器(defaultStack中定义拦截器会执行.拦截器:实现了部分代码)---->Action类---->返回逻辑视图名称----->结果页面.
1.2.2 Struts2的配置文件的提示问题:
Window--->Preferences---->搜索 xml catalog
选择URI:复制dtd路径,选择文件系统找到本地的DTD:
1.2.3 Struts2的源代码的导入:
1.2.4 Struts2插件:
1.3 Struts2的常见配置:
第一天:Struts的开发流程、配置、Action、Servlet API访问
第二天:参数封装、类型转换、数据校验、国际化
第三天:文件上传和下载、值栈和OGNL、标签
1.3.1 Struts2的配置文件的加载:
Struts2的所有配置文件都由核心过滤器加载.(StrutsPrepareAndExecuteFilter)
在核心过滤器的init方法中:
init_DefaultProperties(); // [1]----加载default.properties文件.在这个文件中定义了struts2的常量.
init_TraditionalXmlConfigurations(); // [2]----加载struts-default.xml(拦截器/结果页面),struts-plugin.xml(struts2插件配置文件),struts.xml
init_LegacyStrutsProperties(); // [3]----加载用户自定义的属性文件.struts.properties.(修改Struts2中常量.)
init_CustomConfigurationProviders(); // [5]----用户配置提供
init_FilterInitParameters() ; // [6]----加载web.xml的
init_AliasStandardObjects() ; // [7]----Bean的加载
配置文件的加载顺序:
default.properties
struts-default.xml
struts-plugin.xml
struts.xml---- 修改struts2的常量
struts.properties---- 修改struts2的常量
web.xml---- 修改struts2的常量
***** 如果多个文件配置了同一个struts2 常量,则后一个文件中配置的常量值会覆盖前面文件配置的常量值
1.3.2 Struts2的常见配置:
Package的配置
<package>标签:包. 包不是java中的包. 用来管理<action>.
* 常见的属性:
* name:定义包的名称的.包的名称是唯一的,不能重复的.
* extends:定义当前的包,继承哪个包.继承struts-default.因为struts-default里面定义了拦截器/结果页面...
* namespace:定义名称空间的.与<action>标签的name属性共同决定访问路径.
* namespace写法:
* 带名称的空间:namespace="/aa"
* 不带名称:namespace="/"
* 没有任何名称空间:namespace=""
例子:
<package name="demo1" extends="struts-default" namespace="/aa">
<action name=”bb/cc/hello” class=””>
</package>
<package name="demo1" extends="struts-default" namespace="/aa/bb">
<action name=”cc/hello” class=””>
</package>
<package name="demo1" extends="struts-default" namespace="/aa/bb/cc">
<action name=”hello” class=””>
</package>
在页面中
<a href=”/aa/bb/cc/hello.action”>Action</a>
***** 默认名称空间最大化./aa/bb/cc/hello.action访问路径 将/aa/bb/cc全都当成名称空间查找.
Action的配置:
<action>标签的配置:配置Action类的.
常见的属性:
* name:与<package>标签中的namespace共同决定访问路径.
* class:要执行的Action类的全路径.
* method:要执行Action类中的哪个方法的.默认就是execute.
<result>标签的配置:结果页面
常见的属性:
* name:逻辑视图名称.
* type:控制页面跳转.(转发/重定向...)
1.3.3 Struts2的常量配置:
在struts2中有很多的常量.常量都定义在org.apache.struts2.default.properties(key=value)
三个地方可以配置常量:
* struts.xml中配置(一般使用)
<constant name="key" value="value"></constant>
* struts.properties中配置
key=value
* web.xml中配置
<init-param>
<param-name>key</param-name>
<param-value>value</param-value>
</init-param>
* 常见的常量配置:
* struts.i18n.encoding=UTF-8---- 在Struts2中POST请求乱码,框架已经处理了.
* req.setCharacterEncoding(“UTF-8”);----处理POST请求乱码.
* struts.action.extension=action,,----设置struts2的扩展名,默认值是action,,.<action>的访问可以写成.action 或者 不写扩展名.
* struts.devMode=false----开发模式.一般设置为true,修改struts.xml后不需要重启tomcat
1.3.4 struts2中默认值:
* <action>
* method属性:默认值是execute.默认执行execute的方法.
* class属性:默认值是com.opensymphony.xwork2.ActionSupport
* <result>
* name属性:默认值success
* 默认的Action 和 Action默认处理类
* 默认的Action:在访问某个Action的时候,路径写错了.执行默认的Action.
* <default-action-ref name="default"/>
* Action的默认处理类:访问这个路径的时候,action可以找到 但是没有配置这个<action>中的class属性.
* <default-class-ref class="com.opensymphony.xwork2.ActionSupport" />
1.3.5 include的配置:
用于struts2分模块开发中.
1.4 Struts2的Action编写:
1.4.1 Action的编写:
三种方式编写Action类:
* Action的类是一个POJO的类.(简单的Java类)
* Action实现一个Action接口.
* SUCCESS:成功
* NONE:页面不需要跳转.
* INPUT:数据校验
* LOGIN:登录视图
* ERROR:错误视图
* Action类继承一个ActionSupport类.(******)
* 继承了ActionSupport之后,Action类中就会有数据校验、国际化...功能
1.4.2 Action中的方法的访问:
一般一个模块的代码会提交到一个Action中,编写一个Action,在Action中提供多个业务的操作的方法.
在页面中:
<h1>员工管理</h1>
<a href="${ pageContext.request.contextPath }/addEmp.action">添加员工</a>
<a href="${ pageContext.request.contextPath }/modifyEmp.action">修改员工</a>
<a href="${ pageContext.request.contextPath }/deleteEmp.action">删除员工</a>
<a href="${ pageContext.request.contextPath }/findEmp.action">查看员工</a>
在Action中:
public class EmpAction extends ActionSupport{
public String add(){
System.out.println("添加员工...");
return NONE;
}
public String modify(){
System.out.println("修改员工...");
return NONE;
}
public String delete(){
System.out.println("删除员工...");
return NONE;
}
public String find(){
System.out.println("查询员工...");
return NONE;
}
}
在struts.xml中配置:
<action name="addEmp" class="cn.itcast.struts2.demo4.EmpAction" method="add"></action>
<action name="modifyEmp" class="cn.itcast.struts2.demo4.EmpAction" method="modify"></action>
<action name="deleteEmp" class="cn.itcast.struts2.demo4.EmpAction" method="delete"></action>
<action name="findEmp" class="cn.itcast.struts2.demo4.EmpAction" method="find"></action>
以上这种编写的方式也不是特别的好,因为一个模块的执行的方法过多,需要配置的内容就会很多
* 可以采用通配符的形式进行配置Action中的某个方法的执行.
* 通配符的用法有一个要求:
* 访问路径和执行的方法名有一定的联系!!!
在页面中:
<h1>图书管理</h1>
<a href="${ pageContext.request.contextPath }/book_add.action">添加图书</a>
<a href="${ pageContext.request.contextPath }/book_modify.action">修改图书</a>
<a href="${ pageContext.request.contextPath }/book_delete.action">删除图书</a>
<a href="${ pageContext.request.contextPath }/book_find.action">查看图书</a>
Action的类:
public class BookAction extends ActionSupport{
public String add(){
System.out.println("添加图书...");
return NONE;
}
public String modify(){
System.out.println("修改图书...");
return NONE;
}
public String delete(){
System.out.println("删除图书...");
return NONE;
}
public String find(){
System.out.println("查看图书...");
return NONE;
}
}
在struts.xml中的配置:
<action name="book_*" class="cn.itcast.struts2.demo4.BookAction" method="{1}"></action>
1.4.3 动态方法访问:
使用动态方法访问形式访问Action中的某个方法.在配置文件struts.xml中必须开启一个常量.
* <constant name="struts.enable.DynamicMethodInvocation" value="true"/>
访问路径:
* 规则:Action的访问路径!方法名.action
* <a href=”/struts2_day01/book!add.action”>添加图书</a>
页面:
<h1>订单管理</h1>
<a href="${ pageContext.request.contextPath }/order!add.action">添加订单</a>
<a href="${ pageContext.request.contextPath }/order!modify.action">修改订单</a>
<a href="${ pageContext.request.contextPath }/order!delete.action">删除订单</a>
<a href="${ pageContext.request.contextPath }/order!find.action">查看订单</a>
Action:
public class OrderAction extends ActionSupport{
public String add(){
System.out.println("添加订单");
return NONE;
}
public String modify(){
System.out.println("修改订单");
return NONE;
}
public String delete(){
System.out.println("删除订单");
return NONE;
}
public String find(){
System.out.println("查询订单");
return NONE;
}
}
struts.xml中配置
<!-- 动态方法访问的配置 -->
<action name="order" class="cn.itcast.struts2.demo4.OrderAction"/>
1.5 Struts2中Servlet API的访问
Struts2中要访问Servlet的API有三种形式:
* 1.完全解耦合的形式完成ServletAPI的访问.
* 使用ActionContext对象:
* Map<String,Object> getParameters();----接收请求参数
* Map<String,Object> getSession();----获得的是session的Map.
* 操作session的方式
* session.setAttribute(String name,Object value);
* session.getAttribute(String name);
* 在struts2中操作session:
* Map<String,Object> map = getSession();
* map.put(key,value);
* Map<String,Object> getApplication()----获得的是application的Map.
* void put(String key,Object value);----向ActionContext中存值.(相当于存入request域中)
* Object get(String key);----从ActionContext中获取值.(相当于从request域中获得值)
* 2.接口注入的形式:实现一些接口访问ServletAPI:
* ServletRequestAware
* ServletResponseAware
* ServletContextAware
* 3.使用一个类ServletActionContext中静态方法
* static HttpServletRequest getRequest()
* static HttpServletResponse getResponse()
* static ServletContext getServletContext()
* static PageContext getPageContext()
***** 第一种最好的因为解耦合的方式:
1.6 Struts2中Servlet API的访问总结
1.完全解耦合的形式完成ServletAPI的访问.
使用ActionContext对象
*获取ActionContext--->ActionContext ac = ActionContext.getContext();-其实该对象就是request域对象,实质是一个map
ac.getSession()-获取session 继而可以对session进行操作,获取到的session也是一个实质为map的session域对象
ac.getApplication();-获取application 可以对application进行操作,获取的也是一个实质为map的application域对象
2.接口注入的形式 访问Servlet API的方式.
* ServletRequestAware
* ServletResponseAware
* ServletContextAware
使action类实现这几个接口 其中就有了相应的ServletRequest,ServletResponse,ServletContext对象,想在类中使用
只需要声明相应的变量,再对变量提供set方法 就可以使用了
如:private HttpServletRequest request;
private ServletContext context;
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
public void setServletContext(ServletContext context) {
this.context = context;
}
3.使用一个类ServletActionContext中静态方法
HttpServletRequest request = ServletActionContext.getRequest();-获取request
request.getSession()-获取session
ServletContext application = ServletActionContext.getServletContext();-获取application对象
1.7 Struts2中结果页面配置:
结果页面的配置分成两种:
* 全局结果页面配置:
<!-- 配置一个全局结果页面 -->
<global-results>
<result>/demo5/success.jsp</result>
</global-results>
* 局部结果页面配置:
<action>
<result></result>
</action>
结果页面类型:
* <result>标签中
* 属性:
* name:结果页面的逻辑视图名称,默认值是success.
* type:页面跳转的方式.
* 结果页面的类型的定义:struts-default.xml中
<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-types>
* 常用的结果页面的类型:
* dispatcher:type属性的默认值.转发.(一般情况下转发到JSP)
* redirect:重定向.(一般情况下重定向到JSP)
* chain:转发.(一般情况下转发到一个Action)
* redirectAction:重定向到另一个Action
* stream:struts2的文件下载中使用.
1.8 综合的案例
1.8.1 登录的功能.
1.创建一个web项目
2.导入相应的jar包
* struts2的11个jar包
* c3p0
* mysql
* dbUtils
* JSTL--->2个
* BeanUtils--->2个
3.创建数据库
create database struts2_day01;
use struts2_day01;
create table user(
id int primary key auto_increment,
username varchar(20),
password varchar(20)
);
insert into user values (null,'admin','admin');
4.创建包结构
* cn.itcast.action
* cn.itcast.service
* cn.itcast.dao
* cn.itcast.vo
5.设计页面:
<h1>登录页面</h1>
<form action="" method="post">
<table border="1" width="400">
<tr>
<td>用户名</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="登录"></td>
</tr>
</table>
</form>
6.配置核心过滤器
<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>
7.配置struts.xml
<package name="user" extends="struts-default">
<!-- 全局结果页面 -->
<global-results>
<result name="login">/jsp/login.jsp</result>
</global-results>
<action name="user_*" class="cn.itcast.action.UserAction" method="{1}">
<result name="success" type="redirect">/jsp/success.jsp</result>
</action>
</package>
8.编写Action类:
public class UserAction extends ActionSupport{
// 提供一个login的方法
public String login(){
// 1.接收数据
HttpServletRequest request = ServletActionContext.getRequest();
Map<String,String[]> map = request.getParameterMap();
// 2.封装数据
User user = new User();
try {
BeanUtils.populate(user, map);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
// 3.处理数据
UserService us = new UserService();
User existUser = us.login(user);
// 4.显示到JSP
if(existUser == null){
// 用户名或密码错误
request.setAttribute("msg", "用户名或密码错误!");
return LOGIN;
}else{
// 登录成功
// 保存用户的信息到session中
request.getSession().setAttribute("existUser", existUser);
return SUCCESS;
}
}
}