这是根据老师上课的内容做的课程项目笔记,项目资源是老师发的,不是本人的项目资源
在线商城系统03——把所有商品类型在前端页面展示出来,展示在02中跳转的商品类型管理页面中
操作数据有三层结构,pojo,dao和service,pojo存放实体数据,dao对pojo进行操作,service对dao进行操作。
导入数据库
打开mysql小黑窗,把创建数据库的sql文件和初始化数据的sql文件拖入命令行,现在就有数据了。
创建pojo
一般来说一张表对应一个实体类,编写实体类时需要对其进行序列化操作。
什么是序列化?
确切的说应该是对象的序列化,一般程序在运行时,产生对象,这些对象随着程序的停止运行而消失,但如果我们想把某些对象(因为是对象,所以有各自不同的特性)保存下来,在程序终止运行后,这些对象仍然存在,可以在程序再次运行时读取这些对象的值,或者在其他程序中利用这些保存下来的对象。这种情况下就要用到对象的序列化。
注意:定义类型的时候尽可能使用包装类。
创建文件夹pojo,该文件夹与controller同级目录,在该文件夹下创建与产品类型表对应的类,类中的属性要与表中的字段相对应:
创建dao
创建文件夹dao存放dao接口,该文件夹与controller平级目录,在dao文件夹下创建接口ProductTypeDao,接口的内容按照所想要的功能编写,对产品类型表的操作是查看所有类型的产品:
因为这是一个ssdm项目,因此不需要编写dao的实现类,而是在map配置文件中写sql语句。
一般情况下map文件是在resources目录下的,但是也可以在源代码目录下创建,只要做好相关配置就好了。
在backend包下创建包mapper,创建一个xml文件productTypeMapper.xml
因为创建该表对应的实体bean的时候,类中的属性名与表中的字段名是相同的,返回值只需要是resultType就可以了,如果有不同的话就要使用Map。
这样将查询的结果注入到指定的resultType中:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zte.shop.backend.dao.ProductTypeDao">
<!--查看所有产品类型
public List<ProductType> selectAll();-->
<select id="selectAll" resultType="com.zte.shop.backend.pojo.ProductType">
select
name,id,status
from
t_product_type
</select>
</mapper>
创建了dao和mapper文件并不能使这两个文件能找到彼此,要在资源路径中添加dao的配置文件spring-dao.xml。在该配置文件中实现与数据库(数据源)的连接、集成mybatis。可以将数据源分到另一个文件中,在spring-dao.xml中引用这个数据源,降低程序的耦合性。
创建存放数据源的文件,在resources下创建文件datasource.properties
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/zshop?useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=111111
jdbc.initialSize=5
在resources下创建配置文件spring-dao.xml,在该配置文件中加载存放数据源的文件
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:datasource.properties"/>
<!--数据源-->
<bean id="datasource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="initialSize" value="${jdbc.initialSize}"/>
</bean>
<!--集成mybatis-->
</beans>
加上这一段之后就能加载,mapper配置文件了,并且将mapper配置文件与数据源集成
<!--集成mybatis-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="datasource"/>
<!--设置别名-->
<property name="typeAliasesPackage" value="com.zte.shop.backend.pojo"/>
<!--加载mapper配置文件-->
<property name="mapperLocations" value="classpath:com/zte/shop/backend/mapper/*Mapper.xml"/>
</bean>
但是此时dao接口类并没有与mapper配置文件相互集成,要在spring-dao.xml中生成mapper代理
<!--生成mapper代理-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.zte.shop.backend.dao"/>
</bean>
因为这是一个多模块开发的项目,不应该把所有模块的逻辑都写在同一个模块下,因此要把相应的文件夹移到相应的模块中去
把controller、mapper、dao包移到dao模块,pojo包移到pojo模块中。
这个时候还有一个问题,因为Mapper配置文件只有在resources资源目录下才能被扫描到,放在源代码目录下是扫描不到的,要在相应的pom.xml中进行相应的配置使在资源路径下的mapper文件能够被找到。
在dao模块的pom.xml配置文件中加入:
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>
</resources>
</build>
但是此时就覆盖掉默认的resources目录了,想要resources目录下的配置文件也被扫描到就要在pom.xml中继续指定:
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>
创建service
dao层编写好之后要在service模块对dao层进行包装。
首先在service模块下创建一个接口ProductTypeService,用于查询所有的产品类型,与dao层不同的是,service层添加了事务管理
ProductTypeService:
在shop_parent包下创建impl包,用于存放接口的实现类,创建ProductTypeServiceImpl
注意:在service实现类中的几个重要注解
- @service: 加了该注解表示该类被spring管理
- @Transactional:事务管理加在类上表示该类通用,如果类中的某方法不需要通用的事务管理可以在方法上添加一个@Transactional来覆盖掉默认的事务管理设置
- @Autowired:注入,在service中一般用于注入dao
@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class ProductTypeImpl implements ProductTypeService {
@Autowired
private ProductTypeDao productTypeDao;
@Transactional(propagation = Propagation.SUPPORTS,readOnly = true)
@Override
public List<ProductType> findAll() {
return productTypeDao.selectAll();
}
}
在serviceimpl中虽然注入了dao,但是现在不能起到作用,注入的dao此时并没有被spring管理,因此要在dao接口类上添加,使之被spring管理
但是此时spring并不能扫描到该包,要在spring-dao.xml中指定扫描包才可:
这个时候虽然加上了注解但是此时注解是无效的,因为service并没有被配置。之前controller、dao能被spring管理,注解能够起作用的原因都是因为有相应的配置文件,在配置文件中扫描了这些包。要想使service也被spring管理,同理,也要创建一个管理service的配置文件,在该配置文件中扫描service包,配置事务。
在shop_backend_web模块的resources下创建配置文件spring-service.xml
- 扫描包,让service被spring管理,被spring管理的是service的实现类,而不是接口
<!--扫描service包,被spring管理的是service的实现类-->
<context:component-scan base-package="com.zte.shop_parent.service.impl"/>
- 配置声明事务,这个数据源是之前创建的数据源配置文件,由于在spring-dao.xml中已经加载过了,所以这里不用加载就可以直接使用,这段代码使@Transactional注解有效:
<!--配置声明事务-->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource"/>
</bean>
<!--配置注解事务-->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
注意:配置注解事务的注解驱动有好几个,要选择最后是tx的。
controller层
在上篇文章中已经写了一部分controller层的代码。但是仅仅完成了使页面成功跳转,是没有任何业务操作的。
这个方法是用于查找所有商品类型的,在controller层调用service层的方法来获取想要的数据,再把数据封装到变量中,在前端jsp文件中访问该变量的时候就可以获取到查询出的方法了。
这个方法使用来查找所有商品的所以这个二级目录最好换成"/findAll",在对应的main.jsp页面中的请求路径也要换。
前端页面取值
controller层写好之后就可以在前端页面获取数据了,刚刚写的controller层的方法返回的是productTypeManage.jsp页面,在该页面中获取通过data获取集合,该集合存放的是所有的商品类型的信息,遍历该集合,获取每条商品类型信息并展示出来
由于状态需要其他操作,现在先传入id和name看看页面是否能正确展示出来:
数据库中的数据出现了中文乱码:
查看该数据库的字符集,发现是latinl,把字符集修改为utf8:
乱码解决
接下来再编写没有完成的状态,数据库中的状态是整数类型的,1表示启用0表示禁用,所以要写个if语句把他们分开:
<td>
<c:if test="${productType.status==1}">启用</c:if>
<c:if test="${productType.status==0}">禁用</c:if>
</td>