Springmvc学习笔记

SpringMVC

概念

SpringMVC是一种基于Java实现MVC模型的轻 量级Web框架

  • web开发的三层架构image-20230607094228636

  • mvc模式image-20230607094318919

    image-20230607094452641

入门案例

image-20230607094611470

  1. 创建web工程(Maven)image-20230607102435048
    调整工程目录image-20230607094733059

  2. 导入坐标(sevlet设置为provided,意味着该依赖项由目标环境(例如应用服务器或容器)提供,而不是由 Maven 解析和打包)image-20230607094958125

  3. 配置tomcat插件image-20230607095027318

  4. 定义处理请求的功能类并配置关系的映射关系(给一个调用名称)image-20230607095408719

    @RequestMapping用于设置请求映射路径,与web访问的地址保持一致

    • 参数绑定注解
      • @RequestBody:适用于将请求体中的数据直接映射到方法参数上的对象
      • @RequestParam:用于从请求参数中获取数据,通常用于处理 GET、POST 等请求中的查询参数。
      • @PathVarible:用于从 URL 路径中获取数据,通常用于处理 RESTful 风格的请求。
  5. 设置请求映射的配置类,并指定扫描路径image-20230607095634045

  6. 配置加载服务器的配置抽象类并覆盖三个方法

    • createServletApplicationContext():加载容器
    • getServletMappings( ):设定哪些请求归springmvc处理
    • createRootApplicationContext ( ):如果创建Servlet容器时需要加载非SpringMVC对应的bean,使用当前方法进行,
    1. image-20230607100931712
    2. image-20230607100817224初始化容器对象、将配置注册到容器中、返回容器
    3. image-20230607100855522/表示所有的请求都跪springmvc处理
  7. 创建tomcat服务器image-20230607101007966测试:看能否运行、输入save后控制台有无输出

web.xml可以删掉

设置返回json数据,上面写上@ResponseBody说明这不是页面是响应体image-20230607104948896

image-20230607101756294

分析

image-20230607105151632

  1. 服务器的运行需要在容器中进行,以提供其所需的环境和资源管理的框架
  2. 创建WebApplicationContext对象的目的是为了管理和加载Web应用程序中的各种组件,包括控制器、服务、数据访问对象等。WebApplicationContext是Spring框架针对Web应用程序的上下文对象,它扩展了ApplicationContext接口,提供了特定于Web环境的功能和特性。
  • WebApplicationContext 要放置在 ServletContext 中:为了实现在整个 Web 应用程序中共享和访问 Spring 容器的功能和特性。

image-20230607143623382

bean加载控制

因为功能不同,要避免Spring错误的加载到SpringMVC的bean,所以要进行Controller加载控制与业务bean加载控制

  • 方案一:pring加载的bean设定扫描范围为com . itheima,排除掉controller包内的beanimage-20230607144530380
    • excludeFilters:排除扫描路径中加载的bean,需要指定类别(type) 与具体项(classes)
    • includeFilters:加载指定的bean,需要指定类别(type) 与具体项(classes)
  • 方案二: Spring加载的bean设定扫描范围为精准范围,例如service包、dao包等image-20230607144252293虽然是自动代理,但是还是建议写全
  • 方案三:不区分Spring与SpringMVC的环境,加载到同一个环境中 下图为简化开发模式,使用AbstractAnnotationConfigDispatcherServletInitializer
    image-20230607145116460

@ComponetScan具有传递性,如果扫描到的类里面有这个image-20230607152300707,扫到了controller,则会被重新添加

PostMan

image-20230607155112406

请求与响应

解决路径同名冲突问题:设置模块名作为请求路径前缀

请求映射路径

@RequestMapping

原先image-20230607155438368
加路径前缀后image-20230607155600771

请求方式

普通参数

url地址传参,地址参数名与形参变量名相同,定义形参即可接收参数

Get请求

从服务器获取数据

http://localhost/commonParam?name=itcast&age=15

然后在controller层接收image-20230607160628942

名称相同才能映射

​ Post请求

用于向服务器提交数据

将参数放在请求正文中,相对于 GET 请求更安全,因为参数不会明文显示在 URL 上。

image-20230607160959970

乱码处理

用generate(快捷键alt+insert)生成覆盖的方法

image-20230607161254402

@RequestParam

绑定形参和实参之间的关系image-20230607163006814

P0J0类型参数

传递实体类对象

简单属性
  1. 创建实体类image-20230607163901753
  2. 在controller层中写接受属性的方法image-20230607163951045
  3. 如果属性名一样就可以自动装配image-20230607164112697
引用属性(嵌套)
  1. 创建被引用的属性类image-20230607164307742
  2. 在被传递的实体类对象中引用
    1. 定义image-20230607164512885
    2. 覆写getter、setter、tostring
    3. 实参上要加上前缀image-20230607164628787
数组类型参数

image-20230607164830892image-20230607164842412同名自动识别

集合类型参数
  1. 设置形参image-20230607164914377
  2. 前面加上@RequestParam,将参数指定为集合的数据而非集合的属性image-20230607165211527
json数据传参

json:以文本形式表示格式化的数据

  1. 导入json坐标辅助类型转换
  2. postman发json数据image-20230608085940415
  3. 开启json数据转化为对象的功能image-20230608090246554
  4. 将参数标记为Java对象:@RequestBodyimage-20230608090528944此注解一个处理器方法只能使用- -次
    • @RequestBody与@RequestParam区别
      • 区别
        • @RequestParam用于接收ur1地址传参, 表单传参[application/ x-WWw- form-urlencoded]
        • @RequestBody用于接收json数据[application/json]
      • 应用
        后期开发中,发送json格式数据为主,@RequestBody应用较广。如果发送非json格式数据,选用@RequestParam接收请求参数
日期型参数传递

(有格式的参数)

格式正确时
  1. controller层中提供请求方法:image-20230608091402283
  2. 请求用斜杠格式image-20230608091430088可以直接传递:由字符串转成date
格式不正确时

指定格式@DateTimeFormat()image-20230608091730047时间的格式是HH:mm:ss,日期的格式是yyyy:MM:dd,注意格式区分

image-20230608094247433

converter接口

类型转换器

@DateTimeFormat()靠converter接口实现

image-20230608092244355

有默认转换规则,有些转换没有自动开启,如果不能按规则转换就打开EnableWebMvc

响应方式

将处理完的结果反馈给用户

响应页面
跳转页面

写页面名称returnimage-20230608094500827

响应文本数据

image-20230608094611141要加@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风格访问资源时使用行为动作区分对资源进行 了何种操作

image-20230608110437026

上述行为是约定方式,约定不是规范,可以打破,所以称REST风格,而不是REST规范
描述模块的名称通常使用复数,也就是加s的格式描述,表示此类资源,而非单个资源,例如: users、 books、 accouns…

根据REST风格对资源进行访问称为RESTful

入门案例

image-20230608111018482

  1. 统一RequestMapping
  2. 用RequestMapping的method()设定请求动作

传参: image-20230608111308918

  1. 使用路径变量@PathVariable指定变量来自路径
  2. 指定变量来自路径中的具体位置
三种接收参数方式区别

image-20230608111555134

RESTful快速开发

  1. 把@RequestMapping放在最前面统一写image-20230608112141150
  2. 把@ResponseBody放在前面统一写
  3. @ResponseBody和@Controller可以合二为一成@RestController
  4. @PostMapping与@Reques tMapping( method = Reques tMethod. POST)等效image-20230608112430436
  5. 加上路径映射和参数绑定注解@RequestBody

案例

基于RESTfu1页面数据交互
  1. 添加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>
    
    
  2. 基础配置

    • 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:同上
  3. 制作表现层接口(controller)使用postman测通

    • GET:从服务器获取资源。
    • POST:将数据提交给服务器,用于创建新的资源。
    • PUT:向服务器发送数据,用于更新现有资源。
    • DELETE:删除服务器上的资源。

    image-20230608113943341参数前需要加@RequestBody将请求体中的数据自动解析为方法参数的值。image-20230608114112621image-20230608114155439

  4. 拷入页面,放入web.app下运行
    放行非springmvc的请求:所有页面都会被springmvc拦截,识别成配置,应该修改成静态资源放行不被springmvc拦截 image-20230608164002455

    1. 在config中创建SpringMvcSupport.java支持类添加资源过滤
    2. 添加addResourceHandler方法,当访问/pages/???时候,走/pages 目录下的内容
    3. image-20230608164329989image-20230608164358355让springmvc启动时加载此页面:添加@Configuration做成配置类,加入到springmvcconfig.java的扫描路径中
  5. 绑定页面与功能:在页面上通过vue发送AJAX异步提交,访问表现层接口,能发送数据并回显

    • 主页列表查询
    1. 对后台发送AJAX请求(方法类型要与请求类型相对应)
    2. 得到返回的数据与html页面中的数据绑定image-20230608165053190
    • 添加(发送post请求):

      找到要发送的参数的名字,来明确要发送的对象image-20230608165642596

      <!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整合

步骤:

创建工程

  1. 建立模块结构image-20230615110507947

  2. 添加jar包image-20230609143745895和tomcat插件image-20230609143815761

    <?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插件

  3. 创建对应的包image-20230609145450380

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
  1. 造datasource数据源

  2. 设置set,定义成员变量,从jdbc.properties中注入信息

    要设置成driverClass而不是driver(driver"是指数据库驱动程序本身,是一个包含所有与特定数据库系统进行通信所需功能的Java类库。"driver"中的"driverClass"是"driver"中的一个具体实现类,用于实现数据库连接和交互的功能。)

  3. 定义成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
  1. sqlSessionFactory:注入datasource(添加到方法参数中)
  2. 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 {

}

功能模块

表与实体类
造表

image-20230614115718611image-20230614115741035

造对象

造表映射过去的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实现类

    1. 注入dao接口

    2. 使用@Autowired自动装配,修改一下配置消除报错image-20230614183114478

    3. 写业务处理逻辑

      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

  1. @RestController和RequestMapping(“/books”)

  2. @Autowired,写数据处理逻辑

  3. 写好请求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)
  1. 创建测试类image-20230615104508990
  2. Spring整合JUnit@Runwith(SpringJUnit4ClassRunner.class)
    指定配置类@ContextConfiguration(classes = SpringConfig.class)
  3. 写测试方法image-20230615104810259
  4. 最后点左边绿箭头运行
表现层接口测试(使用Postman)
  1. 点击右上角运行image-20230615104950610
  2. 使用postman发送post数据image-20230615105017896看结果对不对

事务处理

开启注解事务驱动

在springconfig.java中开启

image-20230615105228552

配置事务管理器

应该写在数据源对象那里,这里是jdbcconfig.java

注意dataSource要用注解调用不能用方法调用image-20230615105626706

添加事务配到接口上

在业务层接口加@Transactionalimage-20230615105734050

具体事务具体再配

表现层数据封装

前端接收数据格式一创建结果模型类, 封装数据到message(msg属性中
(前后端通讯协议)

code代表是什么操作(增删改)

表现层数据封装——设置统一数据返回结果类

public class
Result {
private Object data;//数据
private Integer code ;//编码
private String msg;//消息
}

Result类中的字段并不是固定的,可以根据需要自行增减
提供若干个构造方法,方便操作

程序实现
Result.java

在表现层定义Result.java,描述统一格式中的数据

定义字段,写get和set方法以及构造方法,多定义几个增加灵活性
构造方法的参数的习惯是先写code再写数据,一般有下图中的后两个就可以了

image-20230615180011434

Code.java

要定义为常量,一般是1代表成功,0代表失败image-20230615175804362

static用于声明静态成员,而final用于声明不可变的常量。通过将staticfinal修饰符应用于变量,可以创建静态常量,并在程序中保持其不可变性和可访问性。

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类
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值