一、三大框架介绍
1、sssj --》springmvc spring springjdbc(第一个项目)
2、早期:ssh (struts2 spring hibernate) 用的比较多 ,现在struts2被springmvc替代
3、中小型项目 :s s sdj(第二个项目)
springmvc spring springdatajpa(就是对jpa进行封装) – spring全家桶
4、现在(比较流行):ssm架构(第三个或者第四项目)
springmvc+spring+mybatis
二、搭建Spring+jpa环境
步骤:
一般都是Spring和其他框架进行整合 Spring和JPA
所有配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 扫描spring service注解 repostory注解 开启全注解-->
<context:component-scan base-package="com.cc.ssj"></context:component-scan>
<!--大的步奏:jdbc.properties dataSource EntityManagerFactory Transaction-->
<!-- 1、加载配置jdbc.properties-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 2、配置连接池dataSource 加载jdbc.properties中的信息到程序中来 -->
<!-- destroy-method="close" 当前bean销毁的时候,会先调用close方法,关闭连接 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///db0731ssj"></property>
<property name="username" value="root"></property>
<property name="password" value="cc123456"></property>
</bean>
<!--3、配置EntityManagerFactory-->
<!-- 得到EntityManagerFactory:LocalContainerEntityManagerFactoryBean-->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<!-- 1.注入DataSource -->
<property name="dataSource" ref="dataSource"></property>
<!-- 2.从哪个包去扫描@Entity,domain包 -->
<property name="packagesToScan" value="com.cc.ssj.domain"></property>
<!-- 3.配置JPA的实现 -->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<!--是否显示Sql-->
<property name="showSql" value="true"></property>
<!-- 是否创建表-->
<property name="generateDdl" value="true"></property>
<!--数据库方言-->
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"></property>
</bean>
</property>
</bean>
<!-- 事务管理器-->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<!--注入:EntityManagerFactory 好让我们的事务去管理他-->
<property name="entityManagerFactory" ref="entityManagerFactory"></property>
</bean>
<!-- 开启事务 扫描@Transaction这种注解-->
<tx:annotation-driven/>
</beans>
1、applicationContext.xml 中Bean对象注入的顺序
引用jdbc.properties–>dataSource–>EntityManagerFactory–>-->Transaction
2、配置步奏:
0、配置扫描包:扫描Spring的注解(@Service、@Repostory、等等)
1、配置:jdbc.properties
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///db0731ssj
jdbc.username=root
jdbc.password=cc123456
2、配置连接池dataSource
2.1、加载jdbc.properties中的信息到程序中来
2.2、destroy-method=“close” 当前bean销毁的时候,会先调用close方法,关闭连接
3、配置EntityManagerFactory
3.1、得到:EntityManagerFactory
LocalContainerEntityManagerFactoryBean
3.2、注入 dataSource
3.3、扫描实体类的配置 @Entity—— 扫描domain包
3.4、配置JPA的实现
4、搭建三层结构
1、IProductDao(新增 修改 删除)
2、ProductDaoImpl(新增 修改 删除)
DaoImpl层:使用——>@PersistenceContext 注入EnttiyManager
//开启dao层注解
@Repository
public class ProductDaoImpl implements IProductDao {
//注入EnttiyManager
//@Autowired 不能使用这个注入
//@PersistenceContext通过持久化上下文得到entityManager
@PersistenceContext
private EntityManager entityManager;
……增伤改查方法……}
3、IProductService
4、 ProductServiceImpl
注入的Dao的接口,以后都是了。
Service层需要处理业务——开启事务注解
/* 处理业务:开启事务
* Propagation.REQUIRED(常用)
表示当前方法必须运行在事务中。
Propagation.SUPPORTS(常用)
* 表示当前方法不需要事务上下文,但是如果存在当前事务的话,那么该方法会在这个事务中运行
*/
@Transactional(propagation = Propagation.SUPPORTS,readOnly = true)
public class ProductServiceImpl implements IProductService {
//注入Dao的接口
@Autowired
private IProductDao productDao;
/*这里的增、删、改都是需要事务的哦!!所以再给他们单独配置一个*/
@Transactional(propagation = Propagation.REQUIRED)
public void save(Product product) {
productDao.save(product);
}
三、Spring事务传播机制
3.1、什么是传播机制
多个方法之间,比如A方法 去调用B方法 事务就可以进行相互传播(A有事务,调用B后,B也被加起事务了)
3.2、传播机制总共有七种:
Propagation.REQUIRED(常用)
表示当前方法必须运行在事务中。如果当前事务存在,方法将会在该事务中运行。否则,会启动一个新的事务
Propagation.SUPPORTS(常用)
Propagation.SUPPORTS(常用)
表示当前方法不需要事务上下文,但是如果存在当前事务的话,那么该方法会在这个事务中运行
3.3、配置及使用:
1、注入:JpaTransactionManager
<!-- 1、事务管理器-->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<!--注入:EntityManagerFactory 好让我们的事务去管理他-->
<property name="entityManagerFactory" ref="entityManagerFactory"></property>
</bean>
<!-- 2、开启事务 扫描@Transaction这种注解-->
<tx:annotation-driven/>
2、使用
如果@Transactional配置到类上面 ,类里面方法都是用这个传播机制 ;
如果自身的方法配置@Transactional传播机制 方法上面就采用自己配置注解
readOnly = true 只读:只允许读取 – 查询方法配置
@Service
@Transactional(propagation = Propagation.SUPPORTS,readOnly = true)
public class ProductServiceImpl implements IProductService {
//注入Dao的接口
@Autowired
private IProductDao productDao;
/*这里的增、删、改都是需要事务的哦!!所以再给他们单独配置一个*/
@Transactional(propagation = Propagation.REQUIRED)
public void save(Product product) {
productDao.save(product);
}
四、SpringMVC+spring集成
1、配置步奏
(1)导入jar --spring-web /spring-webmvc
(2)、配置 applicationContext-MVC.xml 配置文件
0、配置mvc命名空间(如果报红-找不到,就把jar包删了)
1、扫描controller
2、静态资源放行
3、 扫描@RequestMapping注解
4、视图解析器:InternalResourceViewResolver
配置前缀 后缀
5、上传解析器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 1、扫描controller-->
<context:component-scan base-package="com.cc.ssj.web.controller"></context:component-scan>
<!-- 2、静态资源放行-->
<mvc:default-servlet-handler/>
<!-- 3、扫描RequestMapping-->
<mvc:annotation-driven/>
<!-- 4、视图解析器:InternalResourceViewResolver-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!--5、上传-->
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize">
<value>${1024*1024*10}</value>
</property>
</bean>
</beans>
(3)、配置web.xml
1、核心控制器配置:DispatcherServlet
初始化:访问 classpath:applicationContext_mvc.xml 这个配置文件
2、字符编码过滤器:CharacterEncodingFilter
3、监听器读取配置
4、处理懒加载关闭问题
4.1、异常1:(JSON的对象数据传不过去)
JsonMappingException: could not initialize proxy - no Session
LazyInitializationException: could not initialize proxy - no Session
处理方式:
延迟 entityManager 关闭(我们去取dir分类中的name的时候已经关闭了。)。
加一层过滤器(放到最上面)
4.1、异常2:没有找到 “handler” 这个属性
异常2:HttpMessageNotWritableException……中没有找到 "handler" 这个属性
1.jpa在底层延迟加载的时候额外生产了一个属性"handler"
2.SpringMVC返回JSON数据进行数据组装的时候,出现冲突
处理方式:
让SpringMVC忽略"handler" 这个属性
在实体类中的List数据(Product中的dir属性)上面打注解:
@JsonIgnoreProperties({"hibernateLazyInitializer","handler"})
5、web.xml 所有配置:
<!-- 4、处理懒加载关闭问题 -->
<filter>
<filter-name>openEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>openEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 1、核心控制器配置-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext_mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!--所有的servlet都要过-->
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--2、字符编码过滤器-->
<filter>
<filter-name>characterEncoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--3、监听器读取配置-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
(4)、配置tomCat服务器
略……
五、前台处理数据 及 Controller层注意事项
1、Controller层注意事项
如果要返回json数据,一定要用:@ResponseBody ——返回json数据
2、处理数据:
注意:jsp返回数据时,如果返回的json数据中有Obejct对象的数据,需要:
1、在需要取值的定义一个:formatter: 函数名(cc) 属性
<th data-options="field:'dir',width:80,align:'right',formatter:cc">类型</th>
2、使用JS代码去取值即可
dir是product中的一个字段,但是是对象,所以需要这样取值
<script type="text/javascript">
function cc (dir) {
if (dir != null) {
return dir.name;
}
}
</script>
2、处理数据:
注意:jsp返回数据时,如果返回的json数据中有Obejct对象的数据,需要:
1、在需要取值的定义一个:formatter: 函数名(cc) 属性
<th data-options="field:'dir',width:80,align:'right',formatter:cc">类型</th>
2、使用JS代码去取值即可
dir是product中的一个字段,但是是对象,所以需要这样取值
<script type="text/javascript">
function cc (dir) {
if (dir != null) {
return dir.name;
}
}
</script>