SpringMVC
概念
SpringMVC是一种基于Java实现MVC模型的轻 量级Web框架
-
web开发的三层架构
-
mvc模式
入门案例
-
创建web工程(Maven)
调整工程目录 -
导入坐标(sevlet设置为provided,意味着该依赖项由目标环境(例如应用服务器或容器)提供,而不是由 Maven 解析和打包)
-
配置tomcat插件
-
定义处理请求的功能类并配置关系的映射关系(给一个调用名称)
@RequestMapping用于设置请求映射路径,与web访问的地址保持一致
- 参数绑定注解
- @RequestBody:适用于将请求体中的数据直接映射到方法参数上的对象
- @RequestParam:用于从请求参数中获取数据,通常用于处理 GET、POST 等请求中的查询参数。
- @PathVarible:用于从 URL 路径中获取数据,通常用于处理 RESTful 风格的请求。
- 参数绑定注解
-
设置请求映射的配置类,并指定扫描路径
-
配置加载服务器的配置抽象类并覆盖三个方法
- createServletApplicationContext():加载容器
- getServletMappings( ):设定哪些请求归springmvc处理
- createRootApplicationContext ( ):如果创建Servlet容器时需要加载非SpringMVC对应的bean,使用当前方法进行,
- 初始化容器对象、将配置注册到容器中、返回容器
- /表示所有的请求都跪springmvc处理
-
创建tomcat服务器测试:看能否运行、输入save后控制台有无输出
web.xml可以删掉
设置返回json数据,上面写上@ResponseBody说明这不是页面是响应体
分析
- 服务器的运行需要在容器中进行,以提供其所需的环境和资源管理的框架
- 创建WebApplicationContext对象的目的是为了管理和加载Web应用程序中的各种组件,包括控制器、服务、数据访问对象等。WebApplicationContext是Spring框架针对Web应用程序的上下文对象,它扩展了ApplicationContext接口,提供了特定于Web环境的功能和特性。
- WebApplicationContext 要放置在 ServletContext 中:为了实现在整个 Web 应用程序中共享和访问 Spring 容器的功能和特性。
bean加载控制
因为功能不同,要避免Spring错误的加载到SpringMVC的bean,所以要进行Controller加载控制与业务bean加载控制
- 方案一:pring加载的bean设定扫描范围为com . itheima,排除掉controller包内的bean
- excludeFilters:排除扫描路径中加载的bean,需要指定类别(type) 与具体项(classes)
- includeFilters:加载指定的bean,需要指定类别(type) 与具体项(classes)
- 方案二: Spring加载的bean设定扫描范围为精准范围,例如service包、dao包等虽然是自动代理,但是还是建议写全
- 方案三:不区分Spring与SpringMVC的环境,加载到同一个环境中 下图为简化开发模式,使用AbstractAnnotationConfigDispatcherServletInitializer
@ComponetScan具有传递性,如果扫描到的类里面有这个,扫到了controller,则会被重新添加
PostMan
请求与响应
解决路径同名冲突问题:设置模块名作为请求路径前缀
请求映射路径
@RequestMapping
原先
加路径前缀后
请求方式
普通参数
url地址传参,地址参数名与形参变量名相同,定义形参即可接收参数
Get请求
从服务器获取数据
http://localhost/commonParam?name=itcast&age=15
然后在controller层接收
名称相同才能映射
Post请求
用于向服务器提交数据
将参数放在请求正文中,相对于 GET 请求更安全,因为参数不会明文显示在 URL 上。
乱码处理
用generate(快捷键alt+insert)生成覆盖的方法
@RequestParam
绑定形参和实参之间的关系
P0J0类型参数
传递实体类对象
简单属性
- 创建实体类
- 在controller层中写接受属性的方法
- 如果属性名一样就可以自动装配
引用属性(嵌套)
- 创建被引用的属性类
- 在被传递的实体类对象中引用
- 定义
- 覆写getter、setter、tostring
- 实参上要加上前缀
数组类型参数
同名自动识别
集合类型参数
- 设置形参
- 前面加上@RequestParam,将参数指定为集合的数据而非集合的属性
json数据传参
json:以文本形式表示格式化的数据
- 导入json坐标辅助类型转换
- postman发json数据
- 开启json数据转化为对象的功能
- 将参数标记为Java对象:@RequestBody此注解一个处理器方法只能使用- -次
- @RequestBody与@RequestParam区别
- 区别
- @RequestParam用于接收ur1地址传参, 表单传参[application/ x-WWw- form-urlencoded]
- @RequestBody用于接收json数据[application/json]
- 应用
后期开发中,发送json格式数据为主,@RequestBody应用较广。如果发送非json格式数据,选用@RequestParam接收请求参数
- 区别
- @RequestBody与@RequestParam区别
日期型参数传递
(有格式的参数)
格式正确时
- controller层中提供请求方法:
- 请求用斜杠格式可以直接传递:由字符串转成date
格式不正确时
指定格式@DateTimeFormat()时间的格式是HH:mm:ss,日期的格式是yyyy:MM:dd,注意格式区分
converter接口
类型转换器
@DateTimeFormat()靠converter接口实现
有默认转换规则,有些转换没有自动开启,如果不能按规则转换就打开EnableWebMvc
响应方式
将处理完的结果反馈给用户
响应页面
跳转页面
写页面名称return
响应文本数据
要加@ResponseBody
响应json数据
把方法的返回值设成pojo再return;
加@ResponseBody将响应的对象由页面改为pojo
集合对象也同上
@RespnseBody
设置当前控制器返回值作为响应体
由HttpMessageConverter接口实现
Rest风格
简介
REST (Representational State Transfer) ,表现形式(即访问网络资源的格式)状态转换
- 传统风格资源描述形式
http: //localhost/user/getById?id=1
http: //localhost/user/ saveUser - REST风格描述形式
- REST风格描述形式
http://localhost/user/1
http://localhost/user
优点:
- 隐藏资源的访问行为, 无法通过地址得知对资源是何种操作
- 书写简化
区分
按照REST风格访问资源时使用行为动作区分对资源进行 了何种操作
上述行为是约定方式,约定不是规范,可以打破,所以称REST风格,而不是REST规范
描述模块的名称通常使用复数,也就是加s的格式描述,表示此类资源,而非单个资源,例如: users、 books、 accouns…
根据REST风格对资源进行访问称为RESTful
入门案例
- 统一RequestMapping
- 用RequestMapping的method()设定请求动作
传参:
- 使用路径变量@PathVariable指定变量来自路径
- 指定变量来自路径中的具体位置
三种接收参数方式区别
RESTful快速开发
- 把@RequestMapping放在最前面统一写
- 把@ResponseBody放在前面统一写
- @ResponseBody和@Controller可以合二为一成@RestController
- @PostMapping与@Reques tMapping( method = Reques tMethod. POST)等效
- 加上路径映射和参数绑定注解@RequestBody
案例
基于RESTfu1页面数据交互
-
添加javax.servlet、spirng和json的依赖项以及maven的插件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>practice-02</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>practice-02 Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>7.8.0</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.10.RELEASE</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>7.8.0</version> <scope>compile</scope> </dependency> </dependencies> <build> <finalName>practice-02</finalName> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.1</version> <configuration> <port>80</port> <path>/</path> </configuration> </plugin> </plugins> </build> </project>
-
基础配置
-
SpringMvcConfig.java
package com.itheima.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan("com.itheima.controller") public class SpringMvcConfig { }
-
web容器的配置类ServletContainerslnitConfig.java
package com.itheima.config; import org.springframework.web.filter.CharacterEncodingFilter; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; import javax.servlet.Filter; public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer { protected Class<?>[] getRootConfigClasses() { return new Class[0]; } 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}; } }
-
领域层domain(处理业务逻辑、定义业务实体和规则)
- book:name和price的get和set,以及tostring的覆写
- User:同上
-
-
制作表现层接口(controller)使用postman测通
- GET:从服务器获取资源。
- POST:将数据提交给服务器,用于创建新的资源。
- PUT:向服务器发送数据,用于更新现有资源。
- DELETE:删除服务器上的资源。
参数前需要加@RequestBody将请求体中的数据自动解析为方法参数的值。
-
拷入页面,放入web.app下运行
放行非springmvc的请求:所有页面都会被springmvc拦截,识别成配置,应该修改成静态资源放行不被springmvc拦截- 在config中创建SpringMvcSupport.java支持类添加资源过滤
- 添加addResourceHandler方法,当访问/pages/???时候,走/pages 目录下的内容
- 让springmvc启动时加载此页面:添加@Configuration做成配置类,加入到springmvcconfig.java的扫描路径中
-
绑定页面与功能:在页面上通过vue发送AJAX异步提交,访问表现层接口,能发送数据并回显
- 主页列表查询
- 对后台发送AJAX请求(方法类型要与请求类型相对应)
- 得到返回的数据与html页面中的数据绑定
-
添加(发送post请求):
找到要发送的参数的名字,来明确要发送的对象
<!DOCTYPE html> <html> <head> <!-- 页面meta --> <meta charset="utf-8"> <title>SpringMVC案例</title> <!-- 引入样式 --> <link rel="stylesheet" href="../plugins/elementui/index.css"> <link rel="stylesheet" href="../plugins/font-awesome/css/font-awesome.min.css"> <link rel="stylesheet" href="../css/style.css"> </head> <body class="hold-transition"> <div id="app"> <div class="content-header"> <h1>图书管理</h1> </div> <div class="app-container"> <div class="box"> <div class="filter-container"> <el-input placeholder="图书名称" style="width: 200px;" class="filter-item"></el-input> <el-button class="dalfBut">查询</el-button> <el-button type="primary" class="butT" @click="openSave()">新建</el-button> </div> <el-table size="small" current-row-key="id" :data="dataList" stripe highlight-current-row> <el-table-column type="index" align="center" label="序号"></el-table-column> <el-table-column prop="type" label="图书类别" align="center"></el-table-column> <el-table-column prop="name" label="图书名称" align="center"></el-table-column> <el-table-column prop="description" label="描述" align="center"></el-table-column> <el-table-column label="操作" align="center"> <template slot-scope="scope"> <el-button type="primary" size="mini">编辑</el-button> <el-button size="mini" type="danger">删除</el-button> </template> </el-table-column> </el-table> <div class="pagination-container"> <el-pagination class="pagiantion" @current-change="handleCurrentChange" :current-page="pagination.currentPage" :page-size="pagination.pageSize" layout="total, prev, pager, next, jumper" :total="pagination.total"> </el-pagination> </div> <!-- 新增标签弹层 --> <div class="add-form"> <el-dialog title="新增图书" :visible.sync="dialogFormVisible"> <el-form ref="dataAddForm" :model="formData" :rules="rules" label-position="right" label-width="100px"> <el-row> <el-col :span="12"> <el-form-item label="图书类别" prop="type"> <el-input v-model="formData.type"/> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="图书名称" prop="name"> <el-input v-model="formData.name"/> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="24"> <el-form-item label="描述"> <el-input v-model="formData.description" type="textarea"></el-input> </el-form-item> </el-col> </el-row> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="dialogFormVisible = false">取消</el-button> <el-button type="primary" @click="saveBook()">确定</el-button> </div> </el-dialog> </div> </div> </div> </div> </body> <!-- 引入组件库 --> <script src="../js/vue.js"></script> <script src="../plugins/elementui/index.js"></script> <script type="text/javascript" src="../js/jquery.min.js"></script> <script src="../js/axios-0.18.0.js"></script> <script> var vue = new Vue({ el: '#app', data:{ dataList: [],//当前页要展示的分页列表数据 formData: {},//表单数据 dialogFormVisible: false,//增加表单是否可见 dialogFormVisible4Edit:false,//编辑表单是否可见 pagination: {},//分页模型数据,暂时弃用 }, //钩子函数,VUE对象初始化完成后自动执行 created() { this.getAll(); }, methods: { // 重置表单 resetForm() { //清空输入框 this.formData = {}; }, // 弹出添加窗口 openSave() { this.dialogFormVisible = true; this.resetForm(); }, //添加 saveBook () { axios.post("/books",this.formData).then((res)=>{ }); }, //主页列表查询 getAll(){ axios.get("/books").then((res)=>{ this.dataList= res.data; }) } } }) </script> </html>
SSM整合
步骤:
创建工程
-
建立模块结构
-
添加jar包和tomcat插件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.itheima</groupId> <artifactId>Project-03</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <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> <!--spring-mybatis依赖--> <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> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.16</version> </dependency> <!--测试依赖--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <!--Jackson框架依赖(实现Java对象和JSON数据的相互转换)--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.0</version> </dependency> </dependencies> <!--Tomcat插件--> <build> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.1</version> <configuration> <port>80</port> <path>/</path> </configuration> </plugin> </plugins> </build> </project>
项目设置-spring框架-mybatis-mysql-druid数据源-junit测试框架servlet容器-tomcat插件
-
创建对应的包
SSM整合
写好配置包
Spring
springconfig.java
package com.itheima.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@ComponentScan({"com.itheima.service"})
@Import({JdbcConfig.class, MybatisConfig.class})
@EnableTransactionManagement
public class SpringConfig {
}
在springconfig.java中用propertysource挂上
导入另外两个配置类
Mybatis
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm_db
jdbc.username=root
jdbc.password=Angel22
jdbcconfig.java
-
造datasource数据源
-
设置set,定义成员变量,从jdbc.properties中注入信息
要设置成driverClass而不是driver(driver"是指数据库驱动程序本身,是一个包含所有与特定数据库系统进行通信所需功能的Java类库。"driver"中的"driverClass"是"driver"中的一个具体实现类,用于实现数据库连接和交互的功能。)
-
定义成bean
package com.itheima.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;
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.java
- sqlSessionFactory:注入datasource(添加到方法参数中)
- MapperScannerConfigurer(映射扫描):指定映射从哪里加载
package com.itheima.config;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;
public class MybatisConfig {
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);//注入数据
factoryBean.setTypeAliasesPackage("com.itheima.domain");//设置别名
return factoryBean;
}
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setBasePackage("com.itheima.dao");
return mapperScannerConfigurer;
}
}
SpringMvc
ServletConfig.java
Web容器配置类
package com.itheima.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
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[]{"/"};
}
}
注意要定义为protected:
- 允许继承并重写以满足特定应用程序的需求
- 对外部代码不可见提高安全性
SpingMvcConfig.java
package com.itheima.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@ComponentScan("com.itheima.controller")
@EnableWebMvc
public class SpringMvcConfig {
}
功能模块
表与实体类
造表
造对象
造表映射过去的pojo对象,get,set和tostring
package com.itheima.domain;
public class Book {
private Integer id;
private String type;
private String name;
private String description;
@Override
public String toString() {
return "Book{" +
"id=" + id +
", type='" + type + '\'' +
", name='" + name + '\'' +
", description='" + description + '\'' +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
造数据访问层、业务层和表现层
dao(接口+自动代理)
dao层写增删改查,用mybatis自动代理实现
package com.itheima.dao;
import com.itheima.domain.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 BookDao {
// 保存
@Insert("insert into tbl_book (type,name,description) values(#{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 where id=#{id}")
public Book getById(Integer id);
// 查找全部
@Select("select * from tbl_book")
public List<Book> getAll();
}
@Insert("insert into tbl_book values(null, #{type}, #{name}, #{description})")
适用于对象中的属性顺序与表中列的顺序完全一致的情况。@Insert("insert into tbl_book (type, name, description) values(#{type}, #{name}, #{description})")
适用于对象中的属性顺序与表中列的顺序不一致,或者只插入表中的部分列的情况。
#{type}
、#{name}
、#{description}
分别表示对应对象中的属性值。
service(接口+实现类)
业务层
-
service接口:把void改为boolean类型返回值代表执行结果,要加文档注释!
@param表示参数,@return表示返回结果
package com.itheima.service; import com.itheima.domain.Book; import java.util.List; public interface BookService { /** * 保存 * @param book * @return */ public boolean save(Book book); /** * 修改 * @param book * @return */ public boolean update (Book book); /** * 按id删除 * @param id * @return */ public boolean delete(Integer id); /** * 按id查询 * @param id * @return */ public Book getById(Integer id); /** * 查询全部 * @return */ public List<Book> getAll(); }
-
service实现类
-
注入dao接口
-
使用@Autowired自动装配,修改一下配置消除报错
-
写业务处理逻辑
package com.itheima.service.impl; import com.itheima.dao.BookDao; import com.itheima.domain.Book; import com.itheima.service.BookService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @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) { return bookDao.getById(id); } public List<Book> getAll() { return bookDao.getAll(); } } package com.itheima.service.impl; import com.itheima.dao.BookDao; import com.itheima.domain.Book; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class BookServiceImpl { @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) { return bookDao.getById(id); } public List<Book> getAll() { return bookDao.getAll(); } }
-
controller
写表现层controller
-
@RestController和RequestMapping(“/books”)
-
@Autowired,写数据处理逻辑
-
写好请求Method,前面用@PostMapping映射路径(Restful风格 )
package com.itheima.controller; import com.itheima.domain.Book; import com.itheima.service.BookService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping("/books") public class BookController { @Autowired private BookService bookService; @PostMapping public boolean save(@RequestBody Book book) { return bookService.save(book); } @PutMapping public boolean update(@RequestBody Book book) { return bookService.update(book); } @DeleteMapping("/{id}") public boolean delete(@PathVariable Integer id) { return bookService.delete(id); } @GetMapping("/{id}") public Book getById(@PathVariable Integer id) { return bookService.getById(id); } @GetMapping public List<Book> getAll() { return bookService.getAll(); } }
测试
业务层接口测试(整合JUnit)
- 创建测试类
- Spring整合JUnit
@Runwith(SpringJUnit4ClassRunner.class)
指定配置类@ContextConfiguration(classes = SpringConfig.class)
- 写测试方法
- 最后点左边绿箭头运行
表现层接口测试(使用Postman)
- 点击右上角运行
- 使用postman发送post数据看结果对不对
事务处理
开启注解事务驱动
在springconfig.java中开启
配置事务管理器
应该写在数据源对象那里,这里是jdbcconfig.java
注意dataSource要用注解调用不能用方法调用
添加事务配到接口上
在业务层接口加@Transactional
具体事务具体再配
表现层数据封装
前端接收数据格式一创建结果模型类, 封装数据到message(msg属性中
(前后端通讯协议)
code代表是什么操作(增删改)
表现层数据封装——设置统一数据返回结果类
public class
Result {
private Object data;//数据
private Integer code ;//编码
private String msg;//消息
}
Result类中的字段并不是固定的,可以根据需要自行增减
提供若干个构造方法,方便操作
程序实现
Result.java
在表现层定义Result.java,描述统一格式中的数据
定义字段,写get和set方法以及构造方法,多定义几个增加灵活性
构造方法的参数的习惯是先写code再写数据,一般有下图中的后两个就可以了
Code.java
要定义为常量,一般是1代表成功,0代表失败
static
用于声明静态成员,而final
用于声明不可变的常量。通过将static
和final
修饰符应用于变量,可以创建静态常量,并在程序中保持其不可变性和可访问性。
BookController.java
把BookController.java中方法的返回类型改为Result来封装
package com.itheima.controller;
import com.itheima.domain.Book;
import com.itheima.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@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> bookList = bookService.getAll();
Integer code = bookList != null ? Code.GET_OK : Code.GET_ERR;
String msg = bookList != null ? "" : "数据查询失败,请重试!";
return new Result(code,bookList,msg);
}
}
注意getAll()方法中是判断bookList是否为空,不是book,因为有可能数据查询结果本身为空
ic 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> bookList = bookService.getAll();
Integer code = bookList != null ? Code.GET_OK : Code.GET_ERR;
String msg = bookList != null ? "" : "数据查询失败,请重试!";
return new Result(code,bookList,msg);
}
}
注意getAll()方法中是判断bookList是否为空,不是book,因为有可能数据查询结果本身为空
return 后面要加new表示实例化一个Result类