创建工程
导入坐标 注意:servlet-api包与tomcat7的依赖包servlet-api冲突,需要添加provided 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 <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 > 8.0.28</version > </dependency > <dependency > <groupId > com.alibaba</groupId > <artifactId > druid</artifactId > <version > 1.1.12</version > </dependency > <dependency > <groupId > javax.servlet</groupId > <artifactId > javax.servlet-api</artifactId > <version > 4.0.1</version > <scope > provided</scope > </dependency > <dependency > <groupId > com.fasterxml.jackson.core</groupId > <artifactId > jackson-databind</artifactId > <version > 2.9.0</version > </dependency > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.13.1</version > <scope > test</scope > </dependency > </dependencies > <build > <plugins > <plugin > <groupId > org.apache.tomcat.maven</groupId > <artifactId > tomcat7-maven-plugin</artifactId > <version > 2.2</version > <configuration > <port > 80 </port > </configuration > </plugin > </plugins > </build >
创建配置文件 SpringConfig 1 2 3 4 5 6 @Configuration @ComponentScan("cola.service") @PropertySource("classpath:jdbc.properties") @Import({JdbcConfig.class, MyBatisConfig.class}) public class SpringConfig {}
JdbcConfig 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @Configuration 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 ds = new DruidDataSource (); ds.setDriverClassName(driver); ds.setUrl(url); ds.setUsername(username); ds.setPassword(password); return ds; } }
jdbc.properties 1 2 3 4 jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql:///db1 jdbc.username=root jdbc.password=root
MyBatisConfig 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class MyBatisConfig { @Bean public SqlSessionFactoryBean sqlSessionFactory (DataSource dataSource) { SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean (); factoryBean.setDataSource(dataSource); factoryBean.setTypeAliasesPackage("cola.domain" ); return factoryBean; } @Bean public MapperScannerConfigurer mapperScannerConfigurer () { MapperScannerConfigurer msc = new MapperScannerConfigurer (); msc.setBasePackage("cola.dao" ); return msc; } }
ServletConfig 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 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 []{"/" }; } @Override protected Filter[] getServletFilters() { CharacterEncodingFilter filter = new CharacterEncodingFilter (); filter.setEncoding("utf-8" ); return new Filter []{filter}; } }
SpringMvcConfig 1 2 3 4 5 @Configuration @ComponentScan("cola.controller") @EnableWebMvc public class SpringMvcConfig {}
数据层接口 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public interface BookDao { @Insert("insert into tb_book values (null, #{type}, #{name}, #{description})") public void save (Book book) ; @Update("update tb_book set type=#{type}, name=#{name}, description=#{description} where id=#{id}") public void update (Book book) ; @Delete("delete from tb_book where id=#{id}") public void delete (Integer id) ; @Select("select * from tb_book where id=#{id}") public Book getById (Integer id) ; @Select("select * from tb_book;") public List<Book> getAll () ; }
业务层接口及实现类 1 2 3 4 5 6 7 8 9 10 11 public interface BookService { public boolean save (Book book) ; public boolean update (Book book) ; public boolean delete (Integer id) ; public Book getById (Integer id) ; public List<Book> getAll () ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 @Service public class BookServiceImpl implements BookService { @Autowired 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 Book getById (Integer id) { Book book = bookDao.getById(id); return book; } public List<Book> getAll () { List<Book> books = bookDao.getAll(); return books; } }
表现层 REST风格 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 @RestController @RequestMapping("/books") public class BookController { @Autowired private BookService bookService; @PostMapping public boolean save (@RequestBody Book book) { bookService.save(book); return true ; } @PutMapping public boolean update (@RequestBody Book book) { bookService.update(book); return true ; } @DeleteMapping("/{id}") public boolean delete (@PathVariable Integer id) { bookService.delete(id); return true ; } @GetMapping("/{id}") public Book getById (@PathVariable Integer id) { Book book = bookService.getById(id); return book; } @GetMapping public List<Book> getAll () { List<Book> books = bookService.getAll(); return books; } }
事务处理 在SpringConfig中开启事务管理 @EnableTransactionManagement
1 2 3 4 5 6 7 @Configuration @ComponentScan("cola.service") @PropertySource("classpath:jdbc.properties") @Import({JdbcConfig.class, MyBatisConfig.class}) @EnableTransactionManagement public class SpringConfig {}
在JdbcConfig中创建事务管理Bean 注意这里的DataSource要通过形参传递进入,直接通过方法调用就不是Spring管理的Bean了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 @Configuration 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 ds = new DruidDataSource (); ds.setDriverClassName(driver); ds.setUrl(url); ds.setUsername(username); ds.setPassword(password); return ds; } @Bean public PlatformTransactionManager transactionManager (DataSource dataSource) { DataSourceTransactionManager ds = new DataSourceTransactionManager (); ds.setDataSource(dataSource); return ds; } }
在事务层接口开启事务管理 @Transactional
1 2 3 4 5 6 7 8 9 10 11 12 @Transactional public interface BookService { public boolean save (Book book) ; public boolean update (Book book) ; public boolean delete (Integer id) ; public Book getById (Integer id) ; public List<Book> getAll () ; }
表现层数据封装 封装数据到data中,封装操作结果到code属性中,封装特殊信息到message属性中。
由于是用在表现层,故放在controller中。
Result类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 public class Result { private Object data; private Integer code; private String msg; public Result () { } public Result (Integer code, Object data) { this .data = data; this .code = code; } public Result (Integer code, Object data, String msg) { this .data = data; this .code = code; this .msg = 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; } }
Code类 1 2 3 4 5 6 7 8 9 10 11 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 ; }
更改表现层 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 @RestController @RequestMapping("/books") 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("/{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> books = bookService.getAll(); Integer code = books != null ? Code.GET_OK : Code.GET_ERR; String msg = books != null ? "" : "查询失败" ; return new Result (code, books, msg); } }
异常处理器 所有异常均抛到表现层处理。分类处理,利用AOP思想。
在表现层创建异常处理类 1 2 3 4 5 6 7 8 @RestControllerAdvice public class ProjectExceptionAdvice { @ExceptionHandler({Exception.class}) public Result doException (Exception ex) { System.out.println("出异常了" ); return new Result (50000 ,null ,"出异常了" ); } }
创建数据层异常类和业务层异常类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 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; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 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; } }
在异常处理类中添加处理方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 @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 (50000 ,null ,"出异常了" ); } }
修改数据层及业务层以实现异常处理 数据层 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public interface BookDao { @Insert("insert into tb_book values (null, #{type}, #{name}, #{description})") public int save (Book book) ; @Update("update tb_book set type=#{type}, name=#{name}, description=#{description} where id=#{id}") public int update (Book book) ; @Delete("delete from tb_book where id=#{id}") public int delete (Integer id) ; @Select("select * from tb_book where id=#{id}") public Book getById (Integer id) ; @Select("select * from tb_book;") public List<Book> getAll () ; }
业务层 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 @Service public class BookServiceImpl implements BookService { @Autowired private BookDao bookDao; public boolean save (Book book) { return bookDao.save(book) > 0 ; } public boolean update (Book book) { return bookDao.update(book) > 0 ; } public boolean delete (Integer id) { return bookDao.delete(id) > 0 ; } public Book getById (Integer id) { Book book = bookDao.getById(id); return book; } public List<Book> getAll () { List<Book> books = bookDao.getAll(); return books; } }
放行静态资源 添加支持设置 1 2 3 4 5 6 7 8 9 10 @Configuration public class SpringMvcSupport extends WebMvcConfigurationSupport { @Override protected void addResourceHandlers (ResourceHandlerRegistry registry) { registry.addResourceHandler("/pages/**" ).addResourceLocations("/pages/" ); registry.addResourceHandler("/css/**" ).addResourceLocations("/css/" ); registry.addResourceHandler("/js/**" ).addResourceLocations("/js/" ); registry.addResourceHandler("/plugins/**" ).addResourceLocations("/plugins/" ); } }
这个支持设置可以直接并入SpringMvcConfig
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Configuration @ComponentScan({"cola.controller","cola.config"}) @EnableWebMvc public class SpringMvcConfig implements WebMvcConfigurer { @Autowired private ProjectInterceptor projectInterceptor; @Override public void addResourceHandlers (ResourceHandlerRegistry registry) { registry.addResourceHandler("/pages/**" ).addResourceLocations("/pages/" ); registry.addResourceHandler("/css/**" ).addResourceLocations("/css/" ); registry.addResourceHandler("/js/**" ).addResourceLocations("/js/" ); registry.addResourceHandler("/plugins/**" ).addResourceLocations("/plugins/" ); } @Override public void addInterceptors (InterceptorRegistry registry) { registry.addInterceptor(projectInterceptor).addPathPatterns("/books" ,"/books/*" ); } }
加入扫描路径 1 2 3 4 5 @Configuration @ComponentScan({"cola.controller","cola.config"}) @EnableWebMvc public class SpringMvcConfig {}
前端部分 参见之前的BrandFinal项目,用element创建静态页面,用vue绑定模型,用axios发送ajax异步请求。
里面还实现了添加表单回显,如何设置表单恢复默认等等,,,,,,,懒得写了
需要注意的是要以REST风格写axios请求,复习一下template slot-scope=”scope”, scope.$index,,scope.row,response箭头函数也得复习一下,,
对了还要学一下Vue里函数方法怎么简化写,