SSM整合开发配置
配置类作用
web(controller springmvc) 业务逻辑层 数据访问层(mybatis)
web->业务逻辑层->数据访问层->数据源(连接池)->数据库(book表)
spring框架负责把三层架构中的所有对象的创建 以及属性的赋值
SSM整合流程
-
创建工程
-
SSM整合(配置文件版)
-
功能模块
- 表与实体类
- dao(接口+自动代理)
- service(接口+实现类)
- 业务层接口测试(整合JUnit)
- controller
- 表现层接口测试(PostMan)
创建工程,添加依赖和插件
<dependencies>
<!--springmvc的依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<!--spring事务管理器要使用的依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!--spring整合myabtis依赖-->
<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>5.1.47</version>
</dependency>
<!--druid连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
<!--小辣椒-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
<!--json的转换包 @RequestBody @ResponseBody-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>
Spring整合Mybatis
-- 创建ssm_db数据库
CREATE DATABASE IF NOT EXISTS ssm_db CHARACTER SET utf8;
-- 使用ssm_db数据库
USE ssm_db;
-- 创建tbl_book表
CREATE TABLE tbl_book(
id INT PRIMARY KEY AUTO_INCREMENT, -- 图书编号
`type` VARCHAR(100), -- 图书类型
`name` VARCHAR(100), -- 图书名称
description VARCHAR(100) -- 图书描述
);
-- 添加初始化数据
INSERT INTO tbl_book VALUES(NULL,'计算机理论','Spring实战 第5版','Spring入门经典教材,深入理解Spring原理技术内幕');
INSERT INTO tbl_book VALUES(NULL,'计算机理论','Spring 5核心原理与30个类手写实战','十年沉淀之作,手写Spring精华思想');
INSERT INTO tbl_book VALUES(NULL,'计算机理论','Spring 5设计模式','深入Spring源码剖析,Spring源码蕴含的10大设计模式');
INSERT INTO tbl_book VALUES(NULL,'市场营销','直播就该这么做:主播高效沟通实战指南','李子柒、李佳琦、薇娅成长为网红的秘密都在书中');
INSERT INTO tbl_book VALUES(NULL,'市场营销','直播销讲实战一本通','和秋叶一起学系列网络营销书籍');
INSERT INTO tbl_book VALUES(NULL,'市场营销','直播带货:淘宝、天猫直播从新手到高手','一本教你如何玩转直播的书,10堂课轻松实现带货月入3W+');
jdbc.properties属性文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///ssm_db
jdbc.username=root
jdbc.password=root
web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!--
application 往里面放值 修改值 删除值
session 往里面放值 修改值 删除值 钝化 活化
request 往里面放值 修改值 删除值
tomcat容器一启动 就会创建 该项目关联的application对象 一旦application对象 被创建 则ContextLoaderListener就开始工作
它会自动读取配置在WEB-INF中的applicationContext.xml 如果你的配置文件不在WEB-INF中 我们就需要告知 你的applicationContext.xml
-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>xx</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>xx</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--
创建德鲁伊对象
-->
<bean id="dss" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${jdbc.name}"/>
<property name="password" value="${jdbc.pwd}"/>
<property name="driverClassName" value="${jdbc.driverclass}"/>
<property name="url" value="${jdbc.url}"/>
</bean>
<!--
创建sqlsessionfacroty的对象
-->
<bean id="sss" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dss"/>
<!--
给com.tyhxzy.entity下面的所有类起别名 别名就是类名首字母小写
-->
<property name="typeAliasesPackage" value="com.tyhxzy.entity"/>
<!--
将映射文件加载进来
-->
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
</bean>
<!--
创建数据访问层对象
<property name="basePackage" value="数据访问层接口所在的包名"/>
<property name="sqlSessionFactoryBeanName" value="sqlsessionfacrpty的对象名"/>
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.tyhxzy.mapper"/>
<property name="sqlSessionFactoryBeanName" value="sss"/>
</bean>
<!--
扫描注解 创建业务逻辑性对象 以及实现将数据访问层对象注入给业务逻辑层的属性
-->
<context:component-scan base-package="com.tyhxzy.service.impl"/>
</beans>
springmvc.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--
.noHandlerFound No mapping for GET /pp/book/find
-->
<context:component-scan base-package="com.tyhxzy.controller"/>
<!--
创建处理器映射器 处理器适配器
-->
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
mybatis-config.xml
2 功能模块开发
创建数据源对象 在applicationContext.xml
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--
创建德鲁伊对象
-->
<bean id="dss" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${jdbc.name}"/>
<property name="password" value="${jdbc.pwd}"/>
<property name="driverClassName" value="${jdbc.driverclass}"/>
<property name="url" value="${jdbc.url}"/>
</bean>
数据层开发(BookDao)
Book实体类
package com.tyhxzy.entity;
import lombok.Data;
@Data
public class Book {
private Integer id;
private String type;
private String name;
private String desc;
}
BookMapper接口
package com.tyhxzy.dao;
import com.tyhxzy.entity.Book;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;
public interface BookMapper {
package com.tyhxzy.mapper;
import com.tyhxzy.entity.Book;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface BookMapper {
List<Book> findall(String name);
@Insert("insert into book values(null,#{type},#{name},#{desc})")
int saveBook(Book book);
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.tyhxzy.mapper.BookMapper">
<select id="findall" resultType="book">
select * from book
<where>
<if test="name!='all'">
name like concat('%',#{name},'%')
</if>
</where>
</select>
</mapper>
业务层开发(BookService/BookServiceImpl)
BookService接口
package com.tyhxzy.service;
import com.tyhxzy.entity.Book;
import java.util.List;
public interface BookService {
List<Book> selectAll(String name);
int saveBook(Book book);
}
BookServiceImpl实现类
@Service
public class BookServiceImpl implements BookService {
@Autowired
private BookMapper bookMapper;
@Override
public List<Book> selectAll(String name) {
return bookMapper.findall(name);
}
@Override
public int saveBook(Book book) {
return bookMapper.saveBook(book);
}
}
表现层开发(BookController)
package com.tyhxzy.controller;
import com.tyhxzy.entity.Book;
import com.tyhxzy.service.BookService;
import com.tyhxzy.util.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
//@ResponseBody+@Controller
@RestController
@RequestMapping("/book")
// 取消跨域限制
@CrossOrigin
public class BookController {
@Autowired
private BookService bookService;
@RequestMapping("/find")
public R find(@RequestParam(value = "aa",required = false,defaultValue = "all") String name){
List<Book> books = bookService.selectAll(name);
if(books==null){
R r = new R(false,"查询失败",null);
return r;
}else{
R r = new R(true,"查询成功",books);
return r;
}
}
@RequestMapping("/save")
public R save(@RequestBody Book book){
int res= bookService.saveBook(book);
if(res>0) {
R r = new R(true, "保存成功", null);
return r;
}else{
R r = new R(false, "保存失败", null);
return r;
}
}
}
postman测试表现层接口
表现层数据封装
表现层响应数据的问题
问题:我们表现层增删改方法返回true或者false表示是否成功,getById()方法返回一个json对象,getAll()方法返回一个json对象数组,这里就出现了三种格式的响应结果,极其不利于前端解析。
解决:我们需要统一响应结果的格式
定义Result类封装响应结果
package com.tyhxzy.entity;
import lombok.Data;
@Data
public class Result {
private Integer code; //状态码, 代表本次请求成功还是失败 1000010
private Object data; //数据,请求成功携带的数据
private String msg ; //消息说明。
public Result() {
}
public Result(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Result(Integer code, Object data, String msg) {
this.code = code;
this.data = data;
this.msg = msg;
}
}
注意事项:
Result类中的字段并不是固定的,可以根据需要自行增减
Code类封装响应码
package com.tyhxzy.domain;
//状态码
public interface Code {
Integer SAVE_OK = 20011;
Integer DELETE_OK = 20021;
Integer UPDATE_OK = 20031;
Integer GET_OK = 20041;
Integer SAVE_ERR = 20010;
Integer DELETE_ERR = 20020;
Integer UPDATE_ERR = 20030;
Integer GET_ERR = 20040;
}
注意事项:
Code类的常量设计也不是固定的,可以根据需要自行增减,例如将查询再进行细分为GET_OK,GET_ALL_OK,GET_PAGE_OK
表现层数据封装返回Result对象
package com.tyhxzy.controller;
import com.tyhxzy.entity.Book;
import com.tyhxzy.entity.Code;
import com.tyhxzy.entity.Result;
import com.tyhxzy.service.BookService;
import org.apache.ibatis.annotations.Delete;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.List;
//@Controller //把该类变成一个controller
@RestController //@RestController作用: 1. 会把该类变成contrller, 2. 所有方法的返回值都是json
@RequestMapping("/books")
public class BookController {
@Autowired
private BookService bookService;
/**
* 添加图书
* restful风格对于增加使用post的请求方式
* @param book
* @return
*/
@PostMapping
public Result save(@RequestBody Book book){
boolean result = bookService.save(book);
if(result){
return new Result(Code.SAVE_OK,"添加成功");
}else{
return new Result(Code.SAVE_ERR,"添加失败");
}
}
/**
* 删除图书
* restful风格对于删除使用delete的请求方式
* @param id
* @return
*
* restFul传参
* 对于get与delete的请求不能使用json传参,只能使用路径传参
* post与put可以使用json传参。
*/
@DeleteMapping("/{id}")
public Result delete(@PathVariable Integer id){
boolean result = bookService.delete(id);
if(result){
return new Result(Code.DELETE_OK,"删除成功");
}else{
return new Result(Code.DELETE_ERR,"删除失败");
}
}
/**
* 修改图书
* restful风格对于增加使用put的请求方式
* @param book
* @return
*/
@PutMapping
public Result update(@RequestBody Book book){
boolean result = bookService.update(book);
if(result){
return new Result(Code.UPDATE_OK,"更新成功");
}else{
return new Result(Code.UPDATE_ERR,"更新失败");
}
}
/**
* 查询单个图书
* restful风格对于查询使用get的请求方式
* @param id
* @return
*/
@GetMapping("/{id}")
public Result findById(@PathVariable("id") Integer id){
Book book = bookService.getById(id);
if(book!=null){
return new Result(Code.GET_OK,book,"查询成功");
}else{
return new Result(Code.GET_ERR,book,"查询失败");
}
}
/**
* 查询所有图书
* restful风格对于查询使用get的请求方式
* @return
*/
@GetMapping
public Result findById(){
List<Book> bookList = bookService.getAll();
if(bookList!=null&&bookList.size()>0){
return new Result(Code.GET_OK,bookList,"查询成功");
}else{
return new Result(Code.GET_ERR,bookList,"查询失败");
}
}
}
-
统一表现层的返回值结果是作用是什么?
- 前后端分离开发的情况下,前端人员不清楚后端人员controller的返回值是什么会给前端人员造成困扰,所以我们就统一返回值结果。让前后端开发人员根据有默契
-
Result对象的每一个字段代表什么意思?
- code : 状态码,表示请求成功还是失败
- data 请求成功返回的数据
- msg 状态码的消息说明