- 包结构
- 环境搭建
- 基础案例
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); //抛出系统异常
}
结果:
测试表现层正常情况下的返回值:
提示:该文章为学习笔记,如有错误,望大佬批评指正,留言必回



