SSM整合流程
- 创建工程
- SSM整合
- Spring
- SpringConfig
- MyBatis
- MybatisConfig
- JdbcConfig
- jdbc.properties
- SpringMVC
- servletConfig
- SpringMvcConfig
- Spring
- 功能模块
- 表与实体类
- dao(接口+自动代理)
- service(接口+实现类)
- 业务层接口测试(整合JUnit )
- controller
- 表现层接口测试(PostMan)
持久层
数据库
目录结构
Spring整合MyBatis
配置
-
SpringConfig
package com.jihua.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.PropertySource; import org.springframework.transaction.annotation.EnableTransactionManagement; @Configuration @ComponentScan({"com.jihua.service"}) @PropertySource("classpath:jdbc.properties") @EnableTransactionManagement @Import({JdbcConfig.class, MybatisConfig.class}) public class SpringConfig { }
-
JdbcConfig、jdbc.properties
package com.jihua.config; import com.alibaba.druid.pool.DruidDataSource; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import javax.sql.DataSource; public class JdbcConfig { @Value("${jdbc.driver}") private String driver; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; @Bean public DataSource dataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName(driver); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); return dataSource; } @Bean public PlatformTransactionManager transactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } }
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/ssm_db?useSSL=false jdbc.username=root jdbc.password=自行修改
-
MyBatisConfig
package com.jihua.config; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.mapper.MapperScannerConfigurer; import org.springframework.context.annotation.Bean; import javax.sql.DataSource; public class MybatisConfig { @Bean public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) { SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(dataSource); factoryBean.setTypeAliasesPackage("com.jihua.domain"); return factoryBean; } @Bean public MapperScannerConfigurer mapperScannerConfigurer() { MapperScannerConfigurer msc = new MapperScannerConfigurer(); msc.setBasePackage("com.jihua.dao"); return msc; } }
模型
-
Book
package com.jihua.domain; public class Book { private Integer id; private String type; private String name; private String description; @Override public String toString() { return "Book{" + "id=" + id + ", type='" + type + '\'' + ", name='" + name + '\'' + ", description='" + description + '\'' + '}'; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } }
数据层标准开发
-
BookDao
package com.jihua.dao; import com.jihua.domain.Book; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; import java.util.List; public interface BookDao { @Insert("insert into tbl_book values(null, #{type}, #{name}, #{description})") public int save(Book book); @Update("update tbl_book set type = #{type}, name = #{name}, description = #{description} where id = #{id}") public int update(Book book); @Delete("delete from tbl_book where id = #{id}") public int delete(Integer id); @Select("select * from tbl_book where id = #{id}") public Book getById(Integer id); @Select("select * from tbl_book") public List<Book> getAll(); }
业务层标准开发
-
BookService
package com.jihua.service; import com.jihua.domain.Book; import org.springframework.transaction.annotation.Transactional; import java.util.List; @Transactional public interface BookService { /** * 保存 * * @param book * @return */ public boolean save(Book book); /** * 修改 * * @param book * @return */ public boolean update(Book book); /** * 删除 * * @param id * @return */ public boolean delete(Integer id); /** * 根据ID查询 * * @param id * @return */ public Book getById(Integer id); /** * 查询所有 * * @return */ public List<Book> getAll(); }
-
BookServiceImpl
package com.jihua.service.impl; import com.jihua.dao.BookDao; import com.jihua.domain.Book; import com.jihua.service.BookService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class BookServiceImpl implements BookService { @Autowired private BookDao bookDao; @Override public boolean save(Book book) { return bookDao.save(book) > 0; } @Override public boolean update(Book book) { return bookDao.update(book) > 0; } @Override public boolean delete(Integer id) { return bookDao.delete(id) > 0; } @Override public Book getById(Integer id) { return bookDao.getById(id); } @Override public List<Book> getAll() { return bookDao.getAll(); } }
测试接口
-
BookServiceTest
package com.jihua.service; import com.jihua.config.SpringConfig; import com.jihua.domain.Book; 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.List; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = SpringConfig.class) public class BookServiceTest { @Autowired private BookService bookService; @Test public void testGetById() { Book book = bookService.getById(1); System.out.println(book); } @Test public void testGetAll() { List<Book> book = bookService.getAll(); System.out.println(book); } }
事务处理
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Configuration
@ComponentScan({"com.jihua.service"})
@PropertySource("classpath:jdbc.properties")
//开启事务管理器
@EnableTransactionManagement
@Import({JdbcConfig.class, MybatisConfig.class})
public class SpringConfig {
}
//开启事务
@Transactional
public interface BookService {
...
}
Spring整合SpringMVC
web配置类
-
ServletConfig
package com.jihua.config; import org.springframework.web.filter.CharacterEncodingFilter; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; import javax.servlet.Filter; public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[]{SpringConfig.class}; } @Override protected Class<?>[] getServletConfigClasses() { return new Class[]{SpringMvcConfig.class}; } @Override protected String[] getServletMappings() { return new String[]{"/"}; } //处理中文字符乱码 @Override protected Filter[] getServletFilters() { //方法一 //CharacterEncodingFilter filter = new CharacterEncodingFilter("UTF-8"); //方法二 CharacterEncodingFilter filter = new CharacterEncodingFilter(); filter.setEncoding("UTF-8"); return new Filter[]{filter}; } }
SpringMVC配置类
-
SpringMvcConfig
package com.jihua.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; @Configuration @ComponentScan({"com.jihua.controller", "com.jihua.config"}) @EnableWebMvc public class SpringMvcConfig { }
基于Restful的Controller开发
-
BookController
package com.jihua.controller; import com.jihua.domain.Book; import com.jihua.service.BookService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping("/books") public class BookController { @Autowired private BookService bookService; @PostMapping public Result save(@RequestBody Book book) { System.out.println(book); boolean flag = bookService.save(book); return new Result(flag ? Code.SAVE_OK : Code.SAVE_ERR, book); } @PutMapping public Result update(@RequestBody Book book) { boolean flag = bookService.update(book); return new Result(flag ? Code.UPDATE_OK : Code.UPDATE_ERR, book); } @DeleteMapping("/{id}") public Result delete(@PathVariable Integer id) { boolean flag = bookService.delete(id); return new Result(flag ? Code.DELETE_OK : Code.DELETE_ERR, null); } @GetMapping("/{id}") public Result getById(@PathVariable Integer id) { Book book = bookService.getById(id); Integer code = book != null ? Code.GET_OK : Code.GET_ERR; String msg = book != null ? "" : "数据查询失败,请重试! "; return new Result(code, book, msg); } @GetMapping public Result getAll() { List<Book> book = bookService.getAll(); Integer code = book != null ? Code.GET_OK : Code.GET_ERR; String msg = book != null ? "" : "数据查询失败,请重试! "; return new Result(code, book, msg); } }
表现层数据封装
表现层与前端数据传输数据协议设计
创建结果模型类,封装数据到data属性中,封装特殊消息到message(msg)属性中
-
设置统一数据返回结果类
public class Result { private Object data; private Integer code; private String msg; }
-
Result类中的字段并不是固定的,可以根据需要自行增减提供若干个构造方法,方便操作
-
增删改
{ "code":20031, "data":true }
-
查单条
{ "code":20040, "data":null, "msg":"数据查询失败,请重试!" }
-
查全部
{ "code":20041, "data":[ { "id": 1, "type" :"计算机理论", "name" : "Spring实战第5版", "description":"Spring入门经典教程" }, { "id" : 2, "type":"计算机理论", "name":"spring 5核心原理与30个类手写实战", "description":"十年沉淀之作" } ] }
表现层与前端数据传输数据协议实现
-
设置统一数据返回结果编码
public class Code { public static final Integer SAVE_OK = 20011; public static final Integer DELETE_OK = 20021; public static final Integer UPDATE_OK = 20031; public static final Integer GET_OK = 20041; public static final Integer SAVE_ERR = 20010; public static final Integer DELETE_ERR = 20020; public static final Integer UPDATE_ERR = 20030; public static final Integer GET_ERR = 20040; }
-
Code类的常量设计也不是固定的,可以根据需要自行增减,例如将查询再进行细分为
GET_OK
,GET_ALL_OK
,GET_PAGE_OK
-
根据情况设定合理的Result
@RequestMapping("/books") public class BookController{ @Autowired private BookService bookService; @GetMapping("/{id}") public Result getById(@PathVariable Integer id) { Book book = bookService.getById(id); Integer code = book != null ? code.GET_OK : Code.GET_ERR; String msg = book != null ? "" : "数据查询失败,请重试! "; return new Result(code, book, msg); } }
异常处理
出现异常现象的常见位置与常见诱因如下:
- 框架内部抛出的异常:因使用不合规导致
- 数据层抛出的异常:因外部服务器故障导致(例如:服务器访问超时)
- 业务层抛出的异常:因业务逻辑书写错误导致(例如:遍历业务书写操作,导致索引异常等)
- 表现层抛出的异常:因数据收集、校验等规则导致(例如:不匹配的数据类型间导致异常)
- 工具类抛出的异常:因工具类书写不严谨不够健壮导致(例如:必要释放的连接长期未释放等)
异常处理器
-
集中的、统一的处理项目中出现的异常
@RestControllerAdvice public class ProjectExceptionAdvice { @ExceptionHandler(Exception.class) public Result doException(Exception ex){ return new Result(666,null,"操作异常"); } }
-
名称: @RestControllerAdvice
-
类型:类注解
-
位置: Rest风格开发的控制器增强类定义上方
-
作用:为Rest风格开发的控制器类做增强
-
范例:
@RestControllerAdvice public class ProjectExceptionAdvice { @ExceptionHandler(Exception.class) public Result doException(Exception ex) { return new Result(666,null,"操作异常"); } }
-
说明:
- 此注解自带@ResponseBody注解与@Component注解,具备对应的功能
-
名称: @ExceptionHandler
-
类型:方法注解
-
位置:专用于异常处理的控制器方法上方
-
作用:设置指定异常的处理方案,功能等同于控制器方法,出现异常后终止原始控制器执行,并转入当前方法执行
-
范例:
@RestControllerAdvice public class ProjectExceptionAdvice { @ExceptionHandler(Exception.class) public Result doException(Exception ex) { return new Result(666,null,"操作异常"); } }
-
说明
- 此类方法可以根据处理的异常不同,制作多个方法分别处理对应的异常
项目异常处理方案
-
项目异常分类
- 业务异常(BusinessException)
- 规范的用户行为产生的异常
- 不规范的用户行为操作产生的异常
- 系统异常(SystemException)
- 项目运行过程中可预计且无法避免的异常
- 其他异常(Exception)
- 编程人员未预期到的异常
- 业务异常(BusinessException)
-
项目异常处理方案
-
业务异常(BusinessException)
- 发送对应消息传递给用户,提醒规范操作
-
系统异常(systemException)
-
发送固定消息传递给用户,安抚用户
-
发送特定消息给运维人员,提醒维护
-
记录日志
-
-
其他异常(Exception)
-
发送固定消息传递给用户,安抚用户
-
发送特定消息给编程人员,提醒维护(纳入预期范围内)
-
记录日志
-
-
-
自定义项目系统级异常
public class SystemException extends RuntimeException{ private Integer code; public SystemException(Integer code, String message){ super(message); this.code = code; } public SystemException( Integer code,String message,Throwable cause) { super(message,cause); this.code = code; } public Integer getcode() { return code; } public void setCode (Integer code) i this.code = code; } }
-
自定义项目业务级异常
public class BusinessException extends RuntimeException{ private Integer code; public BusinessException(Integer code, string message) { super(message); this.code = code; } public BusinessException(Integer code, String message, Throwable cause){ super(message, cause); this.code = code; } public Integer getcode() { return code; } public void setcode(Integer code) { this.code = code; } }
-
自定义异常编码(持续补充)
public class code { public static final Integer sYSTEM_UNKNOw_ERROR = 50001; public static final Integer sYSTEM_TIMEOUT_ERROR = 50002; public static final Integer PRO3ECT_VALIDATE_ERROR = 60001; public static final Integer PRO3ECT_BUSINESS_ERROR = 60002; }
-
触发自定义异常
@Service public class BookServiceImpl implements BookService { @Autowired private BookDao bookDao; public Book getById(Integer id) { if( id < 0 ){ throw new BusinessException(Code.PRO3ECT_BUSINESS_ERROR, "请勿进行非法操作! "); } return bookDao.getById(id); } }
-
拦截并处理异常
@RestControllerAdvice public class ProjectExceptionAdvice { @ExceptionHandler(SystemException.class) public Result doSystemException(SystemException ex) { //记录日志 //发送消息给运维 //发送邮件给开发人员 return new Result(ex.getCode(), null, ex.getMessage()); } @ExceptionHandler(BusinessException.class) public Result doBusinessException(BusinessException ex) { return new Result(ex.getCode(), null, ex.getMessage()); } @ExceptionHandler(Exception.class) public Result doException(Exception ex) { return new Result(Code.SYSTEM_UNKNOWN_ERR, null, "系统繁忙,请稍后再试!"); } }
-
异常处理器效果对比
{ "data":{ "id": 1, "type":"计算机理论", "name":"Spring实战第5版", "description":"Spring入门经典教程" }, "code":20041, "msg":null }
{ "data" : nu1l, "code" : 60002, "msg":"请勿进行非法操作!" }
项目全部代码
项目结构
maven配置
- pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jihua</groupId>
<artifactId>springmvc_ssm</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>80</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
配置类config
- JdbcConfig
package com.jihua.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
public class JdbcConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driver);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
- MybatisConfig
package com.jihua.config;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;
public class MybatisConfig {
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setTypeAliasesPackage("com.jihua.domain");
return factoryBean;
}
@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer msc = new MapperScannerConfigurer();
msc.setBasePackage("com.jihua.dao");
return msc;
}
}
- ServletConfig
package com.jihua.config;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import javax.servlet.Filter;
public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
//处理中文字符乱码
@Override
protected Filter[] getServletFilters() {
//方法一
//CharacterEncodingFilter filter = new CharacterEncodingFilter("UTF-8");
//方法二
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
return new Filter[]{filter};
}
}
- SpringConfig
package com.jihua.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@ComponentScan({"com.jihua.service"})
@PropertySource("classpath:jdbc.properties")
@EnableTransactionManagement
@Import({JdbcConfig.class, MybatisConfig.class})
public class SpringConfig {
}
- SpringMvcConfig
package com.jihua.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@ComponentScan({"com.jihua.controller", "com.jihua.config"})
@EnableWebMvc
public class SpringMvcConfig {
}
- SpringMvcSupport
package com.jihua.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("/");
}
}
控制层controller
- BookController
package com.jihua.controller;
import com.jihua.domain.Book;
import com.jihua.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/books")
public class BookController {
@Autowired
private BookService bookService;
@PostMapping
public Result save(@RequestBody Book book) {
System.out.println(book);
boolean flag = bookService.save(book);
return new Result(flag ? Code.SAVE_OK : Code.SAVE_ERR, book);
}
@PutMapping
public Result update(@RequestBody Book book) {
boolean flag = bookService.update(book);
return new Result(flag ? Code.UPDATE_OK : Code.UPDATE_ERR, book);
}
@DeleteMapping("/{id}")
public Result delete(@PathVariable Integer id) {
boolean flag = bookService.delete(id);
return new Result(flag ? Code.DELETE_OK : Code.DELETE_ERR, null);
}
@GetMapping("/{id}")
public Result getById(@PathVariable Integer id) {
Book book = bookService.getById(id);
Integer code = book != null ? Code.GET_OK : Code.GET_ERR;
String msg = book != null ? "" : "数据查询失败,请重试! ";
return new Result(code, book, msg);
}
@GetMapping
public Result getAll() {
List<Book> book = bookService.getAll();
Integer code = book != null ? Code.GET_OK : Code.GET_ERR;
String msg = book != null ? "" : "数据查询失败,请重试! ";
return new Result(code, book, msg);
}
}
- Code
package com.jihua.controller;
public class Code {
public static final Integer SAVE_OK = 20011;
public static final Integer DELETE_OK = 20021;
public static final Integer UPDATE_OK = 20031;
public static final Integer GET_OK = 20041;
public static final Integer SAVE_ERR = 20010;
public static final Integer DELETE_ERR = 20020;
public static final Integer UPDATE_ERR = 20030;
public static final Integer GET_ERR = 20040;
public static final Integer SYSTEM_ERR = 50001;
public static final Integer SYSTEM_TIMEOUT_ERR = 50001;
public static final Integer SYSTEM_UNKNOWN_ERR = 59999;
public static final Integer BUSINESS_ERR = 60002;
}
- ProjectExceptionAdvice
package com.jihua.controller;
import com.jihua.exception.BusinessException;
import com.jihua.exception.SystemException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class ProjectExceptionAdvice {
@ExceptionHandler(SystemException.class)
public Result doSystemException(SystemException ex) {
//记录日志
//发送消息给运维
//发送邮件给开发人员
return new Result(ex.getCode(), null, ex.getMessage());
}
@ExceptionHandler(BusinessException.class)
public Result doBusinessException(BusinessException ex) {
return new Result(ex.getCode(), null, ex.getMessage());
}
@ExceptionHandler(Exception.class)
public Result doException(Exception ex) {
return new Result(Code.SYSTEM_UNKNOWN_ERR, null, "系统繁忙,请稍后再试!");
}
}
- Result
package com.jihua.controller;
public class Result {
private Object data;
private Integer code;
private String msg;
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Result(Integer code, Object data, String msg) {
this.data = data;
this.code = code;
this.msg = msg;
}
public Result(Integer code, Object data) {
this.data = data;
this.code = code;
}
}
数据访问层dao
- BookDao(接口)
package com.jihua.dao;
import com.jihua.domain.Book;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;
public interface BookDao {
@Insert("insert into tbl_book values(null, #{type}, #{name}, #{description})")
public int save(Book book);
@Update("update tbl_book set type = #{type}, name = #{name}, description = #{description} where id = #{id}")
public int update(Book book);
@Delete("delete from tbl_book where id = #{id}")
public int delete(Integer id);
@Select("select * from tbl_book where id = #{id}")
public Book getById(Integer id);
@Select("select * from tbl_book")
public List<Book> getAll();
}
数据层domain
- Book
package com.jihua.domain;
public class Book {
private Integer id;
private String type;
private String name;
private String description;
@Override
public String toString() {
return "Book{" + "id=" + id + ", type='" + type + '\'' + ", name='" + name + '\'' + ", description='" + description + '\'' + '}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
异常处理层exception
- BusinessException
package com.jihua.exception;
public class BusinessException extends RuntimeException {
private Integer code;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public BusinessException(Integer code, String message) {
super(message);
this.code = code;
}
public BusinessException(Integer code, String message, Throwable cause) {
super(message, cause);
this.code = code;
}
}
- SystemException
package com.jihua.exception;
public class SystemException extends RuntimeException {
private Integer code;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public SystemException(Integer code, String message) {
super(message);
this.code = code;
}
public SystemException(Integer code, String message, Throwable cause) {
super(message, cause);
this.code = code;
}
}
服务层service
- BookService(接口)
package com.jihua.service;
import com.jihua.domain.Book;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Transactional
public interface BookService {
/**
* 保存
*
* @param book
* @return
*/
public boolean save(Book book);
/**
* 修改
*
* @param book
* @return
*/
public boolean update(Book book);
/**
* 删除
*
* @param id
* @return
*/
public boolean delete(Integer id);
/**
* 根据ID查询
*
* @param id
* @return
*/
public Book getById(Integer id);
/**
* 查询所有
*
* @return
*/
public List<Book> getAll();
}
服务层实现impl
- BookServiceImpl
package com.jihua.service.impl;
import com.jihua.dao.BookDao;
import com.jihua.domain.Book;
import com.jihua.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class BookServiceImpl implements BookService {
@Autowired
private BookDao bookDao;
@Override
public boolean save(Book book) {
return bookDao.save(book) > 0;
}
@Override
public boolean update(Book book) {
return bookDao.update(book) > 0;
}
@Override
public boolean delete(Integer id) {
return bookDao.delete(id) > 0;
}
@Override
public Book getById(Integer id) {
return bookDao.getById(id);
}
@Override
public List<Book> getAll() {
return bookDao.getAll();
}
}
资源文件resources
- jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm_db?useSSL=false
jdbc.username=root
jdbc.password=密码请自行修改
webapp
- index.html
<!DOCTYPE html>
<html lang="en" xmlns="">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.zhimg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入vue -->
<script src="https://unpkg.zhimg.com/vue@2/dist/vue.js"></script>
<!-- 引入组件库 -->
<script src="https://unpkg.zhimg.com/element-ui/lib/index.js"></script>
<!-- 引入axios -->
<script src="https://unpkg.zhimg.com/axios.min.js"></script>
</head>
<body>
<div id="app">
<el-button plain type="primary" @click="handleCreat">新增</el-button>
<br/>
<br/>
<!-- 添加对话框 -->
<el-dialog :title="action" :visible.sync="dialogVisible" width="80%">
<el-form :model="form">
<el-form-item label="图书类别" :label-width="formLabelWidth">
<el-select v-model="form.type" placeholder="请选择图书类别">
<el-option label="计算机理论" value="计算机理论"></el-option>
<el-option label="计算机实践" value="计算机实践"></el-option>
</el-select>
</el-form-item>
<el-form-item label="图书名称" :label-width="formLabelWidth">
<el-input v-model="form.name" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="描述" :label-width="formLabelWidth">
<el-input v-model="form.description" autocomplete="off"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="handleDestroy">取 消</el-button>
<el-button type="primary" @click="addBook">添 加</el-button>
</div>
</el-dialog>
<!-- 表格 -->
<template>
<el-table :data="tableData" style="width: 100%" border stripe>
<el-table-column prop="id" label="编号" align="center" width="100%">
</el-table-column>
<el-table-column prop="type" label="图书类别" align="center" width="100%">
</el-table-column>
<el-table-column prop="name" label="图书名称" align="center" width="200%">
</el-table-column>
<el-table-column prop="description" label="描述" align="center">
</el-table-column>
<el-table-column label="操作" align="center" width="200%">
<template slot-scope="scope">
<el-button size="mini" @click="handleUpdate(scope.row)" type="warning">编辑</el-button>
<el-button size="mini" @click="deleteWarning(scope.row)" type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
</template>
</div>
</body>
<script>
new Vue({
el: "#app",
data() {
return {
tableData: {},
// 添加对话框显示控制
dialogVisible: false,
form: {},
formLabelWidth: '80px',
action: "操作"
}
},
created() {
this.getAll();
},
methods: {
//弹出添加窗口
handleCreat() {
this.action = "添加";
this.dialogVisible = true;
this.resetForm();
},
//关闭窗口
handleDestroy() {
this.dialogVisible = false;
this.resetForm();
},
//清空表单
resetForm() {
this.form = {};
},
//弹出修改窗口
handleUpdate(row) {
this.action = "编辑";
this.dialogVisible = true;
//发送ajax请求
axios.get("/books/" + row.id).then((res) => {
this.form = res.data.data;
})
},
//根据id删除
deleteById(id) {
axios.delete("/books/" + id).then((res) => {
console.log(res.data.code);
if (res.data.code == 20021) {
this.$message.success("删除成功");
} else {
this.$message.error("删除失败");
}
});
},
//查询全部
getAll() {
//发送ajax请求
axios.get("/books").then((res) => {
this.tableData = res.data.data;
})
},
addBook() {
//发送ajax请求
axios.post("/books", this.form).then((res) => {
if (res.data.code == 20011) {
this.dialogVisible = false;
this.$message.success("添加成功");
this.getAll();
} else if (res.data.code == 20010) {
this.$message.error("添加失败");
} else {
this.$message.error(res.data.msg);
}
})
},
//删除操作
deleteWarning(row) {
this.$confirm('此操作将永久删除该文件, 是否继续?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.deleteById(row.id);
this.getAll();
}).catch(() => {
this.$message.info("已取消删除");
});
}
}
})
</script>
</html>
测试类test
- BookServiceTest
package com.jihua.service;
import com.jihua.config.SpringConfig;
import com.jihua.domain.Book;
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.List;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class BookServiceTest {
@Autowired
private BookService bookService;
@Test
public void testGetById() {
Book book = bookService.getById(1);
System.out.println(book);
}
@Test
public void testGetAll() {
List<Book> book = bookService.getAll();
System.out.println(book);
}
}
- 若编译失败,在项目根目录执行
mvn idea:idea
} else if (res.data.code == 20010) {
this.$message.error("添加失败");
} else {
this.$message.error(res.data.msg);
}
})
},
//删除操作
deleteWarning(row) {
this.$confirm('此操作将永久删除该文件, 是否继续?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.deleteById(row.id);
this.getAll();
}).catch(() => {
this.$message.info("已取消删除");
});
}
}
})
```
测试类test
- BookServiceTest
package com.jihua.service;
import com.jihua.config.SpringConfig;
import com.jihua.domain.Book;
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.List;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class BookServiceTest {
@Autowired
private BookService bookService;
@Test
public void testGetById() {
Book book = bookService.getById(1);
System.out.println(book);
}
@Test
public void testGetAll() {
List<Book> book = bookService.getAll();
System.out.println(book);
}
}
- 若编译失败,在项目根目录执行
mvn idea:idea