什么是MVC
1.Model模型 模型的职责是负责业务逻辑,包含两部分:业务数据和业务处理逻辑.比如实体类, DAO,Service都属于模型层 2.View视图 视图的职责是显示界面和用户交互(收集用户信息)。属于视图的类是不包含业务 逻辑和控制逻辑的JSP 3.Controller控制器 控制器是模型层和视图层之间的桥梁,用于流程控制。比如我们之前项目中的ActionServlet 写Struts2所需要的控制器配置文件struts.xml非常重要,该文件写请求与各个Action的对应关系, 前端控制器会根据配置信息调用对应的Action(Java类)去处理请求 注意事项: a.在编写struts.xml放在src目录中,而部署后该文件位于WEB-INF/classes中 b.同样的,.properties文件也放在src下,部署后也在WEB-INF/classes/下 c.程序一启动,struts.xml就会被加载到内存,并不是现读的 d.程序一启动,struts.xml就会被加载到内存,并不是现读的. Struts2提供的方便之处 1.数据的自动封装(输入属性) 根据页面组件的name属性,自动给Action中的属性赋值 2.数据的自动传递 Action中的属性在JSP页面可以直接用EL表达式拿到,即自动调用某属性的get方法 Struts2对EL表达式的支持 EL表达式是默认访问page,request,session,application范围的数据 在Strust2中也可以使用EL表达式访问Action对象的属性.访问顺序是page,request, root栈(action),session,appliction.当EL从request中获取不到信息后,会去 ValueStack对象的root栈获取,原因是:Struts2重写了HttpServletReqeust的方法。 Struts2的工作流程: 1.所有请求提交给前端控制器(FC) 2.根据配置信息确定要调用的Action 3.创建一个ValueStack对象(每个请求都有一个独立的VS对象) 4.创建Action对象,把Action对象放在VS栈顶,将VS对象存到request中,存储的key为 "struts.valueStack" 5.控制器调用Action对象接收请求参数,并在方法根据输入属性算出输出属性 6.在调用Action之前或之后调用一系列Interceptor 7.根据Action返回的字符串确定Result(10种类型) 8.调用Result对象,将VS中的数据按照特定的格式输出 9.很多情况下,Result将转发JSP,JSP页面用Tags取出数据并显示 10.请求处理完后,将ValueStack对象和Action对象销毁。 在Action中访问Session和Application 1)利用ActionContext,返回Map类型 ActionContext context=ActionContext.getContext(); Map<String,Object> session=context.getSession() session.put("usernmae":"chang"); Map<String,Object> rquest=(Map)context.get("request"); Map<String,Object> app=context.getApplication(); 注意事项 :不推荐使用ActionContext访问Session的方式,困为这种方式的 “侵入性”较强。ActionContext是Struts2的API,如果使用其他框架代替目前的Struts2 框架,而我们实际项目中的Action数量是非常大的,每个类修改的话,会非常麻烦。 推荐使用实现SessionAware接口的方式 2)ServletActionContext返回的是Servlet使用类型 HttpServletRequest httpreq=ServletActionContext.getRequest() HttpSession httpsession=httpreq.getSession(); ServlerContext httpapp=ServletActionContext.getServletContext(); 3)由Action中实现Aware接口,由框架底层将对象注入给Action变量 RequestAware:Map类型的request SessionAware:Map类型的session ApplicationAware:Map类型的application ServletRequestAware:http ActionContext与ServletActionContext获取Session的异同 1.ActionContext 我们在Action中取得request请求参数"username", ActionContext cont=ActionContext.getContext(); Map params=cont.getParameters(); String username=(String)params.get("username"); static ThreadLocal actionContext=new ActionContextThreadLocal(); ActionContextThreadLocal是实现ThreadLocal的一个内部类,ThreadLocal 可以命名为"线程局部变量",它为每一个使用该变量的线程提供一个变量值的 副本,使每一个线程都可以独立地改变自己的副本,而不会和其他线程的副本 冲突,这样,我们ActionContext里的属性只会在对应的当前请求线程中可见, 从而保证它是线程安全的. 通过ActionContext取得HttpSession: Map session=ActionContext.getContext().getSession(); 2.ServletActionContext ServletActionContext,这个类直接继承了我们上面介绍的ActionContext,它提供了直接 与Servlet相关对象访问的功能,它可以取得的对象有 : 1)javax.servlet.http.HttpServletRequest:HTTPservlet请求对象 2)javax.servlet.http.HttpServletResponse:HTTPservelt响应对象 3)javax.servlet.ServletContext:Servlet上下文信息 4)javax.servlet.ServletConfig:Servlet配置对象 5)javax.servlet.jsp.PageContext:Http页面上下文 如何从ServletActionContext里取得Servlet相关对象 a.取得HttpServletRequest对象 HttpServletRequeste request=ServletActionContext.getRequest(); b.取得HttpSession对象: HttpSession session=ServletActionContext.getRequeset.getSession(); 3.ServletActionContext和ActionContext联系 ServletActionContext和ActionContext有着一些重复的功能,在我们的Action中,该 如何抉择呢? 如果ActionContext能够实现我们的功能,那最好不要使用ServletActionContext,让我们的 Action尽量不要直接去访问Servlet的相关对象 注意:在使用ActionContext时有一点要注意:不要在Action的构造函数里使用ActionContext.getContext, 因为这个时候ActionContext里的一些值也许没有设置,这里通过ActionContext取得的值也许是 null,同样,HttpServletRequest req=ServletActionContext.getRequest()也不要放在构造 函数中,至于原因,因为前面讲到的static ThreadLocal actionContext=new ActionContextThreadLocal(),从这里我们可以看出ActionContext是线程安全的。而ServletActionContext 继承自ActionContext,所以ServletActionContext也线程安全,... 4.struts2中获得request,response和session a.非IOc方式 1.使用org.apache.struts2.ActionContext类,通过它的静态方法getContext()获取当前 Action的上下文对象 ActionContext ctx=ActionContext.getContext(); ctx.put("he":"li");//request.setAttribute("he":"li"); Map session=ctx.getSession() HttpServletRequeset request=ctx.get(org.apache.struts2.StrutsStatic.HTTP_REQUEST); HttpServletResponse response=ctx.get(org.apache.struts2.StrutsStatics.HTTP_RESPONSE); 这里的session是Map对象,在Struts2中底层的session都被封装成了Map类型,我们可以直接操作 这个Map对象进行对session的写入和读写操作,而不用直接操作HttpSession对象 2.使用org.apache.struts2.ServletActionContext类 b.IOC方式(即使用Struts2 Aware拦截器) 要使用IOC方式,我们首先告诉IOC容器(Container)想取得某个对象的意愿,通过实现相应的接口 做到这点 public class UserAction extends ActionSupport implements SessionAware,ServletRequestAware, ServletResponseAware { private HttpServletRequeset request; private HttpServletResponse response; public void setServletRequest(HttpServletRequest request) { } } 用LoginAction继承BaseAction public BaseAction implements SessionAware{ protected Map<String,Object> session; public void setSession(Map<String,Object> session) { this.session=session; } } 该类实现了SessinoAware接口,表示Struts2在启动BaseAction时,首先,创建出 该Action的对象,放入"栈顶",后调用BaseAction的setSession方法,把session传入 给BaseAction对象(注意:如果是普通的Action,Struts2在启动时仅创建出该Action的对象, 然后放入“栈顶”),由此,我们定义了session属性,以便在之后其他的方法中使用,为了让 子类也能使用,所以访问控制符为protected. 按照这样的机制,我们可以让所有的Action( 如LoginAction)继承实现了SessinAware接口 的BaseActino,当需要更换Struts2框架为其他框架时,只需要修改BaseAction即可(另外的框架 只要提供一个类似SessionAware接口的接口,由BaseAction继承) Action属性注入 在<action>配置中,为Action组件的属性指针一个初始值,该值在创建Action对象时注入, 可以将一些变化的参数值,利用该方法指定。 例如:pageSize,password,dir存储路径等 public class ParamAction{ private String param1; private String param2; ...各自的get/set方法 } <action name="param" class="com.isoftstone.ParamAction"> <param name="param1">abc</param> <param name="param2">10</param> </action>