栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringMvc+Spring+Mybatis整合+RESTFUl+异常处理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringMvc+Spring+Mybatis整合+RESTFUl+异常处理

SSM开发基础案例
    • 包结构
    • 环境搭建
    • 基础案例

包结构

config
dao
service
controller
domain
exception (异常类)

resource———》 jdbc.properties


环境搭建

pom.xml坐标:




4.0.0

com.itheima.SpringMvcSum
SpringMvcSum
1.0-SNAPSHOT
war



org.springframework
spring-webmvc
5.2.10.RELEASE



org.springframework
spring-jdbc
5.2.10.RELEASE



org.springframework
spring-test
5.2.10.RELEASE



org.mybatis
mybatis
3.5.6



org.mybatis
mybatis-spring
1.3.0



mysql
mysql-connector-java
5.1.47



com.alibaba
druid
1.1.16



junit
junit
4.12
test



javax.servlet
javax.servlet-api
3.1.0
provided



com.fasterxml.jackson.core
jackson-databind
2.9.0


log4j
log4j
1.2.17


org.apache.logging.log4j
log4j-to-slf4j
2.11.2






org.apache.tomcat.maven
tomcat7-maven-plugin
2.1

80
/






Config:
SpringConfig:

@Configuration
@ComponentScan("com.it.service")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class,MybatisConfig.class})
public class SpringConfig {
}

Spring整合Mybatis:

JdbcConfig:

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;
}
}

MybatisConfig:

public class MybatisConfig {

@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setTypeAliasesPackage("com.it.domain");
return factoryBean;
}

@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer msc = new MapperScannerConfigurer();
msc.setBasePackage("com.it.dao");
return msc;
}
}

resources:
jdbc.properties:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm_db
jdbc.username=root
jdbc.password=1234

SpringMvcConfig:

@Configuration
@EnableWebMvc
@ComponentScan("com.it.controller")
@EnableTransactionManagement //SpringMvc开启事务
public class SpringMvcConfig {
}

ServletConfig:替代web.xml

public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class[] getRootConfigClasses() {
return new Class[]{SpringConfig.class};
}

protected Class[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}

protected String[] getServletMappings() {
return new String[]{"/"}; //拦截所有
}


//这里可以添加一个过滤器,用来设置字符集编码
}
基础案例

dao:
BookDao:

public interface BookDao {

@Insert("insert into tbl_book values(null,#{type},#{name},#{description})")
public void save(Book book);

@Update("update tbl_book set type=#{type},name=#{name},description=#{description} where id=#{id}")
public void update(Book book);

@Delete("delete from tbl_book where id = #{id}")
public void delete(Integer id);

@Select("select * from tbl_book")
public List getAll();

@Select("select * from tbl_book where id=#{id}")
public Book getByid(Integer id);
}

service:
BookService:

@Transactional //开启事务 一般情况下 都在业务层接口开启事务
public interface BookService {


public boolean save(Book book);


public boolean update(Book book);


public boolean delete(Integer id);


public List getAll();


public Book getByid(Integer id);
}

BookServiceImpl:

@Service
public class BookServiceImpl implements BookService {
@Autowired //这里使用dao层接口,使用spring自动注入
private BookDao bookDao;

public boolean save(Book book) {
bookDao.save(book);
return true;
}

public boolean update(Book book) {
bookDao.update(book);
return true;
}

public boolean delete(Integer id) {
bookDao.delete(id);
return true;
}

public List getAll() {
return bookDao.getAll();
}

public Book getByid(Integer id) {
//模拟异常
if(id==1){
throw new BusinessException(Code.BUSINESS_ERR,"异常出现的消息提示");
}

//将可能出现的异常进行包装,转换成自定义异常
try {
int i = 1/0;
} catch (Exception e) { // throw语句通常用在方法体中,并且抛出一个异常对象。程序在执行到throw语句时立即停止,它后面的语句都不执行
throw new SystemException(Code.SYSTEM_ERR,"服务器超时,请重试",e);
}

return bookDao.getByid(id);
}
}

controller:
BookController:

@RestController
@RequestMapping("/books")
@ResponseBody
public class BookController {
@Autowired
private BookService bookService;

@PostMapping
public Result save(@RequestBody Book book) {
boolean flag = bookService.save(book);
return new Result(flag ? Code.SAVE_OK : Code.SAVE_ERR, flag); //返回状态码 ,数据
}
@PutMapping
public Result update(@RequestBody Book book) {
boolean flag = bookService.update(book);
return new Result(flag ? Code.UPDATE_OK : Code.UPDATE_ERR, flag);
}
@DeleteMapping("/{id}")
public Result delete(@PathVariable Integer id) {
boolean flag = bookService.delete(id);
return new Result(flag ? Code.DELETE_OK : Code.DELETE_ERR, flag);
}

@GetMapping
public Result getAll() {
List books = bookService.getAll();
Integer code = books != null ? Code.GET_OK : Code.GET_ERR;
String msg = books != null ? "查询成功" : "数据查询失败,请重试";
return new Result(code, books, msg);
}

@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);
}
}

由于前端人员看到异常信息的多样性和复杂性,我们后端给予处理,在表现层将所有调用业务层处理后的数据统一返回一个格式,方便前端人员处理,所以我们定义一个类,用来做为统一返回的类型格式(在实际开发中,返回的类型可能不止这些,根据业务需求而定,这里只简单的举例,思想是一样的,应该学会灵活运用)

没有经过处理的异常信息:

Result:

public class Result {

private Object data;//返回的结果数据

private Integer code;  //返回的状态码

private String 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;
}

public Result() { }

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;
}
}

由于状态码直接使用数字写在程序中不够专业,这里编写一个对象,用来存放这些状态码,并且将它们设置为静态常量这样在使用时,可以不创建对象,直接通过 对象.常量名 进行访问

Code:根据需求持续添加状态码,可以无数多

public class Code {

//增删改查状态码
public static final Integer SAVE_OK =2011;
public static final Integer DELETE_OK =2021;
public static final Integer UPDATE_OK =2031;
public static final Integer GET_OK =2041;
//失败
public static final Integer SAVE_ERR =2000;
public static final Integer DELETE_ERR =2020;
public static final Integer UPDATE_ERR =2030;
public static final Integer GET_ERR =2040;

//系统异常
public static final Integer SYSTEM_ERR = 50001;
//业务异常
public static final Integer BUSINESS_ERR = 60002;
//系统位置异常
public static final Integer SYSTEM_UNKONW_ERR = 59999;
}

前面是解决表现层返回值类型问题,我们进行了统一的要求。但在实际开发过程中,在前端中返回的结果可能会出现异常信息,所以我们应该定义一个异常处理器,用来拦截异常信息,并将异常信息封装为上面统一的格式,方便前端人员辨别和处理。

ProjectExceptionAdvice:异常拦截器,用户的异常信息会被该拦截器拦下,并进行分类(业务异常,系统异常,其它异常等)处理

@RestControllerAdvice //advice:通知
public class ProjectExceptionAdvice {


@ExceptionHandler(SystemException.class) // 异常处理器 拦截System异常
public Result doSystemException(SystemException ex) { //收集异常的方法
//记录日志
//发送消息给运维
//发送邮件给开发人员
return new Result(ex.getCode(), null, ex.getMessage());

}


@ExceptionHandler(BusinessException.class) // 异常处理器 拦截Business异常
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_UNKONW_ERR, null, "系统繁忙,请稍后再试!");
}
}

下面定义了系统异常和业务异常,除此之外的异常统一为其它异常

exception:
SystemException:

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;
}
}

BusinessException:

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;
}
}

异常定义完之后,可以在合适的地方抛出异常,异常会被拦截器拦截并分类处理,最终返回给前端

模拟异常抛出:

if(id==1){
throw new BusinessException(Code.BUSINESS_ERR,"异常出现的消息提示");  //抛出业务异常
}

结果:

//将可能出现的异常进行包装,转换成自定义异常
try {
int i = 1/0;
} catch (Exception e) { // throw语句通常用在方法体中,并且抛出一个异常对象。程序在执行到throw语句时立即停止,它后面的语句都不执行
throw new SystemException(Code.SYSTEM_ERR,"服务器超时,请重试",e);  //抛出系统异常
}

结果:

测试表现层正常情况下的返回值:


提示:该文章为学习笔记,如有错误,望大佬批评指正,留言必回

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/844499.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号