SSM学习——SSM整合案例(Spring+SpringMVC+Mybatis)(13)
这里写目录标题
- 要求
- Spirng整合Mybatis
- Spirng整合SpringMVC
- 表与实体类的创建
- 创建层级
- Dao层
- Service层
- controller层
- 接口测试
- 业务层`service`测试
- 表现层`controller`测试
- 表现层数据封装
- 定义前后端通信协议
- 异常处理
- 前端
- 配置访问
- 页面展示
- 拦截器
要求
Spirng整合Mybatis
基本的步骤就不说了,反正前面这么多案例了已经
现在,就把maven坐标与创建好的目录看一下
名字 | 实例名/插件名 |
---|---|
springmvc框架 | spring-webmvc |
spring操纵jdbc | spring-jdbc |
spring操纵test测试 | spring-test |
mybatis框架 | mybatis |
servlet技术(运行需要屏蔽,即provided) | javax.servlet-api |
json技术 | jackson-databind |
德鲁伊数据库连接池 | druid |
mybatis整合spring | mybatis-spring |
junit测试 | junit |
mysql驱动 | mysql-connector-java |
tomcat7插件(需要配端口与路径) | tomcat7-maven-plugin |
这里必须将characterEncoding=UTF-8
放在url参数第一位!
jdbc.properties
jdbc.classname=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/20220806lige?characterEncoding=UTF-8&useSSL=false&useServerPrepStmts=true&useUnicode=true
jdbc.username=root
jdbc.password=root
SpringConfig.java
配置类
JdbcConfig.java
配置类
package cn.calendo.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 {//把jdbc.properties里的变量引入(通过@Value注解形式)@Value("${jdbc.classname}")private String classname;@Value("${jdbc.url}")private String url;@Value("${jdbc.username}")private String username;@Value("${jdbc.password}")private String password;//收集连接池数据,整理成一个bean交给Spring管理@Beanpublic DataSource dataSource() {DruidDataSource druidDataSource = new DruidDataSource();druidDataSource.setDriverClassName(classname);druidDataSource.setUrl(url);druidDataSource.setUsername(username);druidDataSource.setPassword(password);return druidDataSource;}//事务控制器,整理成一个bean交给Spring管理@Beanpublic PlatformTransactionManager platformTransactionManager(DataSource dataSource) {DataSourceTransactionManager ds = new DataSourceTransactionManager();ds.setDataSource(dataSource);return ds;}
}
MybatisConfig.java
配置类
public class MybatisConfig {//开始造mybatis最渴望需要的工厂bean(又需要我们提供已造好的datasource),并启用类型别名(需要扫描pojo包)//这个datasource是在spring容器中自动帮我们装配好的(对,就是前面我们JdbcConfig设置好的datasource提交给spring容器处理好的)//返回一个工厂bean交给spring容器处理@Beanpublic SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSource);sqlSessionFactoryBean.setTypeAliasesPackage("cn.calendo.pojo");return sqlSessionFactoryBean;}//这个bean来指定从pojo类字段到dao层接口的映射,由于我们在dao中配的是接口,所以我们写到dao包即可@Beanpublic MapperScannerConfigurer mapperScannerConfigurer() {MapperScannerConfigurer msc = new MapperScannerConfigurer();msc.setBasePackage("cn.calendo.dao");return msc;}
}
Spirng整合SpringMVC
ServletConfig.java
配置类
public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {@Override//对于root,我们需要加载spring的核心配置类,当web容器启动时,getRootConfigClasses会加载SpringConfig里面的beanprotected Class<?>[] getRootConfigClasses() {return new Class[]{SpringConfig.class};}//由于SpringMVC是Spring的父容器,所以SpringMVC容器能访问Spring容器中的东西,而Spring容器不能访问SpringMVC容器中的东西@Override//对于web容器,我们需要加载springMvc的配置类,当web容器启动时,getServletConfigClasses会加载SpringMVCConfig里面的beanprotected Class<?>[] getServletConfigClasses() {return new Class[]{SpringMVCConfig.class};}@Override//springmvc需要拦截所有请求给自己处理,而不是给servlet一点机会protected String[] getServletMappings() {return new String[]{"/"};}//这里本来可以写过滤器,但是我们先不写吧
}
SpringMVCConfig.java
配置类
@Configuration
//他需要读取controller层的方法进行配置
@ComponentScan({"cn.calendo.controller"})
//必定开启功能强大的注解
@EnableWebMvc
public class SpringMVCConfig {}
表与实体类的创建
sql脚本:
use 20220806lige;drop table if exists tb_user;create table tb_user
(id int primary key auto_increment,username varchar(20),password varchar(20),gender varchar(8),address text
);INSERT INTO tb_user
VALUES (1, '张三', '123456', '男', '浙江,杭州');
INSERT INTO tb_user
VALUES (2, '李四', '123456', '女', '浙江,温州');
INSERT INTO tb_user
VALUES (3, '王五', '123456', '男', '江苏,苏州');
INSERT INTO tb_user
VALUES (4, '刘六', '123456', '女', '江苏,南京');
INSERT INTO tb_user
VALUES (5, '孙七', '123456', '男', '山东,青岛');
INSERT INTO tb_user
VALUES (6, '钱吧', '123456', '女', '山东,烟台');
INSERT INTO tb_user
VALUES (7, '阿猫', '123456haode', '无', '福建,厦门');
INSERT INTO tb_user
VALUES (8, '阿狗', '1234we56', '无', '广东,深圳');
INSERT INTO tb_user
VALUES (9, '阿信', 'hahaha123456', '女', '广东,广州');
INSERT INTO tb_user
VALUES (10, '阿文', 'wokao123456', '男', '上海');
好的现在表已经建好了
pojo
实体类
public class User {private Integer id;private String username;private String password;private String gender;private String address;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}//toString其实只是给我们调试用,其它没啥用的,但是我们都会加上它的@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", password='" + password + '\'' +", gender='" + gender + '\'' +", address='" + address + '\'' +'}';}
}
创建层级
Dao层
public interface UserDao {//md我们很懒我们写了接口然后不想自己写实现类,那就用mybatis的代理来帮我们创建这些实现类啊@Insert("insert into tb_user values(null, #{username}, #{password}, #{gender}, #{address})")public void add(User user);@Update("update tb_user set username = #{username}, password = #{password}, gender = #{gender}, address = #{address} where id = #{id}")public void update(User user);@Delete("delete from tb_user where id = #{id}")public void delete(Integer id);@Select("select * from tb_user where id = #{id}")public User selectById(Integer id);@Select("select * from tb_user")public List<User> selectAll();
}
Service层
UserService
实现类
public interface UserService {/*** 新增/保存* @param user* @return*/public boolean addUser(User user);/*** 修改/更新* @param user* @return*/public boolean updateUser(User user);/*** 删除/注销* @param user* @return*/public boolean deleteUser(User user);/*** 单个查询* @param id* @return*/public User selectUserById(Integer id);/*** 查询所有* @return*/public List<User> selectAllUser();
}
UserServiceImpl
实现类
//定义组件给SpringConfig扫描到
@Service
public class UserServiceImpl implements UserService {//由于自动装配了我们就没有new一个user对象,idea好心帮我们查了,但是这不是错误,把这个错误忽略即可//自动装配,不需要我们手动实例化@Autowiredprivate UserDao userDao;//然后我们需要调用Dao层的接口,把值传进去public boolean addUser(User user) {userDao.add(user);return true;}public boolean updateUser(User user) {userDao.update(user);return true;}public boolean deleteUser(Integer id) {userDao.delete(id);return true;}public User selectUserById(Integer id) {return userDao.selectById(id);}public List<User> selectAllUser() {return userDao.selectAll();}
}
controller层
UserController
//设置组件名,给springmvc加载,以及虚拟路径
@RestController
@RequestMapping("/users")
public class UserController {//也是自动装配,调用service层@Autowiredprivate UserService userService;//post请求,参数实体类,用json传数据@PostMappingpublic boolean addUser(@RequestBody User user) {return userService.addUser(user);}//put请求,参数实体类,用json传数据@PutMappingpublic boolean updateUser(@RequestBody User user) {return userService.updateUser(user);}//delete请求,参数id,用路径传递@DeleteMapping("/{id}")public boolean deleteUser(@PathVariable Integer id) {return userService.deleteUser(id);}//get请求,参数id,用路径传递@GetMapping("/{id}")public User selectUserById(@PathVariable Integer id) {return userService.selectUserById(id);}//get请求,无参数@GetMappingpublic List<User> selectAllUser() {return userService.selectAllUser();}
}
接口测试
在企业开发中,当我们写完业务层service
接口时需要进行junit测试
,以及写完表现层controller
接口时需要进行api-post
测试
业务层service
测试
//spring调用junit需要的引用类
//指定配置类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class UserServiceTest {@Autowiredprivate UserService userService;/*** 测试删除一个用户* @param id*/@Testpublic void testDeleteUser(Integer id){boolean user = userService.deleteUser(2);System.out.println(user);}/*** 测试根据id选择用户* @param id*/@Testpublic void testSelectUserById() {User user = userService.selectUserById(1);//正规测试需要做断言匹配System.out.println(user);}/*** 测试选择全部用户*/@Testpublic void testSelectAllUser() {List<User> ListUser = userService.selectAllUser();System.out.println(ListUser);}
}
表现层controller
测试
建立测试数据(delete不需要任何数据只要在url上添加数字即可(遵循rest风格))
如果数据库中文是问号?
那就在jdbc.properties后面加参数,示例:
jdbc.url=jdbc:mysql://localhost:3306/20220806lige?characterEncoding=UTF-8
成功
表现层数据封装
这就是前端与后端人员之间的通信协议
code代表操作的方法,以及成功与否1
成功0
失败
成功,数据都在data
里,失败,返回信息放在msg
里
定义前后端通信协议
package cn.calendo.controller;//定义前后端协议
public class Result {private Object data;public Integer code;private String msg;public Result() {}public Result(Object data, Integer code) {this.data = data;this.code = code;}public Result(Object data, Integer code, 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;}
}
然后在controller里新建一个code,java
来定义code码
package cn.calendo.controller;public class Code {public static final Integer SAVE_OK = 20011;public static final Integer UPDATE_OK = 20021;public static final Integer DELETE_OK = 20031;public static final Integer SELECT_OK = 20041;public static final Integer SAVE_ERR = 20010;public static final Integer UPDATE_ERR = 20020;public static final Integer DELETE_ERR = 20030;public static final Integer SELECT_ERR = 20040;
}
这时我们在UserController
里面所返回的值就需要改动了
package cn.calendo.controller;import cn.calendo.pojo.User;
import cn.calendo.service.UserService;
import com.alibaba.druid.support.json.JSONUtils;
import com.sun.org.apache.xml.internal.serializer.Serializer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.filter.CharacterEncodingFilter;import java.io.Serializable;
import java.util.List;//设置组件名,给springmvc加载,以及虚拟路径
@RestController
@RequestMapping("/users")
public class UserController {//也是自动装配,调用service层@Autowiredprivate UserService userService;//post请求,参数实体类,用json传数据@PostMappingpublic Result addUser(@RequestBody User user) {boolean flag = userService.addUser(user);return new Result(flag ? Code.SAVE_OK : Code.SAVE_ERR, flag);}//put请求,参数实体类,用json传数据@PutMappingpublic Result updateUser(@RequestBody User user) {boolean flag = userService.updateUser(user);return new Result(flag ? Code.UPDATE_OK : Code.UPDATE_ERR, flag);}//delete请求,参数id,用路径传递@DeleteMapping("/{id}")public Result deleteUser(@PathVariable Integer id) {boolean flag = userService.deleteUser(id);return new Result(flag ? Code.DELETE_OK : Code.DELETE_ERR, flag);}//get请求,参数id,用路径传递@GetMapping("/{id}")public Result selectUserById(@PathVariable Integer id) {User user = userService.selectUserById(id);Integer code = (user != null ? Code.SELECT_OK : Code.SELECT_ERR);String msg = (user != null ? "" : "数据查询失败!");return new Result(code, user, msg);}//get请求,无参数@GetMappingpublic Result selectAllUser() {List<User> ListUser = userService.selectAllUser();Integer code = (ListUser != null ? Code.SELECT_OK : Code.SELECT_ERR);String msg = (ListUser != null ? "" : "数据查询失败!");return new Result(code, ListUser, msg);}
}
测试之后,成功
异常处理
新建一个拦截异常类在controller层
//使用这个写好的aop
@RestControllerAdvice
public class ProjectExceptionAdvice {//此注解可以拦截指定异常@ExceptionHandler(Exception.class)public Result doException(Exception e) {System.out.println("拦截到异常");return new Result(404, null,"拦截到异常");}
}
新建异常包处理各种异常
package cn.calendo.exception;public class SystemException extends RuntimeException {private Integer code;public Integer getCode() {return code;}public SystemException(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;}public SystemException(Integer code, Throwable cause) {super(cause);this.code = code;}public SystemException(Integer code, String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {super(message, cause, enableSuppression, writableStackTrace);this.code = code;}
}
前端
配置访问
由于springmvc会把webapp里的东西全部拦截,所以我们需要放行
新建一个叫SpringMVCSupport
的访问放行配置
@Configuration
public class SpringMVCSupport extends WebMvcConfigurationSupport {@Overrideprotected 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
去扫描
@ComponentScan({"cn.calendo.controller", "cn.calendo.config"})
页面展示
我们写一下getAll即可获取到全部数据
然后把新增业务做出来
修改功能:
vue methods:
methods: {//列表getAll() {axios.get("/users").then((res) => {this.dataList = res.data.data;})},//弹出添加窗口handleCreate() {this.resetForm();this.dialogFormVisible = true;},//重置表单resetForm() {this.formData = {};},//添加handleAdd() {axios.post("/users", this.formData).then((res) => {if (res.data.code === 20011) {this.dialogFormVisible = false;this.$message.success("添加成功" + " " + "status: " + res.data.code);} else if (res.data.code === 20010) {this.$message.error("添加失败" + " " + "status: " + res.data.code);} else {this.$message.error(res.data.msg)}this.dialogFormVisible = false;this.getAll();}).finally(() => {this.getAll();});},//弹出编辑窗口handleUpdate(row) {axios.get("/users/" + row.id).then((res) => {if (res.data.code === 20041) {this.formData = res.data.data;this.dialogFormVisible4Edit = true;} else {this.$message.error(res.data.msg);}})},//编辑handleEdit() {axios.put("/users", this.formData).then((res) => {if (res.data.code === 20021) {this.dialogFormVisible4Edit = false;this.$message.success("修改成功" + " " + "status: " + res.data.code);} else if (res.data.code === 20020) {this.$message.error("修改失败" + " " + "status: " + res.data.code);} else {this.$message.error(res.data.msg)}this.dialogFormVisible4Edit = false;this.getAll();}).finally(() => {this.getAll();});},// 删除handleDelete(row) {this.$confirm("此操作永久删除当前数据,是否继续?", "警告", {type: 'info'}).then(() => {axios.delete("/users/" + row.id).then((res) => {if (res.data.code === 20031) {this.$message.success("删除成功" + " " + "status: " + res.data.code);} else if (res.data.code === 20030) {this.$message.error("删除失败" + " " + "status: " + res.data.code);} else {this.$message.error(res.data.msg);}}).finally(() => {this.getAll();});}).catch(() => {this.$message.info("取消删除");})}}
拦截器
springmvc独有的拦截器
和之前的转发一样的写法
先在springmvcConfig
里面写好能扫描到拦截器的路径
这是SpringMvcSupportConfig
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {@Autowiredprivate ProjectInterceptor projectInterceptor;@Overrideprotected void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");}@Overrideprotected void addInterceptors(InterceptorRegistry registry) {//配置拦截器registry.addInterceptor(projectInterceptor).addPathPatterns("/books", "/books/*");}
}
然后开始新建拦截器
拦截器
@Component
//定义拦截器类,实现HandlerInterceptor接口
//注意当前类必须受Spring容器控制
public class ProjectInterceptor implements HandlerInterceptor {@Override//原始方法调用前执行的内容//返回值类型可以拦截控制的执行,true放行,false终止public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String contentType = request.getHeader("Content-Type");HandlerMethod hm = (HandlerMethod)handler;System.out.println("preHandle..."+contentType);return true;}@Override//原始方法调用后执行的内容public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle...");}@Override//原始方法调用完成后执行的内容public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion...");}
}
其实在springmvcconfig
里面也可以直接继承WebMvcConfigurer
@Configuration
@ComponentScan({"com.itheima.controller"})
@EnableWebMvc
//实现WebMvcConfigurer接口可以简化开发,但具有一定的侵入性
public class SpringMvcConfig implements WebMvcConfigurer {@Autowiredprivate ProjectInterceptor projectInterceptor;@Autowiredprivate ProjectInterceptor2 projectInterceptor2;@Overridepublic void addInterceptors(InterceptorRegistry registry) {//配置多拦截器registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*");registry.addInterceptor(projectInterceptor2).addPathPatterns("/books","/books/*");}
}
SSM学习——SSM整合案例(Spring+SpringMVC+Mybatis)(13)相关推荐
- SSM三大框架整合(Spring+SpringMVC+MyBatis)
文章目录 SSM整合 一.导入依赖 1.1 Spring依赖 1.2 SpringMVC依赖 1.3 MyBatis依赖 二.配置文件 2.0 Web.xml 配置文件 2.1 Spring的配置文件 ...
- SSM实现学生管理系统(spring+springMVC+MyBatis)
SSM实现学生管理系统(spring+springMVC+MyBatis) 一.项目介绍 该项目是基于SSM框架实现的学生管理系统,能够对学生信息进行增删改查,分页查询,以及实现管理员的注册.登录 数 ...
- SSM纯注解后台代码整合(Spring+SpringMvc+Mybatis)
SSM后台整合(Spring+SpringMvc+Mybtis+事务+Rest风格+统一结果封装+统一异常处理+拦截器) 文章目录 1 基础环境搭建 1.1 建表 1.2 创建web项目 1.3 导入 ...
- SSM实战项目-员工管理系统 Spring+SpringMVC+MyBatis
项目描述: JavaWeb实战之员工管理系统,一个完整的SSM整合项目,适用于刚学完SSM框架的伙伴,熟练一下SSM整合,融会贯通.基本的增删改查都有,功能比较完善.使用框架并不是很难,关键是要理解起 ...
- SSM框架整合(Spring+SpringMVC+MyBatis)
输出结果 1.Maven Web项目创建 之前有写过Eclipse+Maven创建web项目的帖子,如果需要,请参考这里写链接内容 创建好项目之后因为入下图: 2.SSM整合 2.1 引入需要的JAR ...
- SSM框架整合(Spring+SpringMVC+MyBatis+Oracle)
1.开发环境搭建以及创建Maven Web项目 参看之前的博文:http://www.cnblogs.com/cainiaomahua/p/6306476.html 2.SSM整合 这次整合有2个配置 ...
- 超级详细配置SSM (Intellij idea + Maven + Spring + SpringMVC + MyBatis + c3p0 )
时间2018/12/31,使用的包都是最新的和用的人最多的QAQ. Maven仓库查找包的地址 https://mvnrepository.com/ 在经历了70多个小时的奋斗后(花了60个小时学习了 ...
- SSM整合(Spring + SpringMVC + Mybatis)
SSM所需要的依赖 <?xml version="1.0" encoding="UTF-8"?><project xmlns="ht ...
- ssm注解配置连接mysql_SSM框架整合(注解)-Spring+SpringMVC+MyBatis+MySql
准备工作: 下载整合所需的jar包 点击此处下载 使用MyBatis Generator生成dao接口.映射文件和实体类 如何生成 搭建过程: 先来看一下项目的 目录结构 1.配置dispatcher ...
- SSM框架——详细整合教程(Spring+SpringMVC+MyBatis)
登录 | 注册 收藏成功 确定 收藏失败,请重新收藏 确定 查看所有私信查看所有通知 暂没有新通知 想要绕过微信小程序开发中的坑吗?不妨来听这个,今晚8点,1小时帮你搞定! 14小时以前 CSDN日报 ...
最新文章
- 美法加三位科学家获2018诺贝尔物理学奖
- linux字体栅格化,响应式开发---网页的布局方式、媒体查询、栅格化布局、less语言...
- 转)使用C/C++扩展Python
- django批量修改table_django-formset实现数据表的批量操作
- Robots.txt 协议详解及使用说明
- Android + Appium 自动化测试完整的环境配置及代码详解
- 谈谈为什么要系统学习算法-开复的一篇文章
- rk3399_android7.1耳机拔插ADC检测
- log4j的使用 slf4j简单介绍
- 使用AStar算法解决八数码问题
- python wget_python wget下载文件处理的一些问题
- 手动批量下载ts文件并合并
- 远心镜头(Telecentric lens)原理介绍
- 计算机类绘图的文献,基于计算机CAD绘图探讨论文
- b站pink老师JavaScript的DOM案例代码——模拟京东快递单号查询
- 回给collapsar的信
- OCPC不起量该怎么办?从这四个方面着手,轻松起量
- MyBatis遇到:There is no getter for property named ‘Xxx‘ in ‘class xxx.xxx.Xxx‘问题
- 京林生态花园2021年(第三届)春节花展即将盛大开幕
- 在HashSet集合中添加三个Person对象,把姓名相同的人当作同一个人,禁止重复添加。 提示:Person类中定义name和age属性,重写hashCode()方法和equals()方法,针对Pe