SSH学习笔记
Struts2登录模块处理流程:
- 浏览器发送请求http://localhost/appname/login.action,到web应用服务器;
- 容器接收到该请求,根据web.xml的配置,服务器将请求转到FilterDispatcher进行处理,进入Struts2的流程中;
- 框架在struts.xml配置文件中查找名为login的action对应的类;
- 框架初始化该Action,执行其中的set***方法填充数据,再执行excute方法;
- Execute方法执行后并返回字符串“success”或者“fail”,分别表示执行成功或失败;
- 框架检查配置以查看当返回的字符串所对应的页面。(structs.xml)
每一个action对象都服务一个请求,这和Servlet的原理是不一样的。
在action中:
Public class LoginAction{
Private LoginBean loginUser;
Public LoginBean getLoginUser(){
Return loginUser;
}
public LoginBean setLoginUser(){this.loginUser=loginUser;}
public String execute(){
if(loginUser.getAccount().equals(loginUser.getPassword())){
return “success”;
return “fail”;}
}
}
在Action类中访问servlet中对象的方式:通过ServletActionContext中定义的静态方法来获得servlet中的对象。
HttpServletRequest request=ServletActionContext.getRequest();
HttpServletResponse response=ServletActionContext.getResponse();
HttpSession session=request.getSession();
Action类中提供多个方法来处理多个不同类型的请求:
Public class LoginRegisterAction{
Public String login(){…}
Public String register(){…}
Public String execute(){…}
},此时,action在structs.xml的配置应该这么写:
|
配置方式 |
访问方式 |
方式一 |
声明action的名字和类型<action name="LoginRegisterAction" class="...LoginRegisterAction"> </action> |
为每一个处理请求的方法定义一个Action,如<action name=”login” class=”..LoginRegisterAction method=”login””>..</action> 如<action name=”register” class=”..LoginRegisterAction method=”register””>..</action> |
方式二 |
http://localhost:8080/struts2/ 以actionName!methodName.action形式访问 |
以actionName.action形式访问,如 http://localhost:8080/struts2/login.action
|
Structs.xml示范:
<!--struts.xml-->
<?xml version="1.0" encoding="UTF-8" ?>
<struts>
<package name="strutsBean"
extends="struts-default" namespace="/">
<action name="login" class="Actions.LoginAction">
<result name="success">/loginSuccess.jsp</result>
<result name="fail">/loginFail.jsp</result>
</action>
</package>
</struts>
Package中:name表示包名,extends用于设置对其他包的基础,通常继承一个structs2的内置包“structs-default”,可以多重继承。Namespace是命名空间,用于解决大型项目中的重名问题,不同命名空间下可以有相同的action名字。
Hibernate学习:
对象和关系映射:
在ORM中,一个PO对象,一般表示数据库中一条记录,只是对这个记录的操作可以简化成对这个Bean对象的操作,操作之后数据库中的记录相应变化。框架根据配置文件读取表格中各个列和Bean对象中各个属性的映射。框架提供一些能够对这些对象进行操作的函数。
Hibernate是一个面向java环境的数据库映射工具,管理java类到数据库的映射。把对对象的操作自动转化为对数据库的SQL语句操作。
原理:
对于一个数据库操作,其执行步骤为:
- 框架API通过读取Hibernate配置文件,连接到数据库
- 当对PO进行操作时,框架API通过Hibernate映射文件,来决定操作的表名和列名。
- 框架API执行SQL语句
利用Hibernate编程,步骤:
- 编写Hibernate配置文件,连接到数据库;
- 编写PO(属性的数据类型都选用了对象类型,而非基本数据类型,原因是属性和字段对应,只有对象才能表示空值的概念);
- 编写Hibernate映射文件,将PO和表映射(名字不一定相同,但基本上都命名为相同,并且放在同一个包下面),PO中的属性和表中的列映射;
- 编写DAO,使用Hibernate进行数据库操作
Hibernate实例:
package po;
public class Student {
private String stuno;
private String stuname;
private String stusex;
public String getStuno() { return stuno; }
public void setStuno(String stuno) { this.stuno = stuno;}
/**其它get, set方法**/
}
Student.hbm.xml:
<hibernate-mapping>
<class name="po.Student" table="T_STUDENT">
<id name="stuno" column="STUNO">
<generator class="assigned" />
</id>
<property name="stuname" column="STUNAME" />
<property name="stusex" column="STUSEX" />
</class>
</hibernate-mapping>
- <class name="类名" table="表名">:类和表对应
- <id name="属性" column="列名">:填写主键,即使表内没有主键,配置文件中也要配置一个唯一标识
- <generator class="assigned"/>:主键的生成策略,assigned 表示由用户赋值
- <property name="属性" column="列名"/>:将属性和列对应起来
注册映射文件:
在hibernate.cfg.xml中注册:
<hibernate-configuration>
<session-factory>
<property name="connection.username">root</property>
<property name="connection.password"></property>
<property name="connection.driver_class">
com.mysql.jdbc.Driver</property>
……
<mapping resource="po/Student.hbm.xml" />
</session-factory>
</hibernate-configuration>
利用Hibernate进行数据库操作:
利用Hibernate基本API载入并建立连接:
- 读取Hibernate配置文件(Hibernate.cfg.xml):Configuration conf=new Configuration.configure();
- 生成SessionFactory,对session进行管理;SessionFactory sf = conf.buildSessionFactory();
- 利用SessionFactory打开Session Session=sf.openSession();
添加:session.saveOrUpdate(Object);
删除:session.delete(Object);
修改:Session.saveOrUpdate(Object);
查询:Object Session.get(PO对应的类,主键);如Student stu=(Student)session.get(Student.class,”0002”);
RgusersDAO dao = new RgusersDAO();// 实例化 DAO
Transaction tran = dao.getSession().beginTransaction();// 打开事务
Rgusers bean = new Rgusers();// 生成普通 Java 类
bean.setUsername("赵六");// 设置属性
bean.setPassword("zhao1234");
bean.setUserId(4);
dao.save(bean);// 插入数据
tran.commit();// 提交事务
dao.getSession().close();
深入学习Hibernate:
- Configuration:(可以理解成与hibernate.cfg.xml对应)
一个Configuration实例代表了一个应用程序中Java类型到SQL数据库映射的完整集合;
用于构建SessionFactory;
可以使用Configuration类的configure方法来读取hibernate.cfg.xml文件,并负责管理配置信息;
Configuration conf = new Configuration().configure();
SessionFactory sf = conf.buildSessionFactory();
其他方法:addResourc(String path):指定一个hbm文件路径,动态添加映射文件;
addClass(class persistentClass):指定PO类,载入该类对应配置的映射文件;
conf.addResource(Student.hbm.xml);
conf.addClass(pdao.Student.class);
- SessionFactory:
SessionFactory由Configuration建立;
应用程序从Sessionfactory中获得Session实例;
通常情况下,一个数据库只有唯一一个SessionFactory,可在应用初始化时被创建
SessionFactory sf = conf.buildSessionFactory();Hibernate允许应用程序使用多个数据库,并相应的创建多个sessionFactory实例。
Sessionfactory非常耗内存!它缓存了SQL语句和映射元数据。
- Session:
代表与数据库之间的一次操作,需要进行数据访问时,从连接池获得一个JDBC连接;
通过SessionFactory打开,在所有工作完成后,需要关闭;
HibernateSessionFactory把生产Session的过程进行优化,比较高效:
HibernateSessionFactory.getSession();
HibernateSessionFactory.closeSession();
主键生成策略:
assigned:用户定义
increment:自动递增(long,integer,short)
uuid.hex:利用uuid算法
identity:由数据库根据identity生成主键
native:系统自动选择相应算法生成主键
sequence:由数据库根据序列生成主键
hilo:根据Hibernate的hilo生成主键
复合主键:
改写po类:若表中有多个列组成主键,则为这几个列封装成一个类作为主键,并增加setter和getter方法,编写PO类,将主键对象作为属性之一。
Public class StudentPK implements java.io.Serializable{
Private String stuno;
Private String stuname;
Public String getStuno(){return stuno;}
Public string getStuname(){return stuname;}
Public void setStuno(){this.stuno=stuno;}
Public void setStuname(this.stuname=stuname;)
}
Public class Student{
Private StudentPK spk;
Private String stusex;
Public StudentPK getSpk(){
Return spk;
}
Public void setStudentPK(){
this.spk=spk;
}
Public String getStusex(){
Return stusex;
}
Public void setStusex(){
this.sex=sex;
}
}
在映射文件中进行配置:将主键类中的每个属性和表中的列对应,并制定复合主键的类型
<hibernate-mapping>
<class name="po.Student" table="T_STUDENT">
<composite-id name="spk" class="po.StudentPK">
<key-property name="stuno"
column="STUNO"></key-property>
<key-property name="stuname"
column="STUNAME"></key-property>
</composite-id>
<property name="stusex" column="STUSEX"/>
</class>
</hibernate-mapping>
使用复合主键操作数据库:
查询主键为【001 张三】的学生的性别
Session session = util.HibernateSessionFactory.getSession();
StudentPK spk = new StudentPK();
spk.setStuno(“001”);
spk.setStuname(“张三”);
Student stu = (Student)session.get(Student.class,spk);
If(stu!=null){
System.out.println(stu.getStusex());
}
util.HibernateSessionFactory.closeSession();
HQL查询步骤:
- Query Session.createQuery(String queryString),该方法为HQL查询语句生成一个Query类的对象。
- 返回的Query中,有list()方法,返回一个List对象,通过遍历这个List对象得到查询的内容
查询语句:from 类名 as 对象名[where属性条件]
Session session=util.HibernateSessionFactory.getSession();
String hql=”from Student where stusex=’女’”;
Query query=session.createQuery(hql);
List list=query.list();
for(int i=0;i<list.size();i++){
Student stu=(Student)list.get(i);
System.out.println(stu.getStuname());
}
Util.HibernateSessionFactory.closeSession();
其他hql写法:
Select 属性 from 类名 as对象名[where 属性条件],
select stuno,stuname from Student where stusex=’女’ ;这样的话,查询之后得到的结果集就要用Object来表示了。
For(int i=0;i<list.size();i++){
Object[] objs=(Object[])list.get(i);
System.out.println(objs[0]+””+objs[1]);
}
带参数的hql写法:
String sex=”female”;
String hql=”select stuno,stuname from Student where stusex=:sex”;
Query query=session.createQuery(hql);
query.setString(“sex”,sex);
关联关系映射:
单向关联:多对一
Person和Country
Public class Person{private Integer id;private String name; private Country country;}
Public Class Country{private Integer id; private String name;}
Person表 |
ID |
Name |
CountryID |
Country表 |
ID |
name |
|
Person.hbm.xml:
<hibernate-mapping>
<class name=”po.Person” table=”person” catalog=”test”>
<id name=”id” column=”ID”><generator class=”native” /></id>
<property name=”name” column=”Name”/>
<many-to-one name=”country” column=”CountryID” class=”po.Country” cascade=”all”/>
</class>
</hibernate-mapping>
Country.hbm.xml:
<hibernate-mapping>
<class name=”po.Country” table=”country” catalog=”test”>
<id name=”id” column=”ID”><generator class=”native” /></id>
<property name=”name” column=”name”/>
</class>
</hibernate-mapping>
单向关联一对一:
Person与PersonAddress
Public class Person{private Integer id;private String name; private PersonAddress address;}
Public class PersonAddress{private Integer id;private String city; private String street;}
Person表 |
ID |
Name |
AddressID |
PersonAddress表 |
ID |
city |
street |
Person.hbm.xml:
<hibernate-mapping>
<class name=”po.Person” table=”person” catalog=”test”>
<id name=”id” column=”ID”><generator class=”native”/></id>
<property name=”name” column=”Name”/>
<many-to-one name=”address” column=”AddressID” class=”po.Country” unique=”true”></many-to-one>
</class>
</hibernate-mapping>
PersonAddress.hbm.xml:
<hibernate-mapping>
<class name=”po.PersonAddress” table=”personaddress” catalog=”test”>
<id name=”id” column=”ID”><generator class=”native” /></id>
<property name=”name” column=”name”/>
<property name=”street” column=”street”/>
</class>
</hibernate-mapping>
单向关联一对多:
Person与Phone
Public class Person{private Integer id;private String name; private Set phones=new HashSet(0);}
Public class Phone{private Integer id;private String number; }
Person表 |
ID |
Name |
|
Phone表 |
ID |
number |
personid |
Person.hbm.xml
<hibernate-mapping>
<class name=”po.Person” table=”person” catalog=”test”>
<id name=”id” column=”ID”><generator class=”native”/></id>
<property name=”name” column=”Name”/>
<set name=”phones” cascade=”all” lazy=”false”>
<key column=”personid”/>
<one-to-many class=”po.Phone”/>
</set>
</class>
<hibernate-mapping>
Phone.hbm.xml:
<hibernate-mapping>
<class name=”po.Phone” table=”phone” catalog=”test”>
<id name=”id” column=”ID”><generator class=”native” /></id>
<property name=”number” column=”number”/>
</class>
</hibernate-mapping>
单向关联多对多:
Person和Flight:
Public class Person{private Integer id;private String name; private Set flights=new HashSet(0);}
Public class Flight{private Integer id;private String name; }
Person表 |
ID |
Name |
|
Flight表 |
ID |
name |
|
Person-flight表 |
personID |
flightID |
|
Person.hbm.xml
<hibernate-mapping>
<class name=”po.Person” table=”person” catalog=”test”>
<id name=”id” column=”ID”><generator class=”native”/></id>
<property name=”name” column=”Name”/>
<set name=”flights” table=”person_flight”>
<key column=”personID”/>
<many-to-many column=”flightID” class=”po.Flight”/>
</set>
</class>
<hibernate-mapping>
Flight.hbm.xml:
<hibernate-mapping>
<class name=”po.Flight” table=”Flight” catalog=”test”>
<id name=”id” column=”ID”><generator class=”native” /></id>
<property name=”name” column=”name”/>
</class>
</hibernate-mapping>
双向关联一对多/多对一:
Person和Department:
Public class Person{private Integer id;private
String name; private Department department;}
Public class Department{private Integer id;private String number; private Set staffs=new HashSet(0);}
Person表 |
ID |
Name |
departmentID |
Department表 |
ID |
name |
|
Person.hbm.xml:
<hibernate-mapping>
<class name=”po.Person” table=”person” catalog=”test”>
<id name=”id” column=”ID”><generator class=”native”/></id>
<property name=”name” column=”Name”/>
<many-to-one name=”department” class=”po.Department” column=”departmentID”></many-to-one>
</class>
<hibernate-mapping>
Department.hbm.xml:
<hibernate-mapping>
<class name=”po.Department” table=”Department” catalog=”test”>
<id name=”id” column=”ID”><generator class=”native”/></id>
<property name=”name” column=”Name”/>
<set name=”staffs” >
<key column=”departmentID”/><one-to-many class=”po.Person”/>
</set>
</class>
<hibernate-mapping>
双向关联一对一:
Person与IDCard:
Public class Person{private Integer id;private String name; private IDCard cardID;}
Public class IDCard{private Integer id;private String memo; private Person person;}
Person表 |
ID |
Name |
|
IDCard表 |
ID |
name |
personID |
Person.hbm.xml:
<hibernate-mapping>
<class name=”po.Person” table=”person” catalog=”test”>
<id name=”id” column=”ID”><generator class=”native”/></id>
<property name=”name” column=”Name”/>
<one-to-one name=”cardID” class=”po.IDCard” cascade=”all”/>
</class>
<hibernate-mapping>
IDCard.hbm.xml:
<hibernate-mapping>
<class name=”po.IDCard” table=”idcard” catalog=”test”>
<id name=”id” column=”ID”><generator class=”native”/></id>
<property name=”memo” column=”memo”/>
<many-to-one name=”person”class=”po.Person” unique=”true”><column name=”personid”/>
</many-to-one>
</class>
<hibernate-mapping>
双向关联多对多:
Student和Teacher:
Public class Student{private Integer id;private
String name; private Set teachers= new HashSet(0);}
Public class Teacher{private Integer id;private String name; private Set students=new HashSet(0);}
Person表 |
ID |
Name |
|
Teacher表 |
ID |
Name |
|
Student_teacher |
studentID |
taecherID |
|
Person.hbm.xml:
<hibernate-mapping>
<class name="po.Student" table="student" catalog="test">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="native"></generator>
</id>
<property name="name" type="java.lang.String">
<column name="name" length="45" not-null="true" />
</property>
<set name="teachers" table="teacher_student">
<key column="studentid"/>
<many-to-many column="teacherid" class="po.Teacher"/>
</set>
</class>
</hibernate-mapping>
Teacher.hbm.xml:
<hibernate-mapping>
<class name="po.Teacher" table="teacher" catalog="test">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="native"></generator>
</id>
<property name="name" type="java.lang.String">
<column name="Name" length="45" not-null="true" />
</property>
<set name="students" table="teacher_student">
<key column="teacherid"/>
<many-to-many column="studentid" class="po.Student"/>
</set>
</class>
</hibernate-mapping>
Spring:
Spring的核心是个轻量级(Lightweight)容器(Container),实现了IoC(Inversion of Control)模式的容器,基于此核心容器所构建的应用程序,可以达到组件的松散耦合,使得整个应用程序可以在架构上与维护上都能得到相当程度的简化
Spring IoC:依赖倒转原则,其核心是将具体类之间的依赖,转化成抽象类依赖。即类Person应依赖抽象类ICar而不是Car。
Public Person{
...
public void drive(){
Car toyota=new Car(\"TOYOTA\");
toyota.挂档;
toyota.踩油门;
toyota.打方向;
}
}
导致了对象boy需要负责对象toyota的创建,甚至是整个生命周期的管理,耦合度高,不易维护。
若男孩换车,驾驶Audi,则要修改代码
实例:
applicationContext.xml为spring bean配置文件
Action接口:定义了一个execute方法,不同的Action实现提供了各自的execute方法
public interface Action {
public String execute(String str);
}
Action接口的两个实现:UpperAction
Public class UpperAction implemets Action{
Private String message;
Public String getMessage(){return message;}
Public void setMessage(String message){this.message=message;}
Public String execute(String str){return (getMessage()+str).toUpperCase();}
}
Spring配置文件applicationContext.xml:
<beans>
<description>Spring Quick Start</description>
<bean id="TheAction"
class="com.UpperAction">
<property name="message">
<value>HELLO</value>
</property>
</bean>
</beans>
测试代码:
Public void testQuickStart(){
ApplicationContext ctx = new ClassPathXMLApplicationContext(“applicationContext.xml”);
Action action=(Action)ctx.getBean(“TheAction”);
System.out.println(action.execute(“Rod Johnson”));
}
输出结果:HELLO Rod Johnson
总结:
- 除测试代码之外所有程序代码中,并没有出现Spring中的任何组件
- UpperAction的Message属性由Spring通过配置文件动态设置
- 客户代码(这里的测试代码面向接口编程,无需知道类的具体名称)
依赖注入:由容器动态地将某种依赖关系注入到组件之中
- 接口注入
- 设值注入
- 构造方法注入
接口注入:将调用者与实现者分离
Public class ClassA{
Private InterfaceB clzB;
Public doSomething(){
Object obj=Class.forName(Config.BImplementation).newInstance();
clzB=(InterfaceB)obj;
clzB.doIt();
}
}
设值注入:
Public class ClassA{
Private InterfaceB clzB;
Public void setClzB(InterfaceB clzB){this.clzB=clzB;}
Public InterfaceB getInterfaceB(){return clzB;}
}
举例子:
Public Person{
Private ICar car;
Public Person(){}
Public void setCar(Icar onecar){car=onecar;}
Public ICar getCar(){return car;}
Public void drive(){car.挂档;car.踩油门;,,,}
}
调用:
Toyota Toyota = new Toyato();
Person boy = new Person();
Boy.setCar(toyota);
Boy.drive();
Public interface ICar{void 挂档();void 踩油门();}
Public Class Toyato implements ICar{public void 挂档();public void 踩油门();}
Public Class Audi implements ICar{public void 挂档();public void 踩油门();}
Public class Factory{
Public final String TOYOTA = “toyota”;
Public final String Audi = “audi”;
Public ICar getCar(String craname){
If(carnema.equals(TOYOTA)) return new Toyota();
Else if(carname.equals(AUDI)) return new Audi();
Else throws new IllegalAroumentException(“车名错误”);
}
}
Public class Test{
Public static void main(String args[]){
Person boy = new Person();
ICar car=new Factory().getCar(Factory.TOYOTA);
Boy.setCar(car);
Boy.drive();
ICar car=new Factory().getCar(Factory.Audi);
Boy.setCar(car);
Boy.setCar(car);
Boy.drive();
}
}
<!bean.xml>
<beans>
<bean id=”Toyota” class=”***.Toyota”/>
<bean id=”Audi” class=”***.Audi”/>
</beans>
Public class Test{
Public static void main(String args[]){
Person boy = new Person();
ApplicationContext ctx=new FIleSysytemXmlAplicationContext(“bean.xml”);
ICar car=(ICar)ctx.getBean(“Toyota”);
Boy.setCar(car);
Boy.drive();
}
构造方法注入:
public class ClassA {
private InterfaceB clzB;
public ClassA(InterfaceB clzB) { this.clzB=clzB }
……
}
v 配置文件的读取方式
- FileSystemXmlApplicationContext
- 配置文件必须位于项目根目录中,即与src平级
- ApplicationContext ctx =
new FileSystemXmlApplicationContext("bean.xml");
- ClassPathXmlApplicationContext
- 配置文件在classpath中,即在src目录下
- 在Web应用程序的文档结构中读取
- XmlWebApplicationContext
SSH整合:
- 导入structs2:
项目右键——myeclipse——add structs capability——structs2.1——/*——Structs2 core Libraries和Structs 2 Spring Libraries(如果后面要添加spring的,这个包一定要导入进去,否则会报一个错误:java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener。如果后面不要添加spring的,这个包不要导入)。——finished
- 导入spring:
项目右键——myeclipse——add spring capability——Spring 3.0 core Libraries和Spring3.0 web Libraries——enable AOP Builder,applicationContext.xml放在web-inf目录下——finished。
在web.xml中添加:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>