Spring-Spring与JavaWeb整合

瘦欲@ 提交于 2020-01-13 16:35:34

一.概述

Spring与JavaWeb整合时,Spring可以完成的任务有:

1)Spring来控制事务(dao-JdbcTemplate)

2)所有组件Autowried

3)管理数据库...

1.1 整合的步骤

1.导包

2.写配置

   1)将所有组件加入到容器中,并能正确获取

@Controller:servlet层,目前不能标注在Servlet层(Tomcat启动时会创建Servlet,使用注解的话会创建新的Servlet)
@Service :业务逻辑层
@Repository :dao层
@Component:其他组件

   2)每个组件之间自动装配

   3)配置声明式事务

         事务管理器控制数据库连接池

    4)IOC创建和销毁都要在合适的时机完成--使用监听器启动容器。

项目启动{
    IOC创建完成
}

项目销毁{
    
  IOC销毁
}

可以写一个监听器完成这个工作,Spring写好了这个监听器。这个监听器创建好的IOC容器在ContextLoader(这个属性就是IOC容器)。有一个静态方法能获取:getCurrentWebApplicationContext。

private WebApplicationContext context;

3.测试

二.整合实验

以之前的书城为例:

1.导包:导入Spring所需要的包

spring-aop-4.0.0.RELEASE.jar
spring-aspects-4.0.0.RELEASE.jar
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar
spring-jdbc-4.0.0.RELEASE.jar
spring-orm-4.0.0.RELEASE.jar
spring-tx-4.0.0.RELEASE.jar

2.写配置:

       1)将所有组件加入到容器中,并能正确获取。首先创建Spring的配置文件,并在配置文件中选择需要的名称空间:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

  <context:component-scan base-package="com.atguigu"></context:component-scan>

</beans>

根据上面所讲,在业务逻辑层和Dao层加上注解,下面为例:

@Repository
public class BookDaoImpl extends BaseDaoImpl<Book> implements BookDao{...}

@Service
public class BookServiceImpl implements BookService{...}

//注意注解是写在实现类上的,不能写在接口上

 2)每个组件之间自动装配,如下面会分为两种情况:

  • 在加注解的类中使用@Autowired直接注入
  • 在Servlet(不能加注解)中,调用方法获得组件(这个方法写在一个类中,供所有的Servlet调用。因为Tomcat在启动时会创建Servlet,Servlet会调用这个方法,在这个方法中创建了IOC容器,从IOC容器中获得这个Service组件)。
//有两种情况,一种是在加了注解的类中直接使用@Autowired注解直接注入

@Service
public class BookServiceImpl implements BookService {

	@Autowired
	private BookDao bookDao;
    ...
}

//另一种是在不能加注解的Servlet中,使用特殊方法获得
public class BookServlet extends BaseServlet {
	private static final long serialVersionUID = 1L;

	private BookService bookService=WebUtils.getBean(BookService.class);
    ...
}

//因为启动Tomcat后,首先会创建Servlet,然后这些Servelt会想获得Service,就会调用这个方法,这个方法就会创建IOC容器,然后从容器中获得Service组件
public class WebUtils {
	
   private static ApplicationContext ioc=new ClassPathXmlApplicationContext("applicationContext.xml");
	/*
	 * 从IOC容器中获取组件
	 */
		public static <T>T getBean(Class<T> clazz){
			return ioc.getBean(clazz);
			
		}
   ...
}

    3)配置声明式事务

           事务管理器控制数据库连接池。

           (1)首先在配置文件中配置数据源和JdbcTemplate:

<!-- 引用外部配置文件 -->
  <context:property-placeholder location="classpath:dbconfig.properties"/> 
  <!-- 1.配置数据源 -->
  <bean class="com.mchange.v2.c3p0.ComboPooledDataSource" id="dataSoure">
     <property name="user" value="${jdbc.user}"></property>
     <property name="password" value="${jdbc.password}"></property>
     <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
     <property name="driverClass" value="${jdbc.driverClass}"></property>
  </bean>
  <!-- 2.JdbcTemplate操作数据库 -->
  <bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
     <constructor-arg name="dataSource" ref="dataSoure"></constructor-arg>
  </bean>
  

      (2)下来对Dao层实现类进行更改,因为之前编写的逻辑是所有的Dao实现类都继承了BaseDao实现类,为了更改方便起见,所有对更改都在BaseDao实现类中进行更改。在这个类中使用JdbcTemplate来操作数据库。

@Repository
public abstract class BaseDaoImpl<T> {

	
//	protected QueryRunner queryRunner;
	@Autowired
	private JdbcTemplate jdbcTemplate;
	/**
	 * 保存BaseDaoImpl类的泛型对象class类型
	 */
	protected Class<T> type;

	@SuppressWarnings("unchecked")
	public BaseDaoImpl() {
		// 创建一个QueryRunner对象实例
	
		// 获取父类中带有泛型的父类的class类型
		ParameterizedType supperClass = (ParameterizedType) getClass().getGenericSuperclass();
		// 获取泛型中的具体的类型的class
		type = (Class<T>) supperClass.getActualTypeArguments()[0];
	}

	/**
	 * 执行update,delete,insert语句
	 * 
	 * @param sql
	 *            要执行的sql语句
	 * @param params
	 *            执行的sql语句的参数
	 * @return 如果语句执行成功返回true<br/>
	 *         如果执行失败返回false
	 * @throws SQLException 
	 */
	public int update(String sql, Object... params) throws SQLException {
		int update=jdbcTemplate.update(sql,params);
		return update;
	}

	/**
	 * 执行查询语句,只返回第一个记录
	 * 
	 * @param sql
	 *            要执行的sql语句
	 * @param params
	 *            执行的sql语句的参数
	 * @return 返回查询对象的具体实例 <br/>
	 *         如果查询的数据不存在,则返回null<br/>
	 *         查询失败也返回null
	 * @throws SQLException 
	 */
	public T queryOne(String sql, Object... params) throws SQLException {
	T Object=null;
	try {
		Object = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<T>(type),params);
	} catch (DataAccessException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	return Object;
	}

	/**
	 * 执行查询语句,返回查询后的对象实例集合
	 * 
	 * @param sql
	 *            要执行的sql语句
	 * @param params
	 *            sql语句的参数
	 * @return 返回的是查找到的对象集合<br/>
	 *         查询失败返回null
	 * @throws Exception 
	 */
	public List<T> queryList(String sql, Object... params) throws Exception {
		return jdbcTemplate.query(sql, new BeanPropertyRowMapper<T>(type),params);
	}

	
	/**
	 * 查询只有一个返回值的语句
	 * 
	 * @param sql
	 * @param params
	 * @return
	 * @throws Exception 
	 */
	public Object querySingleValue(String sql, Object... params) throws Exception {
		Object object=jdbcTemplate.queryForObject(sql, Object.class, params);
		return object;
	}

}

   (3)在配置文件中配置事务管理器和配置基于Xml的事务(因为使用注解@Transactional配置事务,需要给所有方法添加,不太方便)

 <!-- 3.配置事务管理器 -->
   <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="dataSourceTransactionManager">
     <property name="dataSource" ref="comboPooldeDataSource"></property>
   </bean>
   
  <!-- 基于配置的事务 -->
  <aop:config>
      <aop:pointcut expression="execution(* com.atguigu.service.impl.*.*(..))" id="txPoint"/>
      <aop:advisor advice-ref="myTx" pointcut-ref="txPoint"/>
  </aop:config>
  <tx:advice id="myTx" transaction-manager="dataSourceTransactionManager">
      <tx:attributes>
         <tx:method name="*"/>
         <tx:method name="get*" read-only="true"/>
      </tx:attributes>
  </tx:advice>

  (4)测试:因为在数据库中设置书的库存量不能小于0,所以在结账操作时,选择库存量为0的书进行结账,会跳转到异常界面,显示结账失败。因为是给所有方法添加了事务管理,所以出现异常时,事务回滚,数据库中的数据不会进行更改。所以,上述情况才会成功。

4)使用监听器来启动容器。在之前的实验步骤中我们在Servlet中调用一个方法来创建容器,并通过这个容器来获得组件。这样做容易存在问题,例如,通过反射可以创建更多的容器,或者容器在项目启动的时候创建,但在项目关闭的时候并没有销毁,不断的开启项目会消耗内存。所以使用一个监听器来启动容器,这个监听器Spring已经创建好了。我们要使用,首先在web,xml中进行注册:

   <!-- needed for ContextLoaderListener -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:applicationContext.xml</param-value>
	</context-param>

	<!-- Bootstraps the root web application context before servlet initialization -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
  

注册成功后,然后在Servlet中获得组件是这样使用的:

public static <T>T getBean(Class<T> clazz){
			//获取IOC容器
			WebApplicationContext ioc=ContextLoader.getCurrentWebApplicationContext();
			return ioc.getBean(clazz);
			
		}

这样就可以使用监听器来启动容器了。

3.测试,执行成功后,页面如下:

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!