1、第 1 页可以看我的另一个文档是关于Servlet和Ajax的一些学习笔记,纯手写。地址:http:/ (cart.jsp)M部分:JavaBean组件(entity,dao)C部分:Servlet,Filter组件 (ShoppingCartServlet)*d.MVC处理流程-首先浏览器发出请求-请求进入C控制器-C控制器调用M模型组件处理-M模型组件处理后返回处理结果- C控制器调用V视图组件生成响应信息*e.Struts框架的MVC实现原有ShoppingCart程序,虽然符合MVC结构,但不适合大型项目开发,因为请求一多,ShoppingCartServlet会出现大量的ifelse
2、. ,可以进行以下方式的改造为ShoppingCartServlet配置一个XML文件,该文件定义不同请求和不同Action组件的对应关系,将原有ifelse分支处理用Action组件封装。*f.Struts框架的处理流程-浏览器发出struts请求-请求进入struts控制器第 2 页-struts控制器解析xml配置文件(xml定义了请求和Action对应关系)-控制器根据不同请求,调用不同的Action-Action调用DAO处理请求,之后返回结果-控制器根据结果调用视图组件为用户响应3.了解Struts历史Struts框架分成Struts1和Struts2.Struts2和Struts
3、1没有必然联系。Struts2是以WebWork框架核心(xwork)为基础构建起来*4.Struts基本使用a.引入struts2核心开发包(5个)-struts2-core-2.1.8.jar (核心包)-xwork-core-2.1.6.jar (webwork内核包)-commons-fileupload-1.2.1.jar (上传包)-ognl-2.7.3.jar (OGNL表达式工具包)-freemarker-2.3.15.jar (模板视图工具包)b.在web.xml中配置下struts控制器c.根据请求编写Action,JSPd.在struts.xml定义Action和请求对应
4、关系5.HelloWord入门实例welcome.actionStruts控制器struts.xmlWelcomeActionwelcome.jsp(Action请求可以是/welcome.action或者/welcome两种写法)=struts.xml基本配置=struts.xml放在src根目录下。a) 根元素,可以包含多个元素b)元素主要用于将Action分组定义。name属性用于指定包名;extends一般指定为struts-default。struts-default这个包在struts-default.xml中定义,其中包含了struts2运行所需的必要组件。c)一个元素可以包含多
5、个.主要用于定义请求和Action组件的对应关系。name属性指定请求名;class属性指定Action的包名.类名d)一个元素可以包含多个.主要用于定义视图响应。name属性与Action.execute()返回值一致。=扩展HelloWorld示例a.隐藏JSP组件b.从WelcomeAction向Welcome.jsp传值c.WelcomeAction接收welcome.action请求带过来的表单信息d.页面跳转可以采用下面配置第 3 页jsp页面如果不指定class属性,会默认调用框架底层的ActionSupport类处理。=课后练习=1.完成helloworld示例-回顾-1.了解
6、Struts2的MVC实现,及其工作流程2.掌握Struts2的核心应用-任务描述:1)为列表添加分页功能1页:1-22页:3-43页:5-6page=1pageSize=2int begin = (page-1)*pageSize+1;int end = page*pageSize;select * from(select rownum rn,c.*from COST c where rownum=52)利用Struts2标签+OGNL技术-1.OGNL技术的使用1)什么是OGNL源于ognl.jar工具包Object Graphics Navigation Language(对象图导航语言
7、)主要用于访问对象的数据和方法。2)OGNL基本原理OGNL工具主要由3部分构成,具体如下第 4 页a.OGNL引擎负责解析ONGL表达式,定位数据b.Root根存储区(Object类型)负责存储要访问的目标对象。c.Context变量存储区(Map类型)负责存放多个要访问的目标对象。*3)OGNL基本语法a.访问Root区域对象基本语法-访问简单数据:“属性“ 例如“name“-访问数组或List集合:“属性0“例如“arr1“-访问Map集合:“属性key“或“属性.key“例如“map.two“或“maptwo“-访问方法:“属性值.方法()“,例如“list.size()“-访问构造方
8、法:“new 包名.构造方法“例如“new java.util.Date()“-访问静态成员:“包名.类名成员“例如“java.lang.MathPI“-创建List对象:“元素1,元素2“-创建Map对象:“#key1:value1,key2:value2“b.访问Context区域对象基本语法采用“#Key“开头.2.OGNL技术在Struts的使用在Struts2中有一个ValueStack数据对象,该对象存储了请求相关的所有数据信息。例如request,session,application,action等.Struts2采用OGNL工具对ValueStack进行操作。1)xwork对
9、OGNL进行了部分改造在xwork中将原来OGNL标准结构中的Root存储区改造成了一个栈结构(CompoundRoot)当利用“属性“表达式访问时,优先去栈顶对象寻找,没有再去次栈顶寻找。2)ValueStack结构(OgnlValueStack)(参考valuestack.jpg)3)Struts2标签的使用在JSP中,利用Struts2标签显示数据,需要为标签指定OGNL表达式,标签利用表达式定位ValueStack中的数据,进行相应操作。a) debug标签:显示valuestack状态b) iterator标签:循环集合元素第 5 页分页中用到了value属性:指定循环集合ognlv
10、ar属性:指定循环变量,会被存放到ValueStack的context区域。status属性:指定循环状态变量,会被存放到ValueStack的context区域.该变量有count 属性表示一共循环了多少个元素(从1开始)。index属性表示当前循环元素的索引(从0开始)。c) if.else.标签:判断分支 暂停 开通test属性:指定ognl判断表达式d) property标签:显示数据value属性:指定ognl表达式e) date标签:将date数据格式化输出name属性:指定ognl表达式format属性:指定日期模板1.Action组件的相关使用1)Action组件的原理-客户发
11、出action请求给struts控制器-struts控制器会创建valuestack对象-struts控制器根据请求创建Action对象并将Action压入valuestack的root栈顶(Action线性安全,不用考虑并发问题)-struts控制器将请求相关request,session对象放入到valuestack的context区域-struts控制器执行Action对象的execute方法处理请求-struts控制器根据execute结果生成响应信息输出-请求处理完毕,销毁valuestack和Action对象。*2)Action中如何使用session,requesta.利用Act
12、ionContext和ServletActionContext工具类ActionContext返回是Struts框架封装成Map之后的 request,session,Application.ServletActionContext返回的是Servlet中使用的request, session,application原有类型。(使用建议:存值取值建议用Map结构API,如果有特殊需求再采用Servlet原有类型)(推荐) b.利用Aware接口方式注入RequestAware 对应的是Map结构的RequestSessionAware 对应的是Map结构的SessionApplicationA
13、ware 对应的是Map结构的Application第 6 页ServletRequestAware对应的HttpServletRequestServletResponseAware对应的HttpServeltResponseServletContextAware对应的ServletContext(建议:Action使用时采用Aware方式,Action之外使用时采用ActionContext工具类)-如何将原有HttpSession封装成Map-public class SessionMap extends AbstractMapprivate HttpSession session;pub
14、lic SessionMap(HttpSession session)this.session = session; public void put(Object key,Object val)session.setAttribute(key,val);public Object get(Object key)session.getAttribute(key); *3)Action属性注入在配置中,为Action对象的属性指定初始值。使用格式如下:属性值4)Action通配符配置在配置时,name请求名可以使用若干个*符号。然后再其他属性中通过使用1,2引用第一个*号,第二个*号所代表的字符串
15、。2.Result组件的相关使用1)Result组件原理a.Result组件的作用Result组件负责生成响应视图内容。Struts2框架提供了多种不同的Result组件类型,用于做不同形式响应。例如json数据响应,流数据响应,jsp响应等。b.Result组件相关配置-Result声明定义第 7 页-Result使用定义a.编写一个转发功能的Result组件public class MyDispatcherResultimplements Resultprivate String location;/setter和getter方法/约定方法public void execute()Http
16、ServletRequest request = ServletActionContext.getRequest();HttpServletResponse response = ServletActionContext.getResponse();RequestDispatcher rd = request.getRequestDispatcher(location);rd.forward(request,response); *2)掌握经常使用的Result组件a. JSP视图-dispatcher(默认):以转发方式调用JSP-redirect:以重定向方式调用JSPjsp页面b.Act
17、ion视图-chain:以转发方式调用下一个Action-redirectAction:以重定向方式调用下一个Action=相同命名空间调用=请求名=跨命名空间调用=请求名/-前期回顾-1)第一天第 8 页理论:Struts2的MVC结构和处理流程技能:掌握Struts2基本使用2)第二天理论:Struts2中ValueStack结构技能:OGNL基本语法Struts2常规标签3)第三天理论:Action原理,Result原理技能:Request,Session等对象使用Action属性注入dispatcher,redirect,redirectAction,chain=补充EL问题=在JSP
18、中,利用EL表达式可以从page,request,session,application范围取值显示。在Struts2中,利用EL表达式可以page, request,valuestack(root), session,application.原因是Struts2将原有Request对象进行了封装。public class StrutsRequestWrapper extends HttpServletRequestWrapper/重写public Object getAttribute(String key)/寻找原request信息Object obj = super.getAttribu
19、te(key);if(obj = null)/寻找valuestack信息obj = valuestack.findValue(key);/Ognl.getValue(key,context,root);return obj;$name request.getAttribute(“name“)Ognl.getValue(“name“,context,root)=第四天=1.任务描述1)完成登录验证码stream Result2.stream Result组件主要负责将Action中的一个InputStream类型的属性以字节流方式输出。验证码功能流程设计:image.actionImageAc
20、tionstream响应-3.json Result组件主要负责将Action的属性以json字符串格式输出。json Result的使用步骤:第 9 页a.引入struts2-json-plugin.jarb.将元素的extends继承 “json-default“c.使用配置/1) 只返回Action中一个属性值属性名/2) 返回Action中多个属性值属性名1,属性名2,属性名3/返回Action中所有属性值-1.拦截器组件Struts2框架提供了大量的拦截器组件,如果不能满足开发者需要,可以进行自定义。一般利用拦截器封装一些通用性功能。例如请求参数给action赋值,文件上传,权限检查
21、等。1)拦截器作用拦截器可以在Action和Result组件调用之前执行,也可以在Action和Result组件之后执行。2)拦截器原理a.所有拦截器组件实现类都必须实现Interceptor接口的interceptor方法。还有extends AbstractInterceptor抽象类(常用)public class MyInterceptor implements Interceptorpublic String intercept(ActionInvocation in)/拦截器的前期处理逻辑in.invoke();/执行Action和Result/in.invokeActionOnl
22、y();/仅执行Action/拦截器的后期处理逻辑 注意:intercept 方法返回的String,当内容部执行了invoke()方法时,返回值无效。如果没有执行invoke(),返回值有效。控制器会根据该返回值调用一个Result生成响应信息b.所有拦截器都具有下列注册配置第 10 页c.拦截器的使用-为所有Action指定默认使用配置-为某一个Action指定使用配置注意:如果为某个Action指定了拦截器配置,不会再调用指定的默认拦截器.1.Struts2表单标签标签封装了界面显示逻辑,用于简化JSP。a)textfield以输入框方式显示属性值.name属性指定ognl表达式b) t
23、extarea以文本域方式显示属性值.name属性指定ognl表达式c) radio以一组单选框方式显示,并可以根据属性值决定哪个选项选中。list属性指定集合ognl,用于生成若干radio选项。name属性指定ognl,用于决定哪个raido选中。编号:密码框:年龄:性别(单选radio):第 11 页婚姻状况:已婚爱好(多选框):所在城市:Hibernate1.Hibernate框架作用,优点Hibernate框架主要用于对数据库的操作。使用该框架可以简化数据操作代码,要程序员将更多地精力放在业务编写上。Hibernate本质上是对JDBC技术的封装。原有JDBC方式访问数据库,有以下几
24、点不足:a.需要编写大量复杂的SQL语句b.需要做大量的对象和记录的转换c.数据库移植时,需要修改SQL语句。(分页语句,使用数据库函数的语句)使用Hibernate框架后,可以解决上述问题2.Hibernate设计原理Hibernate框架是一款ORM工具。基于ORM设计思想开发出来的。Object-Relation-Mapping对象关系映射。对象指的就是Java的Entity对象;关系指的是关系数据库。思想就是将程序中的对象和数据库中的数据实现自动映射转换。利用ORM工具,再查询时,可以自动将记录封装成Java对象返回。在更新、插入操作时,可以将对象自动写入数据表。像中间的SQL+JDB
25、C操作细节,完全封装在工具底层基于ORM思想设计的框架有很多,例如Hibernate,iBATIS,JPA等.*3.Hibernate框架主要结构Hibernate主要由以下几部分构成:a.Java实体类(n个)用于封装数据表记录的Java对象类型b.hibernate.cfg.xml(1个)Hibernate主配置文件,里面主要定义连接数据库的参数。C 文件名.hbm.xml(n个)Hibernate映射描述文件,里面定义了实体类和数据库之间的对应关系。例如定义了java类和数据表,属性和表字段之间的对应关系。D. Hibernate API第 12 页在使用时,需要使用Hibernate提
26、供的API, 它们将SQL+JDBC操作细节封装起来了。*4.Hibernate主要APIa. Configuration主要用于加载配置文件hibernte.cfg.xml/创建配置对象Configuration conf = new Configuration();/加载指定的hibernate.cfg.xml配置src目录下conf.configure(“/hibernate.cfg.xml“);b. SessionFactory通过Configuration获取,主要用于创建Hibernate中的Session对象。SessionFactory sf = conf.buildSessi
27、onFactory();c. SessionSession session = sf.openSession();代表Java程序与数据库之间一次连接。负责对数据库进行增删改查操作。save(),update(),delete(),load(),get()方法.d. Transaction/开启事务Transaction tx = session.beginTransaction();mit();/提交事务负责事务管理。注意:每次做增删改操作必须得显示提交事务。因为Hibernate将默认提交功能关闭了。e. Query负责执行Hibernate查询语句。*5.Hibernate使用步骤a.创
28、建工程,引入hibernate和驱动开发包b.在src下追加hibernate.cfg.xml主配置c.根据数据表创建Entity实体类d.编写实体类和数据表的映射文件hbm.xmle.利用Hibernate API实现增删改查操作-课后练习-1.基于Cost表做增删改查练习2.重构资费管理模块的添加、开启、删除功能1.Hibernate映射类型在hbm.xml中,描述属性和字段之间映射的时候,可以使用type属性指定映射类型。type属性可以指定Java类型和Hibernate类型。主要作用是指定属性值和字段第 13 页值之间转换时,采用的转换类型。(建议采用Hibernate映射类型)Hi
29、bernate映射类型主要有以下几种:a.整数类型byte,short,integer,longb.浮点数类型float,doublec.字符串类型stringd.日期时间类型date,time,timestampe.boolean类型该类型可以实现boolean属性和字符之间的转换。yes_no:将true|false转换成Y|Ntrue_false:将true|false转换成T|Ff.其他big_decimal,big_integer,clob,blob-案例-create table t_foo(t_id number primary key,t_name varchar2(50),t
30、_salary number(8,2),t_marry char(1),t_hiredate date,t_last_login_time date)-mysql-create table t_foo(t_id int auto_increment primary key,t_name varchar(50),t_salary double,t_marry char(1),t_hiredate date,t_last_login_time timestamp) default charset=utf8;2.Hibernate主键生成方式在hbm.xml中,可以为主键指定生成方式。具体如下:*a
31、. sequence :采用指定序列生成,适用于Oracle数据库。使用格式foo_seq第 14 页*b.identity : 采用数据库自增涨机制生成。适用于MySQL,SQLServer数据库。*c.native : 根据方言自动选择identity, sequence等生成方式。*d.increment : 首先获取最大主键值,然后加1,再执行插入操作。适用于各种数据库。先执行select max(id) from t_foo;再执行insert into.e.assigned : Hibernate忽略主键生成,不负责管理。需要程序员在程序中指定主键值f.其他uuid:采用UUID算
32、法生成一个字符串主键值hilo:采用高地位算法生成一个数值主键值3.Hibernate框架基本特性1)一级缓存(Session级别缓存,默认开启)a.每次创建一个Session对象,会为这个Session对象提供一个缓存区,用于缓存该Session查询出来的单个对象。当使用该Session再次查询同一个对象时,从缓存取出,避免对数据库的查询。*b.一级缓存区管理的方法:session.evict(obj):将obj从一级缓存移除session.clear():清除一级缓存所有对象c.一级缓存好处当利用同一个Session对象多次查询同一个数据对象时,仅第一次从数据库查询,后续几次从缓存获取。-
33、Session session =HibernateUtil.getSession();Transaction tx =session.beginTransaction();for(int i=1;i拦截器前期(无)ActionDAOResultJSP(通过标签和EL获取对象数据)拦截器后期(关闭Session)将HTML结果响应1.Hibernate关系映射的作用利用关联映射,Hibernate可以帮着查询加载对象相关的数据,可以简化查询代码。此外还可以基于关系进行增删改操作。2.一对多关系映射a.确定两个对象哪个是1方和n方第 17 页b.需求:由1方对象查询n方记录,可以采用一对多关系映
34、射c.首先在1方实体类中添加集合属性Setd.然后再1方的hbm.xml中定义一对多关系映射的描述e.使用时,通过1方对象.关系属性获取n方数据3.多对一关系映射a.需要由n方对象查询1方对象信息b.在n方实体类中添加属性,属性类为1方类型c.在n方hbm.xml文件中,添加属性的映射描述信息d.清除n方实体类中外键字段描述信息和属性e.使用时,通过n方对象.关联属性获取相关的1方记录信息4.关联操作注意事项*1)关联查询默认情况下,关联属性数据加载采用了延迟加载机制,当调用属性getter方法才出发查询。在使用时,如果需要将关联属性和主对象一起加载,可以通过以下方法改变加载机制。a.在hbm
35、.xml中为该属性添加lazy=“false“(关联属性数据在主对象加载时加载)为该属性追加fetch=“join“(指定关联属性加载方式,可以指定为select,join,subselect值)b.写一个HQL,采用join fetch关键字加载关联属性。(注意:a方案会影响所有Service对象操作,不推荐,如果需要一起加载关联属性,建议采用b方案)*2)级联添加对主对象做添加操作时,关联属性的数据也做相应的添加操作。a.需要在hbm.xml的关联属性定义中添加cascade属性,属性值可以为none(默认), all,delete,save-update等。b.在执行session.sa
36、ve()之前,将关联数据对象添加到关联属性中。*3)级联删除对主对象做删除操作时,关联属性的数据也做相应的删除操作。a.需要在hbm.xml中的关联属性开启级联删除操作。b.在执行session.delete(obj)操作时,删除的obj对象是利用session查询出来的。注意不要使用new方式,因为不具有关联数据第 18 页(级联删除采用n+1个delete清除数据,因此关联数据对象n过多时,不推荐使用,而是采用HQL语句进行删除)/批量清除Service关系表记录delete from Service where account.id=?Query query = session.crea
37、teQuery(hql);/.设置参数query.executeUpdate();4)inverse属性inverse可以控制关系字段值维护的操作由哪一方负责。默认情况下由具有关系的对象双方负责。一般在1方关联的集合属性中使用inverse=true,意思要1方放弃关系维护操作,当程序对1对象做级联操作时,不会再出现update维护关系字段的语句。(提示:使用一对多时,一般都会加上inverse=true)1.如何利用MyEclipse根据数据库生成实体类和映射描述文件1)在DB Browser中建立一个与数据库的连接2)新建一个Web Project工程3)为工程添加Hibernate开发框
38、架(导入包,添加主配置及其参数设置)选中工程右键MyEclipseAdd Hibernate Capabilities.4)按MyEclipse向导添加Hibernate框架开发包,添加主配置文件,设置连接参数,创建一个HibernateUtil工具类 .-生成实体类和hbm.xml-5)进入 DB Browser,选中要操作的数据表,右键Hibernate ReverseEngineering.按向导生成实体类和hbm.xml.6)向导界面1:选择存放实体类和hbm文件的工程和package。选择要生成文件:hbm.xml,pojo,dao7)向导界面2: 将Type Mapping选中为H
39、ibernate Types8)向导界面3:点击Finish完成2.多对多关系映射多对多关系在数据库中需要3张表表示。例如AdminInfoAdmin_Role第 19 页3.继承关系映射a.父类一张表,每个子类一个表,主键对等b.可以采用进行继承关系映射,具体如下-在子类追加extends 父类-在子类hbm.xml中定义/子类中属性的property映射#示例表Oracle#CREATE TABLE PRODUCT(ID NUMBER(5) CONSTRAINT PRODUCT_ID_PK PRIMARY KEY,NAME VARCHAR2(20),PRICE NUMBER(15,2),P
40、RODUCT_PIC VARCHAR2(100);CREATE SEQUENCE product_seq;CREATE TABLE BOOK(ID NUMBER(5) CONSTRAINT BOOK_ID_PK PRIMARY KEY,AUTHOR VARCHAR2(20),PUBLISHING VARCHAR2(50),WORD_NUMBER VARCHAR2(20),TOTAL_PAGE VARCHAR2(20);CREATE TABLE CAR(ID NUMBER(5) CONSTRAINT CAR_ID_PK PRIMARY KEY,BRAND VARCHAR2(20),TYPE VA
41、RCHAR2(1),第 20 页COLOR VARCHAR2(50),DISPLACEMENT VARCHAR2(20);#2)Hibernate查询*a.HQL查询Hibernate Query LanguageHQL与SQL语句结构相似,SQL语句是面向数据表和字段进行查询,而HQL语句是面向Hibernate映射过来的对象和属性进行查询,因此HQL被称为是一种面向对象查询语言HQL和SQL共同点:-都支持select,from,where,order by,having,group by等子句。-都支持运算符表达式,例如+,-,*,/,select new Service(id,osUs
42、ername) from Service返回List-在hbm.xml中定义hql:Query query = session.getNamedQuery(“标识符“)-分页查询用法:query.setFirstResult(抓取起点从0开始计算)query.setMaxResult(抓取最大数量);List list = query.list();b.Criteria查询(QBC)了解,参考示例和Hibernate帮助文档c.Native SQL查询了解,参考示例和Hibernate帮助文档第 21 页1.Hibernate高级特性1)二级缓存技术SessionFactory级别的缓存,受S
43、essionFactory管理,可以被不同Session访问和操作。默认是关闭。一般在使用时需要利用SessionFactory.evict()等方法显式的管理该缓存a.什么情况可以考虑使用二级缓存-该对象被多个不同用户频繁使用-该对象更新操作不频繁b.如何使用二级缓存-添加ehcache.jar开发包和src/ehcache.xml配置-在hibernate.cfg.xml中开启二级缓存,指定采用哪种二级缓存组件-需要缓存哪个对象,就在hbm.xml中添加元素配置c.二级缓存管理sessionFactory.evict方法2)查询缓存技术一级和二级缓存只能缓存单个对象,查询缓存可以缓存一个s
44、elect查询结果。a.查询缓存的使用-要对查询的目标对象开启二级缓存-在hibernate.cfg.xml中开启查询缓存设置-在执行query.list()查询之前,调用query.setCacheable(true);b.适合使用查询缓存的情况-不同用户都执行相同的SQL查询和相同结果-查询结果集不发生改变注意:在使用关联映射时,关系属性数据默认不参与缓存,即使访问对象在缓存中存在,当访问该对象的关联属性数据时,还得去数据库查询。如果需要缓存关联属性数据,需要对关联属性和hbm.xml都设置元素*3)悲观锁和乐观锁当出现多个用户同时执行更新等操作时,会出现事务交叉更新操作的冲突,会破坏业务
45、和数据的完整性。可以使用悲观锁和乐观锁解决这类问题。a.悲观锁机制:在进行数据查询时追加一个锁机制,进行业务操作,此时其他用户不能进行增删改操作,在事务结束时会自动将锁释放,其他用户可以继续执行此类操作。悲观锁特点:将用户操作一个一个处理,可以解决更新并发问题,缺点是处理效率比较低。Hibernate悲观锁机制一般是借助于数据库锁机制。session.load(Train.class,1,);session.get(Train.class,1);第 22 页b.乐观锁机制:多个不同用户都可以同时对数据库记录进行查看和更新操作,但是最先commit提交的用户会执行成功,后续用户会以异常形式提示失
46、败。乐观锁是借助于一个版本字段进行控制,当并发操作中一个用户成功提交了,版本字段值会自动加1,后续提交的对象版本信息小于数据库版本字段值会被hibernate阻止掉。乐观锁特点:允许多个用户同时操作,处理效率相对较高。乐观所使用步骤:-将原有数据表追加一列版本字段,初始值0-在实体类中添加版本属性-在映射描述文件中采用元素定义版本属性和版本字段的映射-当发生多个事务并行交叉执行时,第一个提交的成功,后续提交的会抛出异常。可以异常捕获给用户一个友善的提示。=示例表=create table train(t_id number primary key,t_value number,t_version number);insert into train values (1,100,0);Spi