项目实战04——项目准备

创建一个maven工程o2o

 创建完成后没有报错,加入tomcat启动也没问题,但是有一个问题,main文件下没有java文件和test文件,搜索了一下,发现大部分人的回答是 “右键所选择的Maven工程,右键properties,选择Java Build Path······”但是我并没有找到properties选项。可能是IDEA版本问题。其实回答大部分是说怎么从根本上解决问题,根据要求找到相应的压缩文件,然后说用压缩文件打开修改配置。好的,一切顺利,除了它并没有说修改哪个文件···。可能我的理解有误,还是乖乖手动创建。

 这是正确的目录结构。


接下来就开始正式的项目设计。首先先进行实体类解析:

 从单个实体类区域出发,我们先完成实体类设计与数据库表的创建:

 首先我们在java文件下的com.imooc.o2o.entity包,创建区域实体类Area.java,设置它的属性,这里用的都是引用类型,因为基础类型有默认值,我们不希望有默认值。然后设置它的get、set方法。

/**
 * 区域信息
 * @author 
 *
 */
public class Area {
    // 主键ID
    private Integer areaId;
    // 名称
    private String areaName;
    // 权重,越大越排前显示
    private Integer priority;
    // 创建时间
    private Date createTime;
    // 更新时间
    private Date lastEditTime;

//get、set方法
}

接下来,创建区域的数据库表,设计ID为主键,区域名称为唯一键。

完成后,同样的步骤创建用户实体类:

在entity包下创建PersonInfo实体类:

/**
 * 个人信息实体类
 *
 * @author
 *
 */
public class PersonInfo {
    // 主键ID
    private Long userId;
    // 用户名称
    private String name;
    // 用户头像
    private String profileImg;
    // 用户邮箱
    private String email;
    // 用户性别
    private String gender;
    // 可用状态:0、被禁止 1、可用
    private Integer enableStatus;
    // 1.顾客 2.店家 3.超级管理员
    private Integer userType;
    // 创建时间
    private Date createTime;
    // 最近一次的更新时间
    private Date lastEditTime;

//get、set方法
}

再在数据库中创建相应的表,完成该实体类的设计。

同样的设计还有以下的实体类:

 

 

 

 

 那么这么多的实体类是怎么关联的呢?

 

 然后我们配置以下项目的文件,在main.java.resources目录下创建spring、mapper

 

 然后我们在java中创建更多的包来存放不同的类:

 然后在pom文件中引入依赖,这里的依赖是spring的依赖,这个项目我们是用传统的SSM框架构建,所以引入的依赖较多,比如spring的常用8个依赖,spring-core、spring-beans、spring-context、spring-jdbc、spring-tx、spring-web、spring-webmvc、spring-test,以及mybatis的两个依赖mybatis、mybatis-spring,以及数据库的mysql-connector-java、c3p0 。


接下来,我们自上而下地来完成SSM的各项配置,首先在resources文件下创建jdbc.properties文件指定数据库的链接方式,

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/o2o?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
jdbc.username=root
jdbc.password=123456

然后同样在resources文件下创建mybatis-config.xml配置mybatis的相关信息:

//主要配置信息
<configuration>
    <!-- 配置全局属性 -->
    <settings>
        <!-- 使用jdbc的getGeneratedKeys获取数据库自增主键值 -->
        <setting name="useGeneratedKeys" value="true" />

        <!-- 使用列标签替换列别名 默认:true -->
        <setting name="useColumnLabel" value="true" />

        <!-- 开启驼峰命名转换:Table{create_time} -> Entity{createTime} -->
        <setting name="mapUnderscoreToCamelCase" value="true" />
    </settings>

</configuration>

然后在resource文件的spring目录下,创建spring-dao.xml配置文件,加载了上面的两个配置文件,创建了dataSource连接池,配置了mybatis与数据库交互的方式:

<!-- 配置整合mybatis过程 -->
	<!-- 1.配置数据库相关参数properties的属性:${url} -->
	<context:property-placeholder location="classpath:jdbc.properties"/>
	<!-- 2.数据库连接池 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<!--配置连接池属性-->
		<property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>

		<!-- c3p0连接池的私有属性 -->
		<property name="maxPoolSize" value="40" />
		<property name="minPoolSize" value="10" />
		<!-- 关闭连接后不自动commit -->
		<property name="autoCommitOnClose" value="false" />
		<!-- 获取连接超时时间 -->
		<property name="checkoutTimeout" value="10000" />
		<!-- 当获取连接失败重试次数 -->
		<property name="acquireRetryAttempts" value="2" />
	</bean>

	<!-- 3.配置SqlSessionFactory对象 -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- 注入数据库连接池 -->
		<property name="dataSource" ref="dataSource" />
		<!-- 配置MyBaties全局配置文件:mybatis-config.xml -->
		<property name="configLocation" value="classpath:mybatis-config.xml" />
		<!-- 扫描entity包 使用别名 -->
		<property name="typeAliasesPackage" value="com.imooc.o2o.entity" />
		<!-- 扫描sql配置文件:mapper需要的xml文件 -->
		<property name="mapperLocations" value="classpath:mapper/*.xml" />
	</bean>

	<!-- 4.配置扫描Dao接口包,动态实现Dao接口,注入到spring容器中 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<!-- 注入sqlSessionFactory -->
		<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
		<!-- 给出需要扫描Dao接口包 -->
		<property name="basePackage" value="com.imooc.o2o.dao" />
	</bean>

。然后dao层后就是service层配置,同样在spring目录,创建spring-service.xml配置文件,主要进行事务管理,将在dao层配置好的dataSource注入事务管理器,便于对service层做操作:

//主要配置信息
    <!-- 扫描service包下所有使用注解的类型 -->
    <context:component-scan base-package="com.imooc.o2o.service" />

    <!-- 配置事务管理器 -->
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 注入数据库连接池 -->
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!-- 配置基于注解的声明式事务 -->
    <tx:annotation-driven transaction-manager="transactionManager" />

接下来就是web层的配置,同样spring目录下创建spring-web.xml配置文件,定义了如何响应url请求,也就是定义controler的行为:

//主要配置信息
	<!-- 配置SpringMVC -->
	<!-- 1.开启SpringMVC注解模式 -->
	<mvc:annotation-driven />

	<!-- 2.静态资源默认servlet配置 
        (1)加入对静态资源的处理:js,gif,png 
        (2)允许使用"/"做整体映射 -->
	<mvc:resources mapping="/resources/**" location="/resources/" />
	<mvc:default-servlet-handler />

	<!-- 3.定义视图解析器 -->
	<bean id="viewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/html/"></property>
		<property name="suffix" value=".html"></property>
	</bean>

	<!-- 4.扫描web相关的bean -->
	<context:component-scan base-package="com.imooc.o2o.web" />

基本完成了所有配置,我们需要整合这些spring配置,在src/main/webapp/WEB_INF/web.xml文件下进行整合配置,将spring-dispatcher当成一个service注册到里面,同时将spring的几个配置整合到了一起:

//主要配置信息
<servlet>
    <servlet-name>spring-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring/spring-*.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>spring-dispatcher</servlet-name>
    <!-- 默认匹配所有的请求 -->
    <url-pattern>/</url-pattern>
 </servlet-mapping>


接下来,我们来验证一下dao层是否可以运行。首先,我们利用比较简单的实体类——区域,作为一个验证的对象,先在dao包里创建AreaDao接口:

public interface AreaDao {
	/**
	 * 列出区域列表
     * @return areaLis
	 */
	List<Area> queryArea();
}

由于mybatis不需要dao写一个实现类,而是直接在mybatis里实现,所以我们只需要在resources/mapper里进行配置就可以了。创建一个AreaDao.xml文件:

<?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.imooc.o2o.dao.AreaDao">
	<select id="queryArea" resultType="com.imooc.o2o.entity.Area">
		SELECT area_id, area_name,
		priority, create_time, last_edit_time
		FROM tb_area
		ORDER BY priority
		DESC
	</select>
</mapper>
    

然后创建测试类进行测试,在test/java/com/imooc/o2o 下创建BasTest.class,设置测试的基类:

/**
 * 
 * 配置spring和junit整合,junit启动时加载springIOC容器
 *
 */
// 告诉junit spring配置文件的位置
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "classpath:spring/spring-dao.xml"})
public class BaseTest {

}

但是这个SpringJUnit4ClassRunner和ContextConfiguration注解都报错:

 找了一下这个“Cannot resolve symbol...”错误,发现项目的maven没有修改成本地路径: 

修改完成,刷新maven。不行,重启一下IDEA,file->Invalidate Caches/Restart,然后刷新maven,引入相关包,解决bug!

定义好测试基类,在test/java/com/imooc/o2o下创建dao包,创建AreaDaoTest.class测试类:

public class AreaDaoTest extends BaseTest{
	@Autowired
	private AreaDao areaDao;
	
	@Test
	public void testQueryArea(){
		List<Area> areaList = areaDao.queryArea();
        //因为数据库中area有两条数据,我们测试一下是否等于2
		assertEquals(2, areaList.size());
	}
}

测试一下!不出所料,出bug了:

还是BaseTest类出现的错误。显示找不到上述bug中的两个类,最后感谢我亲爱的舍友找出问题的关键,

 一开始我的test目录下的java文件是Sources类型,改成Tests类型后,bug成功解决且运行成功。即dao层已经成功链接数据库。按照舍友的说法,文件类型决定了编译时是否转化为字节码,所以不同类型会有很大影响。


接下来测试service层,我们现在main/java/com/imooc/o2o/service下创建AreaService接口,

public interface AreaService {
	public List<Area> getAreaList();
}

在service的impl文件下,创建AreaServiceImpl实现类:

@Service
public class AreaServiceImpl implements AreaService {
	@Autowired
	//该注解是让spring容器自动将areaDao的实现注入
	private AreaDao areaDao;
	@Override
	public List<Area> getAreaList(){
		return areaDao.queryArea();
	}
}

然后在test/java/com/imooc/o2o下的BaseTest测试基类下的@ContextConfiguration注解下添加spring-service.xml配置文件,然后在test/java/com/imooc/o2o下创建service文件,并创建测试service层的AreaServiceTest类:

public class AreaServiceTest extends BaseTest {
	@Autowired
	private AreaService areaService;

	@Test
	public void testGetAreaList() {
		List<Area> areaList = areaService.getAreaList();
		assertEquals("西苑", areaList.get(0).getAreaName());
	}
}

因为是调用dao层的getAreaList()方法,在上一步测试中dao层已经成功,所以这里也没有太多的问题。


接下来测试web控制层功能,由于我们的测试例子是区域,而区域是由超级管理员管理的,所以为我们在src/main/java/com/imooc/o2o/web/superadmin文件下,创建AreaController类:

@Controller
@RequestMapping("/superadmin")
public class AreaController {
    @Autowired
    private AreaService areaService;
    @RequestMapping(value = "/listarea",method = RequestMethod.GET)
    @ResponseBody
    //@ResponseBody这个注解是将modelMap这个对象自动转换成json对象返回给前端
    private Map<String,Object> listArea(){
        Map<String, Object> modelMap = new HashMap<String, Object>();
        List<Area> list = new ArrayList<Area>();
        try {
            list = areaService.getAreaList();
            modelMap.put("rows",list);
            modelMap.put("total",list.size());
        }catch (Exception e){
            e.printStackTrace();
            modelMap.put("success",false);
            modelMap.put("errMsg",e.toString());
        }
        return modelMap;
    }
}

由于已经涉及到前端,可以直接启动tomcat,在页面访问该功能,测试该功能是否成功:

是成功的。这么一来,从dao层到service层再到controller层都是可以的。


Logback日志配置

  • 故障定位
  • 显示程序运行状态

主要模块:

  • logback-access
  • logback-classic
  • logback-core

主要标签:

  • logger:作为日志记录器,用于存放日志对象,也可以定义日志的级别、类型
  • appender:指定日志输出目的地,可以是控制台、文件、套接字符
  • layout:格式化日志输出

在main/resources文件下创建logback.xml配置文件,

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
	<!-- 定义参数常量 -->
	<!-- TRACE<DEBUG<INFO<WARN<ERROR -->
	<!-- logger.trace("msg") logger.debug... -->
	<property name="log.level" value="debug" />
	<property name="log.maxHistory" value="30" />
	<property name="log.filePath" value="${catalina.base}/logs/webapps" />
	<property name="log.pattern"
		value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n" />
	<!-- 控制台设置 -->
	<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
		<encoder>
			<pattern>${log.pattern}</pattern>
		</encoder>
	</appender>
	<!-- DEBUG -->
	<appender name="debugAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
		<!-- 文件路径 -->
		<file>${log.filePath}/debug.log</file>
		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
			<!-- 文件名称 -->
			<fileNamePattern>${log.filePath}/debug/debug.%d{yyyy-MM-dd}.log.gz
			</fileNamePattern>
			<!-- 文件最大保存历史数量 -->
			<maxHistory>${log.maxHistory}</maxHistory>
		</rollingPolicy>
		<encoder>
			<pattern>${log.pattern}</pattern>
		</encoder>
		<filter class="ch.qos.logback.classic.filter.LevelFilter">
			<level>DEBUG</level>
			<onMatch>ACCEPT</onMatch>
			<onMismatch>DENY</onMismatch>
		</filter>
	</appender>
	<!-- INFO -->
	<appender name="infoAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
		<!-- 文件路径 -->
		<file>${log.filePath}/info.log</file>
		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
			<!-- 文件名称 -->
			<fileNamePattern>${log.filePath}/info/info.%d{yyyy-MM-dd}.log.gz
			</fileNamePattern>
			<!-- 文件最大保存历史数量 -->
			<maxHistory>${log.maxHistory}</maxHistory>
		</rollingPolicy>
		<encoder>
			<pattern>${log.pattern}</pattern>
		</encoder>
		<filter class="ch.qos.logback.classic.filter.LevelFilter">
			<level>INFO</level>
			<onMatch>ACCEPT</onMatch>
			<onMismatch>DENY</onMismatch>
		</filter>
	</appender>
	<!-- ERROR -->
	<appender name="errorAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
		<!-- 文件路径 -->
		<file>${log.filePath}/erorr.log</file>
		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
			<!-- 文件名称 -->
			<fileNamePattern>${log.filePath}/error/error.%d{yyyy-MM-dd}.log.gz
			</fileNamePattern>
			<!-- 文件最大保存历史数量 -->
			<maxHistory>${log.maxHistory}</maxHistory>
		</rollingPolicy>
		<encoder>
			<pattern>${log.pattern}</pattern>
		</encoder>
		<filter class="ch.qos.logback.classic.filter.LevelFilter">
			<level>ERROR</level>
			<onMatch>ACCEPT</onMatch>
			<onMismatch>DENY</onMismatch>
		</filter>
	</appender>
	<logger name="com.imooc.o2o" level="${log.level}" additivity="true">
		<appender-ref ref="debugAppender"/>
		<appender-ref ref="infoAppender"/>
		<appender-ref ref="errorAppender"/>
	</logger>
	<root level="info">
		<appender-ref ref="consoleAppender"/>
	</root>
</configuration>

然后在控制层加入logback日志信息,修改一下上次controller层的代码,就能打印相关日志:

@Controller
@RequestMapping("/superadmin")
public class AreaController {
    Logger logger = LoggerFactory.getLogger(AreaController.class);
    @Autowired
    private AreaService areaService;
    @RequestMapping(value = "/listarea",method = RequestMethod.GET)
    @ResponseBody
    private Map<String,Object> listArea(){
        logger.info("===start===");
        long stratTime = System.currentTimeMillis();
        Map<String, Object> modelMap = new HashMap<String, Object>();
        List<Area> list = new ArrayList<Area>();
        try {
            list = areaService.getAreaList();
            modelMap.put("rows",list);
            modelMap.put("total",list.size());
        }catch (Exception e){
            e.printStackTrace();
            modelMap.put("success",false);
            modelMap.put("errM",e.toString());
        }
        logger.error("test error!");
        long endTime = System.currentTimeMillis();
        logger.debug("costTime:[{}ms]",endTime - stratTime);
        logger.info("===end===");
        return modelMap;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值