整合 SSM 框架
文章目录
- 整合 MyBatis
- Dao 层
- Service 层
- 整合 Spring
- 整合 SpringMVC
整合 MyBatis
创建数据库
CREATE DATABASE `library`;
USE `library`;
DROP TABLE IF EXISTS `books`;
CREATE TABLE `books` (
`id` int(10) NOT NULL AUTO_INCREMENT COMMENT '书id',
`name` varchar(100) NOT NULL COMMENT '书名',
`counts` int(11) NOT NULL COMMENT '数量',
`detail` varchar(200) NOT NULL COMMENT '描述',
`price` double DEFAULT NULL COMMENT '价格',
`imagePath` varchar(200) DEFAULT NULL COMMENT '图片路径',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) DEFAULT NULL,
`password` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UNIQUE` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
创建 Maven JavaWeb 项目
Maven 导入所用 jar 包的依赖
<dependencies>
<!--Junit 单元测试依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--MySQL 数据库驱动 依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--Druid 数据库连接池 依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
<!--Servlet - JSP 依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!--Mybatis 依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<!--Spring 依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.5</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.5</version>
</dependency>
<!--Lombok 依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<!--Log4j 日志文件依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--处理 JSON 字符串依赖-->
<!--jackson-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.12.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.12.3</version>
</dependency>
<!--fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
<!--email 依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.3.8</version>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>
</dependencies>
Maven 配置静态资源导出
<!--静态资源导出-->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
Dao 层
创建 pojo 包下的实体类 Books
package pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Books {
private int id; //id
private String name; //书名
private int counts; //数量
private String detail; //描述
private double price; //价格
private String imagePath; //图片路径
public Books(String name, int counts, String detail, double price, String imagePath) {
this.name = name;
this.counts = counts;
this.detail = detail;
this.price = price;
this.imagePath = imagePath;
}
}
编写接口类 BookMapper
package dao;
import org.apache.ibatis.annotations.Param;
import pojo.Books;
import java.util.List;
public interface BookMapper {
/** * 增加一本书 * * @param books 书籍 * @return 返回-1表示失败,返回其他则表示成功 */
int addBook(Books books);
/** * 通过 id 删除书籍 * * @param id 书籍id * @return 返回-1表示失败,返回其他则表示成功 */
int deleteBookById(int id);
/** * 通过 id 修改书籍 * * @param books 书籍 * @return 返回-1表示失败,返回其他则表示成功 */
int updateBook(Books books);
/** * 根据 id 查询一本书 * * @param id 书籍id * @return 书籍 */
Books queryBookById(int id);
/** * 查询全部的书 * * @return 全部书籍的集合 */
List<Books> queryAllBooks();
/** * 根据 name 查询书籍 * * @param name 书名 * @return 书籍的集合 */
List<Books> queryBookByName(String name);
/** * 分页查询,如果 name 不为空则根据 name分页;反之,则根据全部数据分页 * * @param name 书名 * @param begin 开始 * @param size 页大小 * @return 当前页的数据 */
List<Books> limitBook(@Param("name") String name, @Param("begin") int begin, @Param("size") int size);
/** * 根据 name 模糊查询行数,如果 name 为空则查询所有行数 * * @return 行数 */
int queryRow(@Param("name") String name);
}
编写 BookMapper.xml 绑定 BookMapper 接口
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--设置 namespace 绑定 BookMapper 接口-->
<mapper namespace="dao.BookMapper">
<!--配置缓存 eviction: 定义回收的策略,常见的有 FIFO,LRU。 flushInterval: 配置一定时间自动刷新缓存,单位是毫秒。 size: 最多缓存对象的个数。 readOnly: 是否只读,若配置可读写,则需要对应的实体类能够序列化。 -->
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
<insert id="addBook" parameterType="Books">
insert into books(name, counts, detail, price, imagePath)
values (#{name}, #{counts}, #{detail}, #{price}, #{imagePath})
</insert>
<delete id="deleteBookById" parameterType="int">
delete
from books
where id = #{id}
</delete>
<update id="updateBook" parameterType="Books">
update books
set name=#{name},
counts=#{counts},
detail=#{detail},
price=#{price},
imagePath=#{imagePath}
where id = #{id}
</update>
<select id="queryBookById" resultType="Books">
select *
from books
where id = #{id}
</select>
<!--queryAllBooks 方法-->
<select id="queryAllBooks" resultType="Books">
select *
from books
</select>
<!--queryBookByName 方法-->
<select id="queryBookByName" resultType="Books">
select *
from books
where name = #{name}
</select>
<!--queryRow 方法 SQL:select count(*) from books 如果 name !=null and name !='' 时 SQL:select count(*) from books where name like "%"#{name}"%" -->
<select id="queryRow" resultType="_int">
select count(*) from books
<where>
<if test=" name !=null and name !=''">
name like "%"#{name}"%"
</if>
</where>
</select>
<!--limitBook 方法 SQL:select * from books limit #{begin}, #{size} 如果 name !=null and name !='' 时 SQL:select * from books where name like "%"#{name}"%" limit #{begin}, #{size} -->
<select id="limitBook" resultType="Books">
select *
from books
<where>
<if test=" name !=null and name !=''">
name like "%"#{name}"%"
</if>
</where>
limit #{begin}, #{size}
</select>
</mapper>
编写 mybatis-config.xml 文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--设置日志 log4j,开启二级缓存-->
<settings>
<setting name="logImpl" value="LOG4J"/>
<setting name="cacheEnabled" value="true"/>
</settings>
<!--设置 pojo 包下的别名-->
<typeAliases>
<package name="pojo"/>
</typeAliases>
<!--注册绑定 Mapper-->
<mappers>
<mapper class="dao.BookMapper"/>
</mappers>
</configuration>
这里 mybatis 日志决定采用 log4j,从网上找了一个实现只保留7天日志的的方法,需要自定义类继承 FileAppender 类进行扩展
编写工具类 MyDailyRollingFileAppender
package utils;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Layout;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.spi.LoggingEvent;
/** * Log4j的扩展-保留最近指定个数的日志文件 */
public class MyDailyRollingFileAppender extends FileAppender {
static final int TOP_OF_TROUBLE = -1;
static final int TOP_OF_MINUTE = 0;
static final int TOP_OF_HOUR = 1;
static final int HALF_DAY = 2;
static final int TOP_OF_DAY = 3;
static final int TOP_OF_WEEK = 4;
static final int TOP_OF_MONTH = 5;
/** * 默认设置:"'.'yyyy-MM-dd" * 设置说明:按天循环打印日志 */
private String datePattern = "'.'yyyy-MM-dd";
private int maxBackupIndex = 1;
private String scheduledFilename;
/** * 下一次Rolling日志文件的时间 */
private long nextCheck = System.currentTimeMillis() - 1;
Date now = new Date();
SimpleDateFormat sdf;
RollingCalendar rc = new RollingCalendar();
int checkPeriod = TOP_OF_TROUBLE;
/** * 获取当前环境所处的时区 * 仅供computeCheckPeriod方法使用 */
static final TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT");
public MyDailyRollingFileAppender() {
}
public MyDailyRollingFileAppender(Layout layout, String filename, String datePattern) throws IOException {
super(layout, filename, true);
this.datePattern = datePattern;
activateOptions();
}
public String getDatePattern() {
return datePattern;
}
public void setDatePattern(String pattern) {
this.datePattern = pattern;
}
public int getMaxBackupIndex() {
return maxBackupIndex;
}
public void setMaxBackupIndex(int maxBackupIndex) {
this.maxBackupIndex = maxBackupIndex;
}
/** * activateOptions译名为激活操作 * 意思是按照配置的参数进行初始化 * scheduledFilename为log的最后一次修改时间 */
@Override
public void activateOptions() {
super.activateOptions();
if (datePattern != null && fileName != null) {
now.setTime(System.currentTimeMillis());
sdf = new SimpleDateFormat(datePattern);
int type = computeCheckPeriod();
printPeriodicity(type);
rc.setType(type);
File file = new File(fileName);
scheduledFilename = fileName + sdf.format(new Date(file.lastModified()));
} else {
LogLog.error("Either File or DatePattern options are not set for appender [" + name + "].");
}
}
int computeCheckPeriod() {
RollingCalendar rollingCalendar = new RollingCalendar(gmtTimeZone, Locale.getDefault());
//设置初始时间为格林尼治时间:1970-01-01 00:00:00 GMT
Date epoch = new Date(0);
if (datePattern != null) {
for (int i = TOP_OF_MINUTE; i <= TOP_OF_MONTH; i++) {
//将所示的时间格式化为当前时区
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern);
simpleDateFormat.setTimeZone(gmtTimeZone);
String r0 = simpleDateFormat.format(epoch);
rollingCalendar.setType(i);
Date next = new Date(rollingCalendar.getNextCheckMillis(epoch));
String r1 = simpleDateFormat.format(next);
//System.out.println("Type = "+i+", r0 = "+r0+", r1 = "+r1);
if (r0 != null && r1 != null && !r0.equals(r1)) {
return i;
}
}
}
return TOP_OF_TROUBLE; // Deliberately head for trouble...
}
/** * 按照周期将当前日志文件转存为日期文件 * * @throws IOException */
void rollOver() throws IOException {
if (datePattern == null) {
errorHandler.error("Missing DatePattern option in rollOver().");
return;
}
String datedFilename = fileName + sdf.format(now);
//如果最后一次的修改时间为当前时间 ,则不做任何任何操作
if (scheduledFilename.equals(datedFilename)) {
return;
}
// 关闭当前文件,重命名为日期文件
this.closeFile();
File target = new File(scheduledFilename);
if (target.exists()) {
target.delete();
}
File file = new File(fileName);
boolean result = file.renameTo(target);
if (result) {
LogLog.debug(fileName + " -> " + scheduledFilename);
} else {
LogLog.error("Failed to rename [" + fileName + "] to [" + scheduledFilename + "].");
}
//获取日志文件列表,控制数量,实现清理策略
if (file.getParentFile().exists()) {
File[] files = file.getParentFile().listFiles(new LogFileFilter(file.getName()));
Long[] dateArray = new Long[files.length];
for (int i = 0; i < files.length; i++) {
File fileItem = files[i];
String fileDateStr = fileItem.getName().replace(file.getName(), "");
Date filedate = null;
try {
filedate = sdf.parse(fileDateStr);
long fileDateLong = filedate.getTime();
dateArray[i] = fileDateLong;
} catch (ParseException e) {
LogLog.error("Parse File Date Throw Exception : " + e.getMessage());
}
}
Arrays.sort(dateArray);
if (dateArray.length > maxBackupIndex) { //需要清理多余日志文件了
for (int i = 0; i < dateArray.length - maxBackupIndex; i++) {
String dateFileName = file.getPath() + sdf.format(dateArray[i]);
File dateFile = new File(dateFileName);
if (dateFile.exists()) {
dateFile.delete();
}
}
}
}
try {
this.setFile(fileName, true, this.bufferedIO, this.bufferSize);
} catch (IOException e) {
errorHandler.error("setFile(" + fileName + ", true) call failed.");
}
scheduledFilename = datedFilename;
}
/** * 写入日志之前判断是否需要新起一个日志来记录 */
@Override
protected void subAppend(LoggingEvent event) {
long n = System.currentTimeMillis();
if (n >= nextCheck) {
now.setTime(n);
nextCheck = rc.getNextCheckMillis(now);
try {
rollOver();
} catch (IOException ioe) {
if (ioe instanceof InterruptedIOException) {
Thread.currentThread().interrupt();
}
LogLog.error("rollOver() failed.", ioe);
}
}
super.subAppend(event);
}
/** * 文件过滤器 */
class LogFileFilter implements FileFilter {
private String logName;
public LogFileFilter(String logName) {
this.logName = logName;
}
@Override
public boolean accept(File file) {
if (logName == null || file.isDirectory()) {
return false;
} else {
LogLog.debug(file.getName());
return file.getName().startsWith(logName);
}
}
}
/** * 根据type打印做出日志打印 * * @param type */
void printPeriodicity(int type) {
switch (type) {
case TOP_OF_MINUTE:
LogLog.debug("Appender [" + name + "] to be rolled every minute.");
break;
case TOP_OF_HOUR:
LogLog.debug("Appender [" + name + "] to be rolled on top of every hour.");
break;
case HALF_DAY:
LogLog.debug("Appender [" + name + "] to be rolled at midday and midnight.");
break;
case TOP_OF_DAY:
LogLog.debug("Appender [" + name + "] to be rolled at midnight.");
break;
case TOP_OF_WEEK:
LogLog.debug("Appender [" + name + "] to be rolled at start of week.");
break;
case TOP_OF_MONTH:
LogLog.debug("Appender [" + name + "] to be rolled at start of every month.");
break;
default:
LogLog.warn("Unknown periodicity for appender [" + name + "].");
}
}
/** * 内部类 * * @author 日志Rolling日历, 获取下一次日志Rolling时间 */
class RollingCalendar extends GregorianCalendar {
private static final long serialVersionUID = -3560331770601814177L;
int type = MyDailyRollingFileAppender.TOP_OF_TROUBLE;
/** * RollingCalendar默认构造器 */
RollingCalendar() {
super();
}
/** * RollingCalendar构造器 * 根据地点时区 ,获取对应的日历Calendar * * @param tz * @param locale */
RollingCalendar(TimeZone tz, Locale locale) {
super(tz, locale);
}
void setType(int type) {
this.type = type;
}
public long getNextCheckMillis(Date now) {
return getNextCheckDate(now).getTime();
}
/** * 根据所传入的时间以及时间类型获取下一个时间 * * @param now * @return */
public Date getNextCheckDate(Date now) {
this.setTime(now);
switch (type) {
case MyDailyRollingFileAppender.TOP_OF_MINUTE:
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.MINUTE, 1);
break;
case MyDailyRollingFileAppender.TOP_OF_HOUR:
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.HOUR_OF_DAY, 1);
break;
case MyDailyRollingFileAppender.HALF_DAY:
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
int hour = get(Calendar.HOUR_OF_DAY);
if (hour < 12) {
this.set(Calendar.HOUR_OF_DAY, 12);
} else {
this.set(Calendar.HOUR_OF_DAY, 0);
this.add(Calendar.DAY_OF_MONTH, 1);
}
break;
case MyDailyRollingFileAppender.TOP_OF_DAY:
this.set(Calendar.HOUR_OF_DAY, 0);
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.DATE, 1);
break;
case MyDailyRollingFileAppender.TOP_OF_WEEK:
this.set(Calendar.DAY_OF_WEEK, getFirstDayOfWeek());
this.set(Calendar.HOUR_OF_DAY, 0);
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.WEEK_OF_YEAR, 1);
break;
case MyDailyRollingFileAppender.TOP_OF_MONTH:
this.set(Calendar.DATE, 1);
this.set(Calendar.HOUR_OF_DAY, 0);
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.MONTH, 1);
break;
default:
throw new IllegalStateException("Unknown periodicity type.");
}
return getTime();
}
}
}
编写 log4j.porperties 对 log4j 进行配置
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file
#控制台输出的相关设置
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target=System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
#文件输出的相关设置
log4j.appender.file=utils.MyDailyRollingFileAppender
#日志文件路径
log4j.appender.file.File=./logs/log.log
log4j.appender.file.Encoding=utf-8
log4j.appender.file.Append=true
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
#设置日志文件名为日期并按天生成日志文件
log4j.appender.file.datePattern='.'yyyy-MM-dd
#保留7天的日志文件
log4j.appender.file.maxBackupIndex=7
log4j.appender.file.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss,SSS}][%c]%m%n
#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
配置好之后,在进行单元测试的时候就可以查看输出的日志文件
Service 层
Service 层调用 Dao 层提供的方法
1、编写接口 BookService
package service;
import pojo.Books;
import java.awt.print.Book;
import java.util.List;
public interface BookService {
/** * 增加一本书 * * @param books 书籍 * @return 返回-1表示失败,返回其他则表示成功 */
int addBook(Books books);
/** * 通过 id 删除书籍 * * @param id 书籍id * @return 返回-1表示失败,返回其他则表示成功 */
int deleteBookById(int id);
/** * 通过 id 修改书籍 * * @param books 书籍 * @return 返回-1表示失败,返回其他则表示成功 */
int updateBook(Books books);
/** * 根据 id 查询一本书 * * @param id 书籍id * @return 书籍 */
Books queryBookById(int id);
/** * 查询全部的书 * * @return 全部书籍的集合 */
List<Books> queryAllBooks();
/** * 根据 name 查询书籍 * * @param name 书名 * @return 书籍的集合 */
List<Books> queryBookByName(String name);
/** * 分页查询,如果 name 不为空则根据 name分页;反之,则根据全部数据分页 * * @param name 书名 * @param begin 开始 * @param size 页大小 * @return 当前页的数据 */
List<Books> limitBook(String name, int begin, int size);
/** * 根据 name 模糊查询行数,如果 name 为空则查询所有行数 * * @return 行数 */
int queryRow(String name);
}
2、编写接口 BookService 实现类 BookServiceImpl
package service;
import dao.BookMapper;
import pojo.Books;
import java.util.List;
public class BookServiceImpl implements BookService {
/** * service 层调用 Dao层 */
private BookMapper bookMapper;
public void setBookMapper(BookMapper bookMapper) {
this.bookMapper = bookMapper;
}
@Override
public int addBook(Books books) {
return bookMapper.addBook(books);
}
@Override
public int deleteBookById(int id) {
return bookMapper.deleteBookById(id);
}
@Override
public int updateBook(Books books) {
return bookMapper.updateBook(books);
}
@Override
public Books queryBookById(int id) {
return bookMapper.queryBookById(id);
}
@Override
public List<Books> queryAllBooks() {
return bookMapper.queryAllBooks();
}
@Override
public List<Books> queryBookByName(String name) {
return bookMapper.queryBookByName(name);
}
@Override
public int queryRow(String name) {
return bookMapper.queryRow(name);
}
@Override
public List<Books> limitBook(String name, int begin, int size) {
return bookMapper.limitBook(name, begin, size);
}
}
整合 Spring
编写 jdbc.properties 配置文件
url=jdbc:mysql://localhost:3306/library?useUnicode=true&characterEncoding=utf8&useSSL=false
driver=com.mysql.jdbc.Driver
user=root
password=123456
注:MySQL 8.0版本之后 url 需要配置时区 serverTimezone=GMT%2B8
spring-dao.xml 对 Dao 进行整合
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--关联数据库配置文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--Druid 数据库连接池配置-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close" init-method="init">
<!-- 基本属性driverClassName、 url、username、password -->
<property name="driverClassName" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${user}"/>
<property name="password" value="${password}"/>
<!-- 配置初始化大小、最小、最大、获取连接等待超时的时间、连接在池中最小生存的时间 -->
<property name="initialSize" value="2"/>
<property name="minIdle" value="5"/>
<property name="maxActive" value="50"/>
<property name="maxWait" value="5000"/>
<property name="minEvictableIdleTimeMillis" value="30000"/>
</bean>
<!--sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!--绑定 Mybatis 配置文件-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
<!--配置 dao 接口扫描包,动态实现 Dao 接口注入 Spring 容器中-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--注入 sqlSessionFactory-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!--扫描 dao 包-->
<property name="basePackage" value="dao"/>
</bean>
</beans>
spring-service.xml 对 Service 进行整合
<?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: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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--扫描 service 下的包-->
<context:component-scan base-package="service"/>
<!--将所有业务类注入到 Spring ,可以通过配置或注解实现-->
<bean id="bookServiceImpl" class="service.BookServiceImpl">
<property name="bookMapper" ref="bookMapper"/>
</bean>
<!--声明式事务配置-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--事务支持-->
<!--给所有方法配置事务-->
<!--配置事务的传播特性:new propagation-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--aop配置事务切入-->
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* dao.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
</beans>
整合 SpringMVC
1、配置 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0">
<!--DispatcherServlet-->
<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.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 乱码过滤 -->
<filter>
<filter-name>encoding</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>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--Session-->
<session-config>
<session-timeout>15</session-timeout>
</session-config>
<!--欢迎页面-->
<welcome-file-list>
<welcome-file>/WEB-INF/jsp/index.jsp</welcome-file>
</welcome-file-list>
<!--错误页面-->
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/jsp/404.jsp</location>
</error-page>
</web-app>
2、配置 springmvc.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 https://www.springframework.org/schema/context/spring-context.xsd">
<!--注解驱动-->
<mvc:annotation-driven/>
<!--静态资源过滤-->
<mvc:default-servlet-handler/>
<!--扫描包:controller-->
<context:component-scan base-package="controller"/>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 注解请求映射 默认是ISO-88859-1,避免乱码这里设置为UTF-8 -->
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes" value="text/html;charset=UTF-8"/>
</bean>
<!-- 启动JSON格式的配置,自动将格式转换成JSON格式,不需要其他类 -->
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes" value="application/json;charset=UTF-8"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
</beans>
3、配置 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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="spring-dao.xml"/>
<import resource="spring-service.xml"/>
<import resource="spring-mvc.xml"/>
</beans>
一个基本的SSM框架就搭建好了,可以再其上添加业务了
还没有评论,来说两句吧...