用spring实现一个论坛基本功能

1 运行环境

Linux:Ubun 14.04 64bit

IDE:IntelliJ IDEA 14.03

JDK:1.7.40

MySQL:5.5.44

Tomcat:7.0.47

Maven:3.0.5

2 具体步骤

新建一个Webapp工程,名字就叫spring-bbs-demo 项目的目录结构如下:

├── pom.xml
├── README.MD
├── spring-bbs-demo.iml
└── src
└── main
├── resources
└── webapp
├── index.jsp
└── WEB-INF
└── web.xml

在mysql里创建两张表,数据库名为sampledb

DROP DATABASE IF EXISTS sampledb;
CREATE DATABASE sampledb DEFAULT CHARACTER SET utf8mb4;
USE sampledb; -- 创建用户表
CREATE TABLE t_user (
user_id INT AUTO_INCREMENT NOT NULL COMMENT '用户id',
user_name VARCHAR(30) NOT NULL DEFAULT '' COMMENT '用户名',
credits INT NOT NULL DEFAULT 0 COMMENT '论坛积分',
password VARCHAR(32) NOT NULL DEFAULT ''COMMENT '用户密码',
last_visit TIMESTAMP NOT NULL DEFAULT 0 COMMENT '最后访问时间',
last_ip VARCHAR(23) NOT NULL DEFAULT '0.0.0.0' COMMENT '最后访问ip',
PRIMARY KEY (user_id)
)ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT '用户表'; -- 创建用户登陆日志表
CREATE TABLE t_login_log (
login_log_id INT AUTO_INCREMENT NOT NULL COMMENT '日志id',
user_id INT NOT NULL DEFAULT 0 COMMENT '用户id',
ip VARCHAR(23) NOT NULL DEFAULT '0.0.0.0' COMMENT '访问ip',
login_datetime TIMESTAMP NOT NULL DEFAULT 0 COMMENT '访问时间',
PRIMARY KEY (login_log_id)
)ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT '用户登陆日志表'; INSERT INTO t_user (user_name,password) VALUES ('admin','123456');

最终项目目录结构

├── pom.xml
├── README.MD
├── spring-bbs-demo.iml
└── src
└── main
├── java
│ └── com
│ └── springbbs
│ ├── dao
│ ├── domain
│ └── service
├── resources
│ └── sql
│ └── user_table_init.sql
└── webapp
├── index.jsp
└── WEB-INF
└── web.xml

NOTE:java为代码根目录,如果不是,可以在java文件夹上右击->Mark Directory As->Resources Root
同理,resources为资源根目录,webappweb根目录,test目录下的java文件夹为TestR Resources Root目录

文件及文件夹相关函数

文件 解释
applicationContext.xml Spring容器配置文件
domain 领域对象(实体类)存放文件夹,往往拥有对应的数据库表,一般要实现Serializable接口,以便序列化
dao 访问实体类的接口,一般一个实体类都会有一个dao与之对应,里面有一些对应的方法
jdbcTemplate Spring对jdbc的简单封装,可以轻松完成大部分的数据库操作而不必频繁的重复对数据库的打开,获取连接,查询,关闭等操作
jdbcTemplate#query() query(String sql,Object[] args,RowCallbackHandler rch).第一个参数不解释了;第二个是占位符(?)对应的参数数据;第三个是查询结果的处理回调接口,该回调接口有一个方法processRow(ResultSet resultSet)负责将查询结果从ResultSet装载到类似于实例类对象的实例中。一般都是使用匿名内部类的方式来调用RowCallbackHandler接口

NOTE:在DAO文件中写的sql语句比较长,多行衔接要注意空格,不然会连在一起,具体小技巧是每一行最后加个空格。

Spring中配置

以上两个DAO实现类中并没有打开/和释放Connection,到底如何访问数据库呢?答案是jdbcspring封装起来了,JdbcTemplate需要一个dataSource,从数据源中获取或返回连接。所以在UserDaoLoginLogDao中都提供了一个带@Autowired注解的jdbcTemplate对象。 所以我们需要先申明一个数据源,然后再定义一个JdbcTemplate Bean,通过Spring的容器上下文自动绑定机制进行Bean的注入。配置文件在Resources文件夹下,名字叫applicationContext.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:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
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"> <!-- 1 加载配置文件 -->
<context:property-placeholder location="classpath:jdbc.properties" ignore-unresolvable="true"/>
<!--2 扫描类包,将标注Spring注解的类自动转化成Bean,同时完成Bean的注入-->
<context:component-scan base-package="com.springbbs.dao"/> <!--3 定义一个使用DBCP实现的数据源-->
<!--如果加载不了配置文件,此处手动改为对应的值-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
p:driverClassName="${jdbc.driver}"
p:url="${jdbc.url}"
p:username="${jdbc.username}"
p:password="${jdbc.password}"/> <!--4 定义jdbc模板Bean-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="dataSource"/>
</beans>

配置说明

jdbc.properties文件为mysql配置文件,内容如下:

jdbc.driver=com.mysql.jdbc.Driver j
dbc.url=jdbc:mysql://localhost:3306/sampledb
jdbc.username=yourName
jdbc.password=yourPassword

在配置文件中加载mysql配置文件,在定义数据源时需要使用到配置文件中的信息

业务层

在这个登陆实例中,仅有一个业务类,即UserService,它负责将持久层的UserDaoLoginDao组织起来完成用户/密码认证、登陆日志记录等操作。loginSucess将两个DAO组织起来共同完成一个事务性工作:更新两个表,虽然没有事务操作的影子,但是通过Spring事务配置即可。 关于几个注解的解释:

注解 作用
@Service UserService标注为一个服务层的Bean
@Autowired 注入userDaologinLogDao这两个DAO层的Bean

在Spring中装配Service

我们必须告诉Spring哪些业务类需要工作于事务环境下及事务的规则等内容,以便Spring根据这些信息自动为目标业务类添加事务管理功能。对applicationContext.xml更改:

<?xml version="1.0" encoding="UTF-8"?>
<!--1 引入aop及tx命名空间所对应的Schema文件-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 加载配置文件 -->
<context:property-placeholder location="classpath:jdbc.properties" ignore-unresolvable="true"/> <!--扫描类包,将标注Spring注解的类自动转化成Bean,同时完成Bean的注入-->
<context:component-scan base-package="com.springbbs.dao"/> <!--扫描service类包,应用Spring的注解配置-->
<context:component-scan base-package="com.springbbs.service"/> <!--配置事务管理器-->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource"/> <!--通过AOP配置提供事务增强,让service包下所有的Bean的所有方法拥有事务-->
<aop:config proxy-target-class="true">
<aop:pointcut id="serviceMethod" expression="execution(* com.springbbs.service..*(..))"/>
<aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice"/>
</aop:config> <tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<!--定义一个使用DBCP实现的数据源-->
<!--如果加载不了配置文件,此处手动改为对应的值-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
p:driverClassName="${jdbc.driver}"
p:url="${jdbc.url}"
p:username="${jdbc.username}"
p:password="${jdbc.password}"/> <!--定义jdbc模板Bean-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="dataSource"/>
</beans>

NOTE: 配置文件解释

命名空间

<!--添加`aop`和`tx`命名空间,这样就可以在`xml`配置文件中使用这两个空间下的标签了-->
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"

Service注解扫描目录

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

事务管理器

<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource"/>

aop事务增强

关于aop(面向切片的编程后面会细讲,目前可以理解为拦截和代理即可),execution(* com.springbbs.service.. *(..))的意思就是任意返回值的service包及子包下的任何参数的任何方法都切入进行事务管理。 ```xml

单元测试

jar包依赖

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>

创建单元测试的方法:光标放在在需要测试的类名字上(本例中是UserService),按住Ctrl+Shift+TJunit4单元测试,勾选3个方法即可。 测试类UserServiceTest代码如下:

package com.springbbs.service;

import com.springbbs.domain.User;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.util.Date; @RunWith(SpringJUnit4ClassRunner.class) // 基于JUnit4的Spring测试框架
@ContextConfiguration(locations = {"classpath:applicationContext.xml"}) //启动Spring容器
public class UserServiceTest { @Autowired
private UserService userService; @Test
public void testHasMatchUser() throws Exception {
boolean b1 = userService.hasMatchUser("admin", "123456");
boolean b2 = userService.hasMatchUser("admin", "1111"); Assert.assertEquals(true, b1);
Assert.assertEquals(false, b2);
} @Test
public void testFindUserByUserName() throws Exception {
User user = userService.findUserByUserName("admin");
Assert.assertEquals("admin", user.getUserName());
} @Test
public void testLoginSucess() throws Exception {
User user = userService.findUserByUserName("admin");
user.setLastIp("127.0.0.1");
user.setLastVistit(new Date());
userService.loginSucess(user);
}
}

NOTE:Spring测试框架可以和Junit4整合,通过Junit4@RunWith注解指定SpringJUnit4ClassRunner.class的测试运行器,该运行器是Spring提供的,可以将Spring容器和Junit4测试框架整合。@ContextConfiguration也是Spring提供的注解,它用于制定Spring的配置文件。 这里需要注意的是,因为我的resources文件夹被指定为资源根目录,所以使用的 classpath路径来加载,即最终在类的根目录下。 在UserServiceTest上右键->Run UserServiceTest即可运行单元测试。最后取数据库中查询登陆日志可以发现成功插入一条记录。

项目代码地址:https://github.com/sjq597/JavaPracticeCode/tree/Spring 分支

tag:https://github.com/sjq597/JavaPracticeCode/tree/spring-bbs-v1.0

Spring 学习笔记02的更多相关文章

  1. Spring学习笔记——02 Bean的命名及实例化

    一.Bean的命名 前一篇讲到IoC是一个管理Bean的容器,Bean多数情况下都是通过XML文件进行配置的,其中Bean的命名有以下几种方式,现在梳理一下. 1. 不指定id,只配置类名 <b ...

  2. Redis:学习笔记-02

    Redis:学习笔记-02 该部分内容,参考了 bilibili 上讲解 Redis 中,观看数最多的课程 Redis最新超详细版教程通俗易懂,来自 UP主 遇见狂神说 4. 事物 Redis 事务本 ...

  3. 软件测试之loadrunner学习笔记-02集合点

    loadrunner学习笔记-02集合点 集合点函数可以帮助我们生成有效可控的并发操作.虽然在Controller中多用户负载的Vuser是一起开始运行脚本的,但是由于计算机的串行处理机制,脚本的运行 ...

  4. 【Spring学习笔记-MVC-3.1】SpringMVC返回Json数据-方式1-扩展

    <Spring学习笔记-MVC>系列文章,讲解返回json数据的文章共有3篇,分别为: [Spring学习笔记-MVC-3]SpringMVC返回Json数据-方式1:http://www ...

  5. spring学习笔记(一) Spring概述

    博主Spring学习笔记整理大部分内容来自Spring实战(第四版)这本书.  强烈建议新手购入或者需要电子书的留言. 在学习Spring之前,我们要了解这么几个问题:什么是Spring?Spring ...

  6. Java框架spring 学习笔记(十八):事务管理(xml配置文件管理)

    在Java框架spring 学习笔记(十八):事务操作中,有一个问题: package cn.service; import cn.dao.OrderDao; public class OrderSe ...

  7. Spring学习笔记2——表单数据验证、文件上传

    在上一章节Spring学习笔记1——IOC: 尽量使用注解以及java代码中,已经搭建了项目的整体框架,介绍了IOC以及mybatis.第二节主要介绍SpringMVC中的表单数据验证以及文件上传. ...

  8. 机器学习实战(Machine Learning in Action)学习笔记————02.k-邻近算法(KNN)

    机器学习实战(Machine Learning in Action)学习笔记————02.k-邻近算法(KNN) 关键字:邻近算法(kNN: k Nearest Neighbors).python.源 ...

  9. OpenCV 学习笔记 02 使用opencv处理图像

    1 不同色彩空间的转换 opencv 中有数百种关于不同色彩空间的转换方法,但常用的有三种色彩空间:灰度.BRG.HSV(Hue-Saturation-Value) 灰度 - 灰度色彩空间是通过去除彩 ...

随机推荐

  1. 成绩转换 AC 杭电

    成绩转换 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  2. MySQL 插入数据时,中文乱码???问题的解决

    在终端,mysql -u root -p 登录: show variables like 'character%'; 来查看当前数据库的相关编码集. client 为客户端使用的字符集. connec ...

  3. d008: 求两数的整数商 和 商

    内容: 求两数的整数商 和 商 ,商保留两位小数 输入说明: 一行 两个整数 输出说明: 一行,一个整数,一个实数(两位小数) 输入样例:   12 8 输出样例 : 1 1.50 #include ...

  4. block 做参数

    三部分 1,定义函数 /* 传出类定义block */ //定义block typedef void (^ItemClickBlock)(NSInteger selectedIndex); //blo ...

  5. Ubuntu12.04 下安装Chrome浏览器

    第一步 下载. 32位:https://dl.google.com/linux/direct/google-chrome-stable_current_i386.deb 64位:https://dl. ...

  6. ExpandableListView(可展开的列表组件)的说明以及其用法

    ExpandableListView的用法和ListView非常像,只是其所显示的列表项应该由ExpandableListAdapter提供,下面是它的xml属性及说明: 然而,接下来是用事实说话了: ...

  7. android数据保存

    永久保存数据的方法:1.Shared Preferences 以键值对的形式存储基本数据类型( booleans, floats, ints, longs, and strings),存储的数据在限制 ...

  8. orientationchange的兼容性

    移动webapp监测屏幕旋转时常用onorientationchange事件,用此事件获取改变后的屏幕尺寸时需要注意: 1. iphone中,可立即获取改变后的屏幕尺寸. 2. android中,获取 ...

  9. 附加、分离数据库和备份、还原数据库的区别(转载于中雪的BLOG)

    备份和恢复的概念: 备份和恢复组件是SQL Server的重要组成部分.备份就是指对SQL Server数据库及其他相关信息进行拷贝,数据库备份记录了在进行备份这一操作时数据库中所有数据的状态,如果数 ...

  10. sql server2008如何创建外键

    原文地址:http://blog.csdn.net/zuozuo1245/article/details/8644115 以前创建数据库时就是有主键的创建了主键,但是表之间的关系没有联系,要建数据库关 ...