一、MVC分层概述
1、请求执行过程
【视图层:jsp】--->【控制层:(struts:action)xxxAction类】
--->【业务层:xxxService】--->【dao层:(hibernate):xxxDao】
2、各层对应关系概述
- 服务器端(操作数据的)
(1)控制层:action---调用业务层
(2)业务层:service---调用dao层处理类,并处理dao层的结果
- 定义service接口
- 定义service实现类
(3)dao层---具体操作数据库
- 定义dao接口
- 定义dao实现类
- 客户端(用户发出请求)
(4)视图层---用户操作的界面
二、xml方式实现SSH
1、封装实体类【类表关系映射】
(1)对应数据库表【类名=表名,字段名=表字段名】
setget封装全部,tostring重写,构造函数(除去id)
(2)创建类的xml映射文件(hibernate)
(3)到applicationContext.xml spring配置文件中向spring容器注入该xml文件
[注]:与数据库无表的对应联系的实体类,不需要生成实体类的映射文件,映射文件是实体类与数据库表的映射
//1、实体类:商品和类别是多对一关系
public class Product {
//类属性
private int id;
private String name;
//tid外键不用封装,1对多,将1的对象声明在多的类中
private Type type;
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
//set get封装属性
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//无参有参构造函数、toString略
}
public class Type {
private int id;
private String name;
//在一的里面声明一个多类型的集合(一个type对应多个product)
private Set<Product> pis=new HashSet<>(0);
//set get封装集合
public Set<Product> getPis() {
return pis;
}
public void setPis(Set<Product> pis) {
this.pis = pis;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//2、hibernate关系映射文件 xml
//【Product.hbm.xml】
<hibernate-mapping>
<!-- 1.table为数据库中对应的表名 -->
<class name="com.sqf.entity.Product" table="product">
<!-- 2.所有colum的值改成同name值一样的小写 -->
<id name="id" type="int">
<column name="id" />
<!-- 3.这里改成native -->
<generator class="native" />
</id>
<property name="name" type="java.lang.String">
<column name="name" />
</property>
<property name="brand" type="java.lang.String">
<column name="brand" />
</property>
<property name="num" type="int">
<column name="num" />
</property>
<!-- 3.配置映射关系:name值为在本类中声明的type对象,column的name为数据库中的外键tid -->
<many-to-one name="type" class="com.sqf.entity.Type" fetch="select" lazy="false">
<column name="tid" />
</many-to-one>
</class>
</hibernate-mapping>
//【Type.hbm.xml】
<hibernate-mapping>
<class name="com.sqf.entity.Type" table="type">
<id name="id" type="int">
<column name="id" />
<generator class="native" />
</id>
<property name="name" type="java.lang.String">
<column name="name" />
</property>
<!-- 配置映射关系:name为在本类中声明的集合对象名,inverse为true表示放弃维护,column的name仍为外键tid
cascade:产生级联操作
-->
<set name="pis" table="product" inverse="true" cascade="all">
<key>
<column name="tid" />
</key>
<one-to-many class="com.sqf.entity.Product" />
</set>
</class>
</hibernate-mapping>
//3、配置Spring配置文件
//【applicationContext.xml】
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<!-- 文件中连接数据库,配置hibernate自身属性略 -->
<!-- 类映射文件写在value中,这里添加的类对应的映射文件路径,而注解中注入的是类的路径 -->
<property name="mappingResources">
<list>
<value>com/sqf/entity/Product.hbm.xml</value>
<value>com/sqf/entity/Type.hbm.xml</value>
</list>
</property>
</bean>
2、dao层【数据库数据具体操作层,处理具体值】
(1)定义dao接口(TypeDao),只声明函数名
(2)定义到接口实现类(TypeDaoImple),继承dao接口并实现其中函数
首先声明sessionFectory对象,并set封装;然后完成实现类
(3)到applicationContext.xml中用bean节点将dao层注入到spring架构中
- id值为dao层在spring架构中声明的dao层对象名;
- class:输入TypeDaoImple实现类名,提示得路径;
- 在bean节点内部利用property节点将daoimpl中声明的sessionFectory对象赋值
3、service层【调用dao层函数的层,处理dao层操作结果】
(1)定义service接口(TypeService),声明同dao接口中对应的函数名
(2)定义service实现类(TypeServiceImpl),继承service接口,并实现其中的类
- 首先在实现类中声明出dao层在spring架构中声明的对象(即applicationContext.xml中dao声明的bean节点的id值),
- set get封装,该dao层对象用来在service实现类中调用dao层的函数
(3)到applicationContext.xml中用bean节点将service层注入到spring架构(类似于dao层注入),并在bean节点内部利用property节点给service实现类中声明的dao层对象赋值
[注] : id值为service层在spring架构中声明的service层对象名
//dao、service层功能代码略,只展示如何将各层对象配置到Spring容器中统一管理
//【applicationContext.xml】spring配置文件
<!--(1)dao层 -->
<bean id="productDao" class="com.sqf.dao.ProductDaoImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- (2)service层 -->
<bean id="productService" class="com.sqf.service.ProductServiceImpl">
<property name="productDao" ref="productDao"></property>
</bean>
<!--(3)action层 -->
<bean id="productAction" class="com.sqf.action.ProductAction">
<property name="productService" ref="productService"></property>
</bean>
4、action层【调用service层函数的层】
(1)获得实体类服务对象,即声明service层在spring架构中声明的对象(注入service层对应的bean的id值),set封装
(2)写action类,数据库的操作通过声明的service对象来调用其函数实现
(3)到applicationContext.xml中用bean节点将action层注入到Spring架构中,并利用property节点给action层中声明的service层对象赋值
[注]: bean的id值作为action层声明的对象
(4)配置strut.xml文件,class可以直接调用该对象(id值),功能同写该action类的路径
[注]:strut.xml文件的作用:连接action层和前端请求
//【action类】--以一个功能函数为例
//1.声明为action层通过接口类获取session对象,通过ModelDriven获取前端参数
public class ProductAction implements SessionAware,ModelDriven<Product>{
//2.通过ModelDriven获得前端对象
Product product=new Product();
@Override
public Product getModel() {
return this.product;
}
//3.获得session
Map<String, Object> session;
@Override
public void setSession(Map<String, Object> arg0) {
session=arg0;
}
//4.获得service层用bean中声明的对象,并set封装 通过set方式注入对象
ProductService productService;
public void setProductService(ProductService productService) {
this.productService = productService;
}
//5.写处理函数
/**************添加*************/
public String add(){
int i=productService.add(product);
System.out.println(i);
if(i!=0){
return "success";
}else{return "error";}
}
}
//【struts.xml】连接前后端
<struts>
<constant name="struts.i18n.encoding" value="utf-8"></constant>
<!-- 定义一个名称为digital的包,继承struts 2的默认包,指定命名空间为"/" -->
<package name="digital" namespace="/" extends="struts-default">
<!-- 【注】为类中的方法配置映射 :name:jsp中action请求名
class:为applicationcontexxml文件中action定义的id(或填action类的路径,method为处理函数名
result相当于注解中的result配置,name为处理函数返回的字符串-->
<!-- 添加函数 -->
<action name="add" class="productAction" method="add">
<result name="error">add.jsp</result>
<result name="success" type="redirect">getAll</result>
</action>
</package>
</struts>
【注】三种前后端传参方式
- 超链接传参:在action类中set get封装jsp中传入的参数名【两个要一致】
<a herf=请求名?参数名=值>
- jsp的name属性传参:action中:声明该类的一个对象ui并setget该对象;jsp中:
<input name=ui.password>
- model driven传参:action类中直接继承modelDriven类即可;jsp中name属性值ui去掉,
<input name=类中对应的属性>
<input name=password>
三、注解方式实现SSH
1、entity实体类层
【省掉类的xml配置文件】
需要的注解:
- 类前:@entity---标识为实体类
- @table(name=对应表名,catalog=数据库名)---标识实体类和哪个数据库中的哪个表映射
- 主键id前:@id---标识id
- @Generatevalue(strategy=GenerationType.identity)---主键的生成策略:自动递增,数据库中主键一定要设置成自动递增,否则出错
- @column(name=id) ---属性名和列名映射
- 其他非id属性:@column(name=属性名)
- 有关联关系的(如与type类有一对多关系):
- Type type;---声明一个与之联系的类对象
@ManyToOne(fetch=fechtype.EAGER)---相当于lasy=false,不延迟; @JoinColumn(name="tid")---name是数据库中该product类的对应type外键tid,对应数据库中字段
2、DAO层
【省掉springxml文件中注入dao层对象和声明sessionFectory对象后的set】
- 在Dao的接口实现类DaoImpl的前面:
- @Repository(“productinfoDao”)---标识为dao层,并对外声明一个对象productinfoDao,相当于注入spring的xml配置文件中bean声明的id值
- 注解类中声明的对象(类中需要的声明出来的对象,并set注入):
- @Autowired
SessionFectory sessionFectory;【这样只声明,不需要set注入了】
3、service层
【省掉springxml文件中注入service层对象和声明dao层对象的set】
- serviceimpl实现类前:
- @service(“poductinfoservice”)---标识该类为service服务层类并对外声明该层的一个对象poductinfoservice
- 注入dao层对象
- @Autowired
productdao productinfoDao;---dao层对外声明的对象productinfoDao
4、action层
【省掉springxml文件中注入action层对象和strut。xml文件的配置】
- action类前:@Cotroller---标识该类为控制层的类
- 注解需要的service对象
- @Autowired
productservice poductinfoservice---service层注解声明时对外声明的对象
- action的处理函数前: @action(value=“前端传过来的url:后的值”)
【处理过程不变】
最后:out.write(变量)传给前端jsp
(5)jsp前端
【利用easyui】
用javascript传数据和action请求
【注】
1.省写的部分:
- 类的配置文件xxx.hbm.xml不需要了
- strut.xml不需要了
- spring的配置文件applicatContext.xml中不需要利用bean注入各层对象了(只用来连接数据库和配置事务管理器)
2.需要改的部分:
- 实体类xml文件的注入改成注解实体类的位置注入(下面配置文件中第2部分)
- appicationCntext.xml中要将各层对象的注入改成开启注解处理器(下面配置文件中第6部分)
【附:Spring配置文件整体内容】
<!-- 1.配置数据源:c3p0数据库连接池 -->
<!-- id: 自定义取名calss:ComboPooledDataSource打然后提示,-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- 连接数据库:(1)配置连接数据库属性 (2)设置最大最小size【name全用提示得】-->
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/digital?characterEncoding=UTF-8"></property>
<property name="user" value="root"></property>
<property name="password" value=""></property>
<property name="maxPoolSize" value="10"></property>
<property name="minPoolSize" value="5"></property>
</bean>
<!-- 2.spring整合sessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<!-- (1)配置连接数据库:引用上面的 数据源-->
<property name="dataSource" ref="dataSource"></property>
<!-- (2)配置hibernate自己的属性 -->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
<prop key="show_sql">true</prop>
<prop key="format_sql">true</prop>
<prop key="hbm2ddl.auto">update</prop>
</props>
</property>
<!-- (3)管理生成的类映射文件 【生成一个类的映射文件,在此处加一个value,勿忘!!!】-->
<!-- (3)改成配置注解实体类的位置及名称 -->
<property name="annotatedClasses">
<list>
<!-- <value>com.sqf.entity.UserInfo</value>
<value>com.sqf.entity.AdminInfo</value>
<value>com.sqf.entity.ProductInfo</value>
<value>com.sqf.entity.Type</value> -->
<value>com.sqf.entity.Product</value>
<value>com.sqf.entity.Type</value>
</list>
</property>
</bean>
<!-- 3.声明hibernate的事务管理器-->
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 4.定义事务通知 ,需要事务管理器 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 指定事务传播规则 -->
<tx:attributes>
<!-- 对所有方法应用REQUIRED事务规则 -->
<tx:method name="*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<!--5.定义切面,并将事务通知和切面组合(定义哪些方法应用事务规则) -->
<aop:config>
<!-- 对com.digital.service包下的所有类的所有方法都应用事务规则【改execution中包名为自己业务层的包名com.sqf】 -->
<aop:pointcut id="serviceMethods" expression="execution(* com.sqf.service.*.*(..))" />
<!-- 将事务通知和切面组合 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods" />
</aop:config>
<!-- 6.注解设置[没有提示则在namespace中加入context] -->
<!-- (1)开启注解处理器 -->
<!-- <context:annotation-config></context:annotation-config> -->
<!-- (2)开启bean自动扫描 -->
<context:component-scan base-package="com.sqf"></context:component-scan>
<!-- (3)注解事务管理-->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>