整合 SSM 框架

Bertha 。 2022-08-30 15:58 421阅读 0赞

文章目录

  • 整合 MyBatis
    • Dao 层
    • Service 层
  • 整合 Spring
  • 整合 SpringMVC

整合 MyBatis

创建数据库

  1. CREATE DATABASE `library`;
  2. USE `library`;
  3. DROP TABLE IF EXISTS `books`;
  4. CREATE TABLE `books` (
  5. `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '书id',
  6. `name` varchar(100) NOT NULL COMMENT '书名',
  7. `counts` int(11) NOT NULL COMMENT '数量',
  8. `detail` varchar(200) NOT NULL COMMENT '描述',
  9. `price` double DEFAULT NULL COMMENT '价格',
  10. `imagePath` varchar(200) DEFAULT NULL COMMENT '图片路径',
  11. PRIMARY KEY (`id`)
  12. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  13. DROP TABLE IF EXISTS `users`;
  14. CREATE TABLE `users` (
  15. `id` int(11) NOT NULL AUTO_INCREMENT,
  16. `name` varchar(30) DEFAULT NULL,
  17. `password` varchar(30) DEFAULT NULL,
  18. PRIMARY KEY (`id`),
  19. UNIQUE KEY `UNIQUE` (`name`)
  20. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

创建 Maven JavaWeb 项目

Maven 导入所用 jar 包的依赖

  1. <dependencies>
  2. <!--Junit 单元测试依赖-->
  3. <dependency>
  4. <groupId>junit</groupId>
  5. <artifactId>junit</artifactId>
  6. <version>4.12</version>
  7. </dependency>
  8. <!--MySQL 数据库驱动 依赖-->
  9. <dependency>
  10. <groupId>mysql</groupId>
  11. <artifactId>mysql-connector-java</artifactId>
  12. <version>5.1.47</version>
  13. </dependency>
  14. <!--Druid 数据库连接池 依赖-->
  15. <dependency>
  16. <groupId>com.alibaba</groupId>
  17. <artifactId>druid</artifactId>
  18. <version>1.2.6</version>
  19. </dependency>
  20. <dependency>
  21. <groupId>org.aspectj</groupId>
  22. <artifactId>aspectjweaver</artifactId>
  23. <version>1.9.6</version>
  24. </dependency>
  25. <!--Servlet - JSP 依赖 -->
  26. <dependency>
  27. <groupId>javax.servlet</groupId>
  28. <artifactId>servlet-api</artifactId>
  29. <version>2.5</version>
  30. </dependency>
  31. <dependency>
  32. <groupId>javax.servlet.jsp</groupId>
  33. <artifactId>jsp-api</artifactId>
  34. <version>2.2</version>
  35. </dependency>
  36. <dependency>
  37. <groupId>javax.servlet</groupId>
  38. <artifactId>jstl</artifactId>
  39. <version>1.2</version>
  40. </dependency>
  41. <!--Mybatis 依赖-->
  42. <dependency>
  43. <groupId>org.mybatis</groupId>
  44. <artifactId>mybatis</artifactId>
  45. <version>3.5.6</version>
  46. </dependency>
  47. <dependency>
  48. <groupId>org.mybatis</groupId>
  49. <artifactId>mybatis-spring</artifactId>
  50. <version>2.0.6</version>
  51. </dependency>
  52. <!--Spring 依赖-->
  53. <dependency>
  54. <groupId>org.springframework</groupId>
  55. <artifactId>spring-webmvc</artifactId>
  56. <version>5.3.5</version>
  57. </dependency>
  58. <dependency>
  59. <groupId>org.springframework</groupId>
  60. <artifactId>spring-jdbc</artifactId>
  61. <version>5.3.5</version>
  62. </dependency>
  63. <!--Lombok 依赖-->
  64. <dependency>
  65. <groupId>org.projectlombok</groupId>
  66. <artifactId>lombok</artifactId>
  67. <version>1.18.12</version>
  68. </dependency>
  69. <!--Log4j 日志文件依赖-->
  70. <dependency>
  71. <groupId>log4j</groupId>
  72. <artifactId>log4j</artifactId>
  73. <version>1.2.17</version>
  74. </dependency>
  75. <!--处理 JSON 字符串依赖-->
  76. <!--jackson-->
  77. <dependency>
  78. <groupId>com.fasterxml.jackson.core</groupId>
  79. <artifactId>jackson-core</artifactId>
  80. <version>2.12.3</version>
  81. </dependency>
  82. <dependency>
  83. <groupId>com.fasterxml.jackson.core</groupId>
  84. <artifactId>jackson-databind</artifactId>
  85. <version>2.12.3</version>
  86. </dependency>
  87. <dependency>
  88. <groupId>com.fasterxml.jackson.core</groupId>
  89. <artifactId>jackson-annotations</artifactId>
  90. <version>2.12.3</version>
  91. </dependency>
  92. <!--fastjson -->
  93. <dependency>
  94. <groupId>com.alibaba</groupId>
  95. <artifactId>fastjson</artifactId>
  96. <version>1.2.75</version>
  97. </dependency>
  98. <!--email 依赖 -->
  99. <dependency>
  100. <groupId>org.springframework</groupId>
  101. <artifactId>spring-context-support</artifactId>
  102. <version>5.3.8</version>
  103. </dependency>
  104. <dependency>
  105. <groupId>javax.mail</groupId>
  106. <artifactId>mail</artifactId>
  107. <version>1.4.7</version>
  108. </dependency>
  109. </dependencies>

Maven 配置静态资源导出

  1. <!--静态资源导出-->
  2. <build>
  3. <resources>
  4. <resource>
  5. <directory>src/main/java</directory>
  6. <includes>
  7. <include>**/*.properties</include>
  8. <include>**/*.xml</include>
  9. </includes>
  10. <filtering>false</filtering>
  11. </resource>
  12. <resource>
  13. <directory>src/main/resources</directory>
  14. <includes>
  15. <include>**/*.properties</include>
  16. <include>**/*.xml</include>
  17. </includes>
  18. <filtering>false</filtering>
  19. </resource>
  20. </resources>
  21. </build>

Dao 层

创建 pojo 包下的实体类 Books

  1. package pojo;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Data;
  4. import lombok.NoArgsConstructor;
  5. @Data
  6. @AllArgsConstructor
  7. @NoArgsConstructor
  8. public class Books {
  9. private int id; //id
  10. private String name; //书名
  11. private int counts; //数量
  12. private String detail; //描述
  13. private double price; //价格
  14. private String imagePath; //图片路径
  15. public Books(String name, int counts, String detail, double price, String imagePath) {
  16. this.name = name;
  17. this.counts = counts;
  18. this.detail = detail;
  19. this.price = price;
  20. this.imagePath = imagePath;
  21. }
  22. }

编写接口类 BookMapper

  1. package dao;
  2. import org.apache.ibatis.annotations.Param;
  3. import pojo.Books;
  4. import java.util.List;
  5. public interface BookMapper {
  6. /** * 增加一本书 * * @param books 书籍 * @return 返回-1表示失败,返回其他则表示成功 */
  7. int addBook(Books books);
  8. /** * 通过 id 删除书籍 * * @param id 书籍id * @return 返回-1表示失败,返回其他则表示成功 */
  9. int deleteBookById(int id);
  10. /** * 通过 id 修改书籍 * * @param books 书籍 * @return 返回-1表示失败,返回其他则表示成功 */
  11. int updateBook(Books books);
  12. /** * 根据 id 查询一本书 * * @param id 书籍id * @return 书籍 */
  13. Books queryBookById(int id);
  14. /** * 查询全部的书 * * @return 全部书籍的集合 */
  15. List<Books> queryAllBooks();
  16. /** * 根据 name 查询书籍 * * @param name 书名 * @return 书籍的集合 */
  17. List<Books> queryBookByName(String name);
  18. /** * 分页查询,如果 name 不为空则根据 name分页;反之,则根据全部数据分页 * * @param name 书名 * @param begin 开始 * @param size 页大小 * @return 当前页的数据 */
  19. List<Books> limitBook(@Param("name") String name, @Param("begin") int begin, @Param("size") int size);
  20. /** * 根据 name 模糊查询行数,如果 name 为空则查询所有行数 * * @return 行数 */
  21. int queryRow(@Param("name") String name);
  22. }

编写 BookMapper.xml 绑定 BookMapper 接口

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3. <!--设置 namespace 绑定 BookMapper 接口-->
  4. <mapper namespace="dao.BookMapper">
  5. <!--配置缓存 eviction: 定义回收的策略,常见的有 FIFO,LRU。 flushInterval: 配置一定时间自动刷新缓存,单位是毫秒。 size: 最多缓存对象的个数。 readOnly: 是否只读,若配置可读写,则需要对应的实体类能够序列化。 -->
  6. <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
  7. <insert id="addBook" parameterType="Books">
  8. insert into books(name, counts, detail, price, imagePath)
  9. values (#{name}, #{counts}, #{detail}, #{price}, #{imagePath})
  10. </insert>
  11. <delete id="deleteBookById" parameterType="int">
  12. delete
  13. from books
  14. where id = #{id}
  15. </delete>
  16. <update id="updateBook" parameterType="Books">
  17. update books
  18. set name=#{name},
  19. counts=#{counts},
  20. detail=#{detail},
  21. price=#{price},
  22. imagePath=#{imagePath}
  23. where id = #{id}
  24. </update>
  25. <select id="queryBookById" resultType="Books">
  26. select *
  27. from books
  28. where id = #{id}
  29. </select>
  30. <!--queryAllBooks 方法-->
  31. <select id="queryAllBooks" resultType="Books">
  32. select *
  33. from books
  34. </select>
  35. <!--queryBookByName 方法-->
  36. <select id="queryBookByName" resultType="Books">
  37. select *
  38. from books
  39. where name = #{name}
  40. </select>
  41. <!--queryRow 方法 SQL:select count(*) from books 如果 name !=null and name !='' 时 SQL:select count(*) from books where name like "%"#{name}"%" -->
  42. <select id="queryRow" resultType="_int">
  43. select count(*) from books
  44. <where>
  45. <if test=" name !=null and name !=''">
  46. name like "%"#{name}"%"
  47. </if>
  48. </where>
  49. </select>
  50. <!--limitBook 方法 SQL:select * from books limit #{begin}, #{size} 如果 name !=null and name !='' 时 SQL:select * from books where name like "%"#{name}"%" limit #{begin}, #{size} -->
  51. <select id="limitBook" resultType="Books">
  52. select *
  53. from books
  54. <where>
  55. <if test=" name !=null and name !=''">
  56. name like "%"#{name}"%"
  57. </if>
  58. </where>
  59. limit #{begin}, #{size}
  60. </select>
  61. </mapper>

编写 mybatis-config.xml 文件

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
  3. <configuration>
  4. <!--设置日志 log4j,开启二级缓存-->
  5. <settings>
  6. <setting name="logImpl" value="LOG4J"/>
  7. <setting name="cacheEnabled" value="true"/>
  8. </settings>
  9. <!--设置 pojo 包下的别名-->
  10. <typeAliases>
  11. <package name="pojo"/>
  12. </typeAliases>
  13. <!--注册绑定 Mapper-->
  14. <mappers>
  15. <mapper class="dao.BookMapper"/>
  16. </mappers>
  17. </configuration>

这里 mybatis 日志决定采用 log4j,从网上找了一个实现只保留7天日志的的方法,需要自定义类继承 FileAppender 类进行扩展

编写工具类 MyDailyRollingFileAppender

  1. package utils;
  2. import java.io.File;
  3. import java.io.FileFilter;
  4. import java.io.IOException;
  5. import java.io.InterruptedIOException;
  6. import java.text.ParseException;
  7. import java.text.SimpleDateFormat;
  8. import java.util.Arrays;
  9. import java.util.Calendar;
  10. import java.util.Date;
  11. import java.util.GregorianCalendar;
  12. import java.util.Locale;
  13. import java.util.TimeZone;
  14. import org.apache.log4j.FileAppender;
  15. import org.apache.log4j.Layout;
  16. import org.apache.log4j.helpers.LogLog;
  17. import org.apache.log4j.spi.LoggingEvent;
  18. /** * Log4j的扩展-保留最近指定个数的日志文件 */
  19. public class MyDailyRollingFileAppender extends FileAppender {
  20. static final int TOP_OF_TROUBLE = -1;
  21. static final int TOP_OF_MINUTE = 0;
  22. static final int TOP_OF_HOUR = 1;
  23. static final int HALF_DAY = 2;
  24. static final int TOP_OF_DAY = 3;
  25. static final int TOP_OF_WEEK = 4;
  26. static final int TOP_OF_MONTH = 5;
  27. /** * 默认设置:"'.'yyyy-MM-dd" * 设置说明:按天循环打印日志 */
  28. private String datePattern = "'.'yyyy-MM-dd";
  29. private int maxBackupIndex = 1;
  30. private String scheduledFilename;
  31. /** * 下一次Rolling日志文件的时间 */
  32. private long nextCheck = System.currentTimeMillis() - 1;
  33. Date now = new Date();
  34. SimpleDateFormat sdf;
  35. RollingCalendar rc = new RollingCalendar();
  36. int checkPeriod = TOP_OF_TROUBLE;
  37. /** * 获取当前环境所处的时区 * 仅供computeCheckPeriod方法使用 */
  38. static final TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT");
  39. public MyDailyRollingFileAppender() {
  40. }
  41. public MyDailyRollingFileAppender(Layout layout, String filename, String datePattern) throws IOException {
  42. super(layout, filename, true);
  43. this.datePattern = datePattern;
  44. activateOptions();
  45. }
  46. public String getDatePattern() {
  47. return datePattern;
  48. }
  49. public void setDatePattern(String pattern) {
  50. this.datePattern = pattern;
  51. }
  52. public int getMaxBackupIndex() {
  53. return maxBackupIndex;
  54. }
  55. public void setMaxBackupIndex(int maxBackupIndex) {
  56. this.maxBackupIndex = maxBackupIndex;
  57. }
  58. /** * activateOptions译名为激活操作 * 意思是按照配置的参数进行初始化 * scheduledFilename为log的最后一次修改时间 */
  59. @Override
  60. public void activateOptions() {
  61. super.activateOptions();
  62. if (datePattern != null && fileName != null) {
  63. now.setTime(System.currentTimeMillis());
  64. sdf = new SimpleDateFormat(datePattern);
  65. int type = computeCheckPeriod();
  66. printPeriodicity(type);
  67. rc.setType(type);
  68. File file = new File(fileName);
  69. scheduledFilename = fileName + sdf.format(new Date(file.lastModified()));
  70. } else {
  71. LogLog.error("Either File or DatePattern options are not set for appender [" + name + "].");
  72. }
  73. }
  74. int computeCheckPeriod() {
  75. RollingCalendar rollingCalendar = new RollingCalendar(gmtTimeZone, Locale.getDefault());
  76. //设置初始时间为格林尼治时间:1970-01-01 00:00:00 GMT
  77. Date epoch = new Date(0);
  78. if (datePattern != null) {
  79. for (int i = TOP_OF_MINUTE; i <= TOP_OF_MONTH; i++) {
  80. //将所示的时间格式化为当前时区
  81. SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern);
  82. simpleDateFormat.setTimeZone(gmtTimeZone);
  83. String r0 = simpleDateFormat.format(epoch);
  84. rollingCalendar.setType(i);
  85. Date next = new Date(rollingCalendar.getNextCheckMillis(epoch));
  86. String r1 = simpleDateFormat.format(next);
  87. //System.out.println("Type = "+i+", r0 = "+r0+", r1 = "+r1);
  88. if (r0 != null && r1 != null && !r0.equals(r1)) {
  89. return i;
  90. }
  91. }
  92. }
  93. return TOP_OF_TROUBLE; // Deliberately head for trouble...
  94. }
  95. /** * 按照周期将当前日志文件转存为日期文件 * * @throws IOException */
  96. void rollOver() throws IOException {
  97. if (datePattern == null) {
  98. errorHandler.error("Missing DatePattern option in rollOver().");
  99. return;
  100. }
  101. String datedFilename = fileName + sdf.format(now);
  102. //如果最后一次的修改时间为当前时间 ,则不做任何任何操作
  103. if (scheduledFilename.equals(datedFilename)) {
  104. return;
  105. }
  106. // 关闭当前文件,重命名为日期文件
  107. this.closeFile();
  108. File target = new File(scheduledFilename);
  109. if (target.exists()) {
  110. target.delete();
  111. }
  112. File file = new File(fileName);
  113. boolean result = file.renameTo(target);
  114. if (result) {
  115. LogLog.debug(fileName + " -> " + scheduledFilename);
  116. } else {
  117. LogLog.error("Failed to rename [" + fileName + "] to [" + scheduledFilename + "].");
  118. }
  119. //获取日志文件列表,控制数量,实现清理策略
  120. if (file.getParentFile().exists()) {
  121. File[] files = file.getParentFile().listFiles(new LogFileFilter(file.getName()));
  122. Long[] dateArray = new Long[files.length];
  123. for (int i = 0; i < files.length; i++) {
  124. File fileItem = files[i];
  125. String fileDateStr = fileItem.getName().replace(file.getName(), "");
  126. Date filedate = null;
  127. try {
  128. filedate = sdf.parse(fileDateStr);
  129. long fileDateLong = filedate.getTime();
  130. dateArray[i] = fileDateLong;
  131. } catch (ParseException e) {
  132. LogLog.error("Parse File Date Throw Exception : " + e.getMessage());
  133. }
  134. }
  135. Arrays.sort(dateArray);
  136. if (dateArray.length > maxBackupIndex) { //需要清理多余日志文件了
  137. for (int i = 0; i < dateArray.length - maxBackupIndex; i++) {
  138. String dateFileName = file.getPath() + sdf.format(dateArray[i]);
  139. File dateFile = new File(dateFileName);
  140. if (dateFile.exists()) {
  141. dateFile.delete();
  142. }
  143. }
  144. }
  145. }
  146. try {
  147. this.setFile(fileName, true, this.bufferedIO, this.bufferSize);
  148. } catch (IOException e) {
  149. errorHandler.error("setFile(" + fileName + ", true) call failed.");
  150. }
  151. scheduledFilename = datedFilename;
  152. }
  153. /** * 写入日志之前判断是否需要新起一个日志来记录 */
  154. @Override
  155. protected void subAppend(LoggingEvent event) {
  156. long n = System.currentTimeMillis();
  157. if (n >= nextCheck) {
  158. now.setTime(n);
  159. nextCheck = rc.getNextCheckMillis(now);
  160. try {
  161. rollOver();
  162. } catch (IOException ioe) {
  163. if (ioe instanceof InterruptedIOException) {
  164. Thread.currentThread().interrupt();
  165. }
  166. LogLog.error("rollOver() failed.", ioe);
  167. }
  168. }
  169. super.subAppend(event);
  170. }
  171. /** * 文件过滤器 */
  172. class LogFileFilter implements FileFilter {
  173. private String logName;
  174. public LogFileFilter(String logName) {
  175. this.logName = logName;
  176. }
  177. @Override
  178. public boolean accept(File file) {
  179. if (logName == null || file.isDirectory()) {
  180. return false;
  181. } else {
  182. LogLog.debug(file.getName());
  183. return file.getName().startsWith(logName);
  184. }
  185. }
  186. }
  187. /** * 根据type打印做出日志打印 * * @param type */
  188. void printPeriodicity(int type) {
  189. switch (type) {
  190. case TOP_OF_MINUTE:
  191. LogLog.debug("Appender [" + name + "] to be rolled every minute.");
  192. break;
  193. case TOP_OF_HOUR:
  194. LogLog.debug("Appender [" + name + "] to be rolled on top of every hour.");
  195. break;
  196. case HALF_DAY:
  197. LogLog.debug("Appender [" + name + "] to be rolled at midday and midnight.");
  198. break;
  199. case TOP_OF_DAY:
  200. LogLog.debug("Appender [" + name + "] to be rolled at midnight.");
  201. break;
  202. case TOP_OF_WEEK:
  203. LogLog.debug("Appender [" + name + "] to be rolled at start of week.");
  204. break;
  205. case TOP_OF_MONTH:
  206. LogLog.debug("Appender [" + name + "] to be rolled at start of every month.");
  207. break;
  208. default:
  209. LogLog.warn("Unknown periodicity for appender [" + name + "].");
  210. }
  211. }
  212. /** * 内部类 * * @author 日志Rolling日历, 获取下一次日志Rolling时间 */
  213. class RollingCalendar extends GregorianCalendar {
  214. private static final long serialVersionUID = -3560331770601814177L;
  215. int type = MyDailyRollingFileAppender.TOP_OF_TROUBLE;
  216. /** * RollingCalendar默认构造器 */
  217. RollingCalendar() {
  218. super();
  219. }
  220. /** * RollingCalendar构造器 * 根据地点时区 ,获取对应的日历Calendar * * @param tz * @param locale */
  221. RollingCalendar(TimeZone tz, Locale locale) {
  222. super(tz, locale);
  223. }
  224. void setType(int type) {
  225. this.type = type;
  226. }
  227. public long getNextCheckMillis(Date now) {
  228. return getNextCheckDate(now).getTime();
  229. }
  230. /** * 根据所传入的时间以及时间类型获取下一个时间 * * @param now * @return */
  231. public Date getNextCheckDate(Date now) {
  232. this.setTime(now);
  233. switch (type) {
  234. case MyDailyRollingFileAppender.TOP_OF_MINUTE:
  235. this.set(Calendar.SECOND, 0);
  236. this.set(Calendar.MILLISECOND, 0);
  237. this.add(Calendar.MINUTE, 1);
  238. break;
  239. case MyDailyRollingFileAppender.TOP_OF_HOUR:
  240. this.set(Calendar.MINUTE, 0);
  241. this.set(Calendar.SECOND, 0);
  242. this.set(Calendar.MILLISECOND, 0);
  243. this.add(Calendar.HOUR_OF_DAY, 1);
  244. break;
  245. case MyDailyRollingFileAppender.HALF_DAY:
  246. this.set(Calendar.MINUTE, 0);
  247. this.set(Calendar.SECOND, 0);
  248. this.set(Calendar.MILLISECOND, 0);
  249. int hour = get(Calendar.HOUR_OF_DAY);
  250. if (hour < 12) {
  251. this.set(Calendar.HOUR_OF_DAY, 12);
  252. } else {
  253. this.set(Calendar.HOUR_OF_DAY, 0);
  254. this.add(Calendar.DAY_OF_MONTH, 1);
  255. }
  256. break;
  257. case MyDailyRollingFileAppender.TOP_OF_DAY:
  258. this.set(Calendar.HOUR_OF_DAY, 0);
  259. this.set(Calendar.MINUTE, 0);
  260. this.set(Calendar.SECOND, 0);
  261. this.set(Calendar.MILLISECOND, 0);
  262. this.add(Calendar.DATE, 1);
  263. break;
  264. case MyDailyRollingFileAppender.TOP_OF_WEEK:
  265. this.set(Calendar.DAY_OF_WEEK, getFirstDayOfWeek());
  266. this.set(Calendar.HOUR_OF_DAY, 0);
  267. this.set(Calendar.MINUTE, 0);
  268. this.set(Calendar.SECOND, 0);
  269. this.set(Calendar.MILLISECOND, 0);
  270. this.add(Calendar.WEEK_OF_YEAR, 1);
  271. break;
  272. case MyDailyRollingFileAppender.TOP_OF_MONTH:
  273. this.set(Calendar.DATE, 1);
  274. this.set(Calendar.HOUR_OF_DAY, 0);
  275. this.set(Calendar.MINUTE, 0);
  276. this.set(Calendar.SECOND, 0);
  277. this.set(Calendar.MILLISECOND, 0);
  278. this.add(Calendar.MONTH, 1);
  279. break;
  280. default:
  281. throw new IllegalStateException("Unknown periodicity type.");
  282. }
  283. return getTime();
  284. }
  285. }
  286. }

编写 log4j.porperties 对 log4j 进行配置

  1. #将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
  2. log4j.rootLogger=DEBUG,console,file
  3. #控制台输出的相关设置
  4. log4j.appender.console=org.apache.log4j.ConsoleAppender
  5. log4j.appender.console.Target=System.out
  6. log4j.appender.console.Threshold=DEBUG
  7. log4j.appender.console.layout=org.apache.log4j.PatternLayout
  8. log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
  9. #文件输出的相关设置
  10. log4j.appender.file=utils.MyDailyRollingFileAppender
  11. #日志文件路径
  12. log4j.appender.file.File=./logs/log.log
  13. log4j.appender.file.Encoding=utf-8
  14. log4j.appender.file.Append=true
  15. log4j.appender.file.Threshold=DEBUG
  16. log4j.appender.file.layout=org.apache.log4j.PatternLayout
  17. #设置日志文件名为日期并按天生成日志文件
  18. log4j.appender.file.datePattern='.'yyyy-MM-dd
  19. #保留7天的日志文件
  20. log4j.appender.file.maxBackupIndex=7
  21. log4j.appender.file.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss,SSS}][%c]%m%n
  22. #日志输出级别
  23. log4j.logger.org.mybatis=DEBUG
  24. log4j.logger.java.sql=DEBUG
  25. log4j.logger.java.sql.Statement=DEBUG
  26. log4j.logger.java.sql.ResultSet=DEBUG
  27. log4j.logger.java.sql.PreparedStatement=DEBUG

配置好之后,在进行单元测试的时候就可以查看输出的日志文件

Service 层

Service 层调用 Dao 层提供的方法

1、编写接口 BookService

  1. package service;
  2. import pojo.Books;
  3. import java.awt.print.Book;
  4. import java.util.List;
  5. public interface BookService {
  6. /** * 增加一本书 * * @param books 书籍 * @return 返回-1表示失败,返回其他则表示成功 */
  7. int addBook(Books books);
  8. /** * 通过 id 删除书籍 * * @param id 书籍id * @return 返回-1表示失败,返回其他则表示成功 */
  9. int deleteBookById(int id);
  10. /** * 通过 id 修改书籍 * * @param books 书籍 * @return 返回-1表示失败,返回其他则表示成功 */
  11. int updateBook(Books books);
  12. /** * 根据 id 查询一本书 * * @param id 书籍id * @return 书籍 */
  13. Books queryBookById(int id);
  14. /** * 查询全部的书 * * @return 全部书籍的集合 */
  15. List<Books> queryAllBooks();
  16. /** * 根据 name 查询书籍 * * @param name 书名 * @return 书籍的集合 */
  17. List<Books> queryBookByName(String name);
  18. /** * 分页查询,如果 name 不为空则根据 name分页;反之,则根据全部数据分页 * * @param name 书名 * @param begin 开始 * @param size 页大小 * @return 当前页的数据 */
  19. List<Books> limitBook(String name, int begin, int size);
  20. /** * 根据 name 模糊查询行数,如果 name 为空则查询所有行数 * * @return 行数 */
  21. int queryRow(String name);
  22. }

2、编写接口 BookService 实现类 BookServiceImpl

  1. package service;
  2. import dao.BookMapper;
  3. import pojo.Books;
  4. import java.util.List;
  5. public class BookServiceImpl implements BookService {
  6. /** * service 层调用 Dao层 */
  7. private BookMapper bookMapper;
  8. public void setBookMapper(BookMapper bookMapper) {
  9. this.bookMapper = bookMapper;
  10. }
  11. @Override
  12. public int addBook(Books books) {
  13. return bookMapper.addBook(books);
  14. }
  15. @Override
  16. public int deleteBookById(int id) {
  17. return bookMapper.deleteBookById(id);
  18. }
  19. @Override
  20. public int updateBook(Books books) {
  21. return bookMapper.updateBook(books);
  22. }
  23. @Override
  24. public Books queryBookById(int id) {
  25. return bookMapper.queryBookById(id);
  26. }
  27. @Override
  28. public List<Books> queryAllBooks() {
  29. return bookMapper.queryAllBooks();
  30. }
  31. @Override
  32. public List<Books> queryBookByName(String name) {
  33. return bookMapper.queryBookByName(name);
  34. }
  35. @Override
  36. public int queryRow(String name) {
  37. return bookMapper.queryRow(name);
  38. }
  39. @Override
  40. public List<Books> limitBook(String name, int begin, int size) {
  41. return bookMapper.limitBook(name, begin, size);
  42. }
  43. }

整合 Spring

编写 jdbc.properties 配置文件

  1. url=jdbc:mysql://localhost:3306/library?useUnicode=true&characterEncoding=utf8&useSSL=false
  2. driver=com.mysql.jdbc.Driver
  3. user=root
  4. password=123456

注:MySQL 8.0版本之后 url 需要配置时区 serverTimezone=GMT%2B8

spring-dao.xml 对 Dao 进行整合

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <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">
  3. <!--关联数据库配置文件-->
  4. <context:property-placeholder location="classpath:jdbc.properties"/>
  5. <!--Druid 数据库连接池配置-->
  6. <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close" init-method="init">
  7. <!-- 基本属性driverClassName、 url、username、password -->
  8. <property name="driverClassName" value="${driver}"/>
  9. <property name="url" value="${url}"/>
  10. <property name="username" value="${user}"/>
  11. <property name="password" value="${password}"/>
  12. <!-- 配置初始化大小、最小、最大、获取连接等待超时的时间、连接在池中最小生存的时间 -->
  13. <property name="initialSize" value="2"/>
  14. <property name="minIdle" value="5"/>
  15. <property name="maxActive" value="50"/>
  16. <property name="maxWait" value="5000"/>
  17. <property name="minEvictableIdleTimeMillis" value="30000"/>
  18. </bean>
  19. <!--sqlSessionFactory-->
  20. <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  21. <property name="dataSource" ref="dataSource"/>
  22. <!--绑定 Mybatis 配置文件-->
  23. <property name="configLocation" value="classpath:mybatis-config.xml"/>
  24. </bean>
  25. <!--配置 dao 接口扫描包,动态实现 Dao 接口注入 Spring 容器中-->
  26. <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  27. <!--注入 sqlSessionFactory-->
  28. <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
  29. <!--扫描 dao 包-->
  30. <property name="basePackage" value="dao"/>
  31. </bean>
  32. </beans>

spring-service.xml 对 Service 进行整合

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <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">
  3. <!--扫描 service 下的包-->
  4. <context:component-scan base-package="service"/>
  5. <!--将所有业务类注入到 Spring ,可以通过配置或注解实现-->
  6. <bean id="bookServiceImpl" class="service.BookServiceImpl">
  7. <property name="bookMapper" ref="bookMapper"/>
  8. </bean>
  9. <!--声明式事务配置-->
  10. <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  11. <!--注入数据源-->
  12. <property name="dataSource" ref="dataSource"/>
  13. </bean>
  14. <!--事务支持-->
  15. <!--给所有方法配置事务-->
  16. <!--配置事务的传播特性:new propagation-->
  17. <tx:advice id="txAdvice" transaction-manager="transactionManager">
  18. <tx:attributes>
  19. <tx:method name="*" propagation="REQUIRED"/>
  20. </tx:attributes>
  21. </tx:advice>
  22. <!--aop配置事务切入-->
  23. <aop:config>
  24. <aop:pointcut id="txPointCut" expression="execution(* dao.*.*(..))"/>
  25. <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
  26. </aop:config>
  27. </beans>

整合 SpringMVC

1、配置 web.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <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">
  3. <!--DispatcherServlet-->
  4. <servlet>
  5. <servlet-name>dispatcherServlet</servlet-name>
  6. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  7. <init-param>
  8. <param-name>contextConfigLocation</param-name>
  9. <param-value>classpath:applicationContext.xml</param-value>
  10. </init-param>
  11. <load-on-startup>1</load-on-startup>
  12. </servlet>
  13. <servlet-mapping>
  14. <servlet-name>dispatcherServlet</servlet-name>
  15. <url-pattern>/</url-pattern>
  16. </servlet-mapping>
  17. <!-- 乱码过滤 -->
  18. <filter>
  19. <filter-name>encoding</filter-name>
  20. <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  21. <init-param>
  22. <param-name>encoding</param-name>
  23. <param-value>utf-8</param-value>
  24. </init-param>
  25. </filter>
  26. <filter-mapping>
  27. <filter-name>encoding</filter-name>
  28. <url-pattern>/*</url-pattern>
  29. </filter-mapping>
  30. <!--Session-->
  31. <session-config>
  32. <session-timeout>15</session-timeout>
  33. </session-config>
  34. <!--欢迎页面-->
  35. <welcome-file-list>
  36. <welcome-file>/WEB-INF/jsp/index.jsp</welcome-file>
  37. </welcome-file-list>
  38. <!--错误页面-->
  39. <error-page>
  40. <error-code>404</error-code>
  41. <location>/WEB-INF/jsp/404.jsp</location>
  42. </error-page>
  43. </web-app>

2、配置 springmvc.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <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">
  3. <!--注解驱动-->
  4. <mvc:annotation-driven/>
  5. <!--静态资源过滤-->
  6. <mvc:default-servlet-handler/>
  7. <!--扫描包:controller-->
  8. <context:component-scan base-package="controller"/>
  9. <!--视图解析器-->
  10. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  11. <property name="prefix" value="/WEB-INF/jsp/"/>
  12. <property name="suffix" value=".jsp"/>
  13. </bean>
  14. <mvc:annotation-driven>
  15. <mvc:message-converters register-defaults="true">
  16. <!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 注解请求映射 默认是ISO-88859-1,避免乱码这里设置为UTF-8 -->
  17. <bean class="org.springframework.http.converter.StringHttpMessageConverter">
  18. <property name="supportedMediaTypes" value="text/html;charset=UTF-8"/>
  19. </bean>
  20. <!-- 启动JSON格式的配置,自动将格式转换成JSON格式,不需要其他类 -->
  21. <bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
  22. <property name="supportedMediaTypes" value="application/json;charset=UTF-8"/>
  23. </bean>
  24. </mvc:message-converters>
  25. </mvc:annotation-driven>
  26. </beans>

3、配置 applicationContext.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <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">
  3. <import resource="spring-dao.xml"/>
  4. <import resource="spring-service.xml"/>
  5. <import resource="spring-mvc.xml"/>
  6. </beans>

一个基本的SSM框架就搭建好了,可以再其上添加业务了

发表评论

表情:
评论列表 (有 0 条评论,421人围观)

还没有评论,来说两句吧...

相关阅读

    相关 SSM框架整合

    1.创建maven项目,准备实体表 idea创建一个maven项目,选用骨架webapp。创建后边验证要用的数据库和实体表。 create database s

    相关 SSM框架整合

    最近接触了不少的项目,从SSM到SSH都接触到了,然而对于这几个项目的架构还是一知半解,我自己花费了一些时间,整理下,写了一个SSM的框架的demo,后期我会给出SSH的一个d

    相关 SSM框架整合

    1、Dao层: Mybatis的配置文件:SqlMapConfig.xml 不需要配置任何内容,需要有文件头。文件必须存在。 applicationContext-d

    相关 ssm框架整合

    整合思路 1、Dao层: Mybatis的配置文件:SqlMapConfig.xml 不需要配置任何内容,需要有文件头。文件必须存在。 application