MVC 思想
M |
V |
C |
Model |
View |
Controller |
数据模型层:DAO/service/entity |
视图层: Jsp/html/freemarker/volicity |
控制层:servlet、struts2、springMVC |
MVC思想的好处:解耦合,提高系统的可维护性和可拓展性
Struts2框架概述: 充当了MVC中的C 替换了Servlet //底层封装了Servlet相关API, 但是它不是 Servlet
也就是应用javaee三层结构中的web层框架 实在struts1 和webwork基础上发展的全新框架。
web层常见框架 :
(1) struts2
(2)springMVC
Struts2官方文档目录:
如果想要使用Struts2框架 首先需要导入jar包
(1)在lib中有jar包,不能把这些jar都导入到项目中
(2)到apps目录里面,找到示例程序,从示例程序复制jar包
做初始化配置 - 开启struts2框架 在web.xml中进行配置
类比于web中的Servlet 每次访问的时候都会执行service方法
每次访问action都会执行execute方法
public String execute() throws Exception { return SUCCESS; }
配置action的访问路径
创建struts2的核心配置文件
核心配置文件名称和位置都是固定的 位置必须在src下 ,名称 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>
访问路径是localhost:8087/项目名/action中name属性的值。
struts2的执行过程
过滤器在服务器启动的时候进行创建,创建过滤器的时候执行init方法
在init方法中主要加载配置文件 包含自己创建的配置文件和struts2自带的配置文件
struts.xml
web.xml
struts2的配置文件详解
<package name="find" extends="struts-default" namespace="/"> <action name="findUser" class="com.baizhi.action.findLink"> <result name="success">/linkmanList.jsp</result> </action> </package>
标签package
类似于包 主要用于区分不同的action ,
name属性:在一个配置文件中可以有多个package 但是package得name属性值不能相同
extends="struts-default" 属性值是固定的 只有写了这个属性之后,在package里面配置的类具有action功能
namespace ="" namespace与action中的name属性值构成访问路径
每一个package标签都有一个namesapce属性,主要的作用就是从访问路径上、区分不同package下的action,namespace的值是访问某个action路径的一部 分,namespace的值 必须 以 / 开头。
注意:namespace 的默认值 是 / ,在同一个struts.xml中,只能有一个package的默认形式。
标签action=""
name 属性 配置action的访问路径 与namespace进行配合
在一个package中可以有多个action标签,但是action的name属性值不能相同
class 属性 action的全限定性类名
method 属性
在一个action中默认执行的是execute方法如果想在同一个actuion中执行自定义方法则需要这个属性
<action name="password_*" class="com.baizhi.action.modifyLink" method="{1}"> <result name="success" type="redirectAction">findUser</result> <result name="ok" type="redirectAction">findUser</result> </action>
例如: password_update 那么数字1 代表update *的占位符 几个* 就代表数字几
标签result
1 根据action的方法返回值,配置到不同的路径里面
2 result标签属性
(1)name属性
- 和方法返回值一样
标签Type
- 配置如何到路径中(转发或者重定向)
- type属性默认值 做转发操作
跨包跳转 只有action->action
同一个package下的跳转
1. action-->jsp
forward(默认状态)
<result name="ok" type="dispatcher">/success.jsp</result>
redirect
<result name="ok" type="redirect">/success.jsp</result>
2.action—>action
forward
<result name="ok" type="chain">action名字没有 / </result>
redirect
<result name="ok" type="redirectAction">action名字没有 / </result>
全局跳转
作用:解决result标签配置冗余
注意:1.全局跳转标签必须配置在所有action之前。
2.全局跳转只在本包内有效
3.当全局跳转与 局部跳转冲突的时候 ,会以局部跳转优先。
总结跳转:
Struts2常量配置
<!-- 设置默认的编码集 --> <constant name="struts.i18n.encoding" value="utf-8"></constant>
(1)表单提交数据到action里面,在action可以获取表单提交数据,
(2)表单提交数据有中文,有乱码问题,解决:
- post提交直接设置编码
- get提交做编码转换
(3)如果在action获取表单通过post方式提交中文,中文乱码问题帮解决了,不需要自己处理问题
Struts2的分模块开发
单独写配置文件将配置文件引入到核心配置文件中
<include file="com/baizhi/config/modify.xml"></include>
Action编写的三种方式
第一种 创建普通类,这个不继承任何类,不实现任何接口
第二种 创建类,实现接口 Action
第三种 创建类,继承类 ActionSupport(一般使用)
访问action的方法重点
第一种 使用action标签的method属性,在这个属性里面写执行的action的方法
使用Method访问
第二种 使用通配符方式实现
在action标签里面name属性,name属性值里面写 符号 * 星号
(1)* 理解: 表示匹配任意内容
- 比如访问hello,* 可以匹配到
- 比如访问add,* 可以匹配到
第三种 动态访问实现(不用)
action里面的方法可以没有返回值,没有返回值时候,在result标签不需要配置
- 把方法写成void
- 让返回值,返回 ”none”
Action获取表单提交数据
有三种方式: 第一种只是获取表单数据并未进行封装
public String loginJudge() { ActionContext context = ActionContext.getContext(); Map<String, Object> map = context.getParameters(); Set<String> keySet = map.keySet(); for(String key:keySet) { //根据key得到value //数组形式:因为输入项里可能有复选框情况 Object[] value = (Object[]) map.get(key); System.out.println(Arrays.toString(value)); } return SUCCESS; }
第二种:使用 ServletActionContext进行获取
调用类里面静态方法,得到request对象
public String loginJudge2() { HttpServletRequest request = ServletActionContext.getRequest(); String username = request.getParameter("username"); String password = request.getParameter("password"); return SUCCESS; }
第三种:使用接口注入的方式
在action中操纵域对象
使用ServletActionContext进行获取
Struts2 获取表单数据并封装
方法一:获取request对象 不再介绍
方法二:属性封装
定义成员变量:1.提供set、get方法
2.成员变量属性一定要与form表单中name属性的值保持一致。
方法三: 模型驱动封装(重点)
public class loginUser extends ActionSupport implements ModelDriven<User>{ private User user = new User(); //使用模型驱动 @Override public User getModel() { // TODO Auto-generated method stub return user; } }
要求表单输入项name值和实体类属性名称一样
注意:
在一个action中,获取表单数据可以属性封装,使用模型驱动封装,不能同时使用属性封装和模型驱动封装获取同一个表单数据如果同时使用,之后执行模型驱动。
方法四 表达式封装(会用)
在表单输入项的name属性值里面写表达式形式
比较表达式封装和模型驱动封装
不同点:
1)使用模型驱动只能把数据封装到一个实体类对象里面
- 在一个action里面不能使用模型驱动把数据封装到不同的实体类对象里面
(2)使用表达式封装可以把数据封装到不同的实体类对象里面
封装数据到集合中
(1)封装数据到list中
第一步 在action声明List
第二步 生成list变量的set和get方法
第三步 在表单输入项里面写表达式
封装数据大map集合
第一步 声明map集合
第二步 生成get和set方法
第三步 在表单输入项的name属性值里面写表达式
OGNL概述
1 之前web阶段,学习过EL表达式,EL表达式在jsp中获取域对象里面的值
2 OGNL是一种表达式,这个表达式功能更加强大,
(1)在struts2里面操作值栈数据
(2)一般把ognl在struts2操作:和struts2标签一起使用操作值栈
3 OGNL不是struts2的一部分,单独的项目,经常和struts2一起使用
(1)使用ognl时候首先导入jar包,struts2提供jar包
<%@taglib prefix="s" uri="/struts-tags" %>
<s:properties value="haha".length()> 字符串的长度
Struts2中有一个重要的概念就是值栈
1 之前在web阶段,在servlet里面进行操作,把数据放到域对象里面,在页面中使用el表达式获取到,域对象在一定范围内,存值和取值
2 在struts2里面提供本身一种存储机制,类似于域对象,是值栈,可以存值和取值
(1)在action里面把数据放到值栈里面,在页面中获取到值栈数据
3 servlet和action区别
(1)Servlet:默认在第一次访问时候创建,创建一次,单实例对象
(2)Action:访问时候创建,每次访问action时候,都会创建action对象,创建多次,多实例对象
4 值栈存储位置
(1)每次访问action时候,都会创建action对象,
(2)在每个action对象里面都会有一个值栈对象(只有一个)
获取值栈对象
//获取ActionContext类的对象
ActionContext context = ActionContext.getContext();
//调用方法得到值栈对象
ValueStack value = context.getValueStack()
每个action对象中只有一个值栈对象
1 值栈分为两部分:
第一部分 root,结构是list集合
(1)一般操作都是root里面数据
第二部分 context,结构map集合
struts2里面标签 s:debug,使用这个标签可以查看值栈结构和存储值
(1)访问action,执行action的方法有返回值,配置返回值到jsp页面中,在jsp页面中使用这个标签
在action没有做任何操作,栈顶元素是 action引用
- action对象里面有值栈对象
- 值栈对象里面有action引用
1 向值栈放数据多种方式
第一种 获取值栈对象,调用值栈对象里面的 set 方法
第二种 获取值栈对象,调用值栈对象里面的 push方法
第三种 在action定义变量,生成变量的get方法
1. 向值栈中放对象
1 实现步骤
第一步 定义对象变量
第二步 生成变量的get方法
第三步 在执行的方法里面向对象中设置值
2. 向值栈放list集合
第一步 定义list集合变量
第二步 生成变量的get方法
第三步 在执行的方法里面向list集合设置值
从值栈中获取数据
方法一:
使用struts2的标签+ognl表达式获取值栈数据
(1)<s:property value=”ognl表达式”/>
向值栈中放入字符串
从值栈中获取
<s:property value=”username”/>
向值栈中放入对象
在页面中获取
向值栈中放入集合 同上
从值栈中取出集合
方式一:
方式二
方式三:
从值栈中取出数据的其他操作
第一种 : 使用set方法向值栈放数据,获取
第二种: 使用push方法向值栈放数据,获取
注意:
(1)使用push方法设置值,没有名称,只有设置的值
(2)向值栈放数据,把向值栈放数据存到数组里面,数组名称 top,根据数组获取值
EL表达式获取值栈数据(为什么)
1 EL表达式获取域对象值
2 向域对象里面放值使用setAttribute方法,获取值使用getAttribute方法
3 底层增强request对象里面的方法getAttribute方法
(1)首先从request域获取值,如果获取到,直接返回
(2)如果从request域获取不到值,到值栈中把值获取出来,把值放到域对象里面
OGNL的#、%使用
1 使用#获取context里面数据
1 在struts2标签中表单标签
(1)在struts2标签里面使用ognl表达式,如果直接在struts2表单标签里面使用ognl表达式不识别,只有%之后才会识别。
Struts2拦截器概述
1 struts2是框架,封装了很多的功能,struts2里面封装的功能都是在拦截器里面
2 struts2里面封装了很多的功能,有很多拦截器,不是每次这些拦截器都执行,每次执行默认的拦截器
3 struts2里面默认拦截器位置
拦截器在什么时候执行
(1)在action对象创建之后,action的方法执行之前
拦截器的底层原理
Aop是面向切面(方面)编程,有基本功能,扩展功能,不通过修改源代码方式扩展功能
第二个 责任链模式
(1)在java中有很多的设计模式,责任链模式是其中的一种
(2)责任链模式和过滤链很相似的
责任链模式:
要执行多个操作,有添加、修改、删除三个操作。
首先执行添加操作,添加操作执行之后 做类似于放行操作,执行修改操作,修改操作执行之后做类似于放行操作,执行删除操作
过滤链:一个请求可有多个过滤器进行过滤,每个过滤器只有做放行才能到下一个过滤器
过滤器和拦截器的的区别
(1)过滤器:过滤器理论上可以任意内容,比如html、jsp、servlet、图片路径
(2)拦截器:拦截器只可以拦截action
2 Servlet和action区别
(1)servlet默认第一次访问时候创建,创建一次,单实例对象
(2)action每次访问时候创建,创建多次,多实例对象
自定义拦截器
开发中,建议使用另外一种方式
- 写类,继承 MethodFilterInterceptor类实现
-- 让action里面某个的方法不进行拦截
让拦截器和action有关系
- 不是在action调用拦截器的方法,而是通过配置文件方式让建立关系
第一步 创建类,继承MethodFilterInterceptor类
第二步 重写MethodFilterInterceptor类里面的方法写拦截器逻辑
(1)在要拦截的action标签所在的package标签里面声明拦截器
(2)在具体的action标签里面使用声明的拦截器
struts2里面执行很多的默认拦截器,但是如果在action里面配置自定义拦截器,
问题:默认的拦截器不会执行了
解决:把默认拦截器手动使用一次
Struts2的标签库
1 s:property: 和ognl表达式在jsp页面中获取值栈数据
2 s:iterator: 获取值栈list集合数据,表示list集合
3 s:debug: 查看值栈结构和数据
<s:form theme="simple"> <s:textfield name="username" lable="username"> </s:textfield> label="username"会将username显示在文本框前面 <s:password name="password" label="password"></s:password> <s:radio list="{'女','男'}" name="sex" label="性别"></s:radio> <s:radio list="#{'nv':'女' ,'nan':'男'}" name="sex" label="性别"></s:radio> 表示构建了一个map集合 <s:checkboxlist list="{'游泳' , '唱歌'}" name="love" label="爱好"></checkboxlist> <s:select list="{'小学','大学','博士'}" name="college" label="学历"></s:select> <s:file name="file" label="上传文件"></s:file> <s:hidden name="hid" value="abcd" ></s:hidden> <s:submit value="提交"></s:submit> <s:reset value="重置" > </s:reset> <s:textarea rows="10" cols="3" name="resum" label="简历"></s:textarea> </s:form>
如果eclipse没有提示的解决方法的
windows ---》preferencecs--》