创建工程

image.png

image.png

导入坐标

注意: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里函数方法怎么简化写,