三、SSM整合的项目实战

三、SSM整合的项目实战

1、需求

1、完成一个任务列表的增删改查功能

2、前端写好了vue的项目,差后端ssm

1、案例功能

1、如图

image-20240119004807586

2、前端提供的接口

1、学习计划分页查询接口

  • /* 
    需求说明
      查询全部数据页数据
    请求uri
      schedule/{pageSize}/{currentPage}
    请求方式 
      get   
    响应的json
      {
          "code":200,
          "flag":true,
          "data":{
              //本页数据
              data:
              [
              {id:1,title:'学习java',completed:true},
              {id:2,title:'学习html',completed:true},
              {id:3,title:'学习css',completed:true},
              {id:4,title:'学习js',completed:true},
              {id:5,title:'学习vue',completed:true}
              ], 
              //分页参数
              pageSize:5, // 每页数据条数 页大小
              total:0 ,   // 总记录数
              currentPage:1 // 当前页码
          }
      }
    */

2、学习计划删除接口

  • /* 
    需求说明
      根据id删除日程
    请求uri
      schedule/{id}
    请求方式 
      delete
    响应的json
      {
          "code":200,
          "flag":true,
          "data":null
      }
    */

3、学习计划保存接口

  • /* 
    需求说明
      增加日程
    请求uri
      schedule
    请求方式 
      post
    请求体中的JSON
      {
          title: '',
          completed: false
      }
    响应的json
      {
          "code":200,
          "flag":true,
          "data":null
      }
    */

4、学习计划修改接口

  • /* 
    需求说明
      根据id修改数据
    请求uri
      schedule
    请求方式 
      put
    请求体中的JSON
      {
          id: 1,
          title: '',
          completed: false
      }
    响应的json
      {
          "code":200,
          "flag":true,
          "data":null
      }
    */

3、前端环境的导入

1、环境

1、使用node:16.16.0版本

2、使用npm:9.x.x版本

  • 相当于是后端的maven。包管理工具

3、vscode

4、项目文件

1、C:\study\ssm\代码(1)\前端代码\vue3-demo2这个文件夹下

5、测试命令

1、npm install //安装依赖
2、npm run dev //运行测试

2、后端依赖整合和添加

1、先准备环境

1、数据库

1、数据表

CREATE TABLE schedule (
  id INT NOT NULL AUTO_INCREMENT,
  title VARCHAR(255) NOT NULL,
  completed BOOLEAN NOT NULL,
  PRIMARY KEY (id)
);

INSERT INTO schedule (title, completed)
VALUES
    ('学习java', true),
    ('学习Python', false),
    ('学习C++', true),
    ('学习JavaScript', false),
    ('学习HTML5', true),
    ('学习CSS3', false),
    ('学习Vue.js', true),
    ('学习React', false),
    ('学习Angular', true),
    ('学习Node.js', false),
    ('学习Express', true),
    ('学习Koa', false),
    ('学习MongoDB', true),
    ('学习MySQL', false),
    ('学习Redis', true),
    ('学习Git', false),
    ('学习Docker', true),
    ('学习Kubernetes', false),
    ('学习AWS', true),
    ('学习Azure', false);

2、实体类

1、Schedule类

package com.atguigu.pojo;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;

/**
 * projectName: com.atguigu.pojo
 *
 * description: 任务实体类
 */
@Data
public class Schedule {

    private Integer id;
    @NotBlank
    private String title;
    @NotNull
    private Boolean completed;
}

3、工具类

1、PageBean.java

  • 1、作用:分页

  • 2、代码

  • package com.atguigu.utils;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    import java.util.List;
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class PageBean {
      private int currentPage;   // 当前页码
      private int pageSize;      // 每页显示的数据量
      private long total;    // 总数据条数
      private List data;      // 当前页的数据集合
    }
    

2、R.java

  • 1、作用:返回结果集

  • 2、代码

  • package com.atguigu.utils;
    
    import lombok.Data;
    
    /**
    * projectName: com.atguigu.utils
    *
    * description: 返回结果类
    */
    @Data
    public class R {
    
      private int code = 200; //200成功状态码
    
      private boolean flag = true; //返回状态
    
      private Object data;  //返回具体数据
    
      public  static R ok(Object data){
          R r = new R();
          r.data = data;
          return r;
      }
    
      public static R  fail(Object data){
          R r = new R();
          r.code = 500; //错误码
          r.flag = false; //错误状态
          r.data = data;
          return r;
      }
    
      public int getCode() {
          return code;
      }
    
      public void setCode(int code) {
          this.code = code;
      }
    
      public boolean isFlag() {
          return flag;
      }
    
      public void setFlag(boolean flag) {
          this.flag = flag;
      }
    
      public Object getData() {
          return data;
      }
    
      public void setData(Object data) {
          this.data = data;
      }
    }

4、config配置类

1、和ssm整合的配置一样

2、WebMvcJavaConfig.java

package com.atguigu.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.*;

/**
 * 控制层的配置类
 *      1、controller
 *      2、handlerMapping handlerAdapter
 *      3、全局异常处理器
 *      4、静态资源处理
 *      5、拦截器
 *      6、jsp视图解析器前后缀
 *      7、json转化器
 * @author shkstart
 */
@RestController
@EnableWebMvc //这个包括2、7
@Configuration
@ComponentScan("com.atguigu.controller")
public class WebMvcJavaConfig implements WebMvcConfigurer {

//    静态资源处理
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

//    jsp视图解析器前后缀
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.jsp("/WEB-INF/views/", ".jsp");
    }

//    拦截器

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
//        registry.addInterceptor().addPathPatterns().excludePathPatterns()
    }
}

3、ServiceJavaConfig.java

package com.atguigu.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;

/**
 * service
 *  1、开启aop注解的支持:aspect:@Before @After @AfterReturning @AfterThrowing @Around @Aspect @Order
 *  2、开启事务的支持:@Transactional ;对应的事务管理器实现
 *
 */
@Configuration
@EnableAspectJAutoProxy //开启aop注解的支持
@EnableTransactionManagement
@ComponentScan("com.atguigu.service")
public class ServiceJavaConfig {

    @Bean
    public TransactionManager transactionManager(DataSource dataSource){
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return  dataSourceTransactionManager;
    }
}

4、MapperJavaConfigNew.java

package com.atguigu.config;

import com.github.pagehelper.PageInterceptor;
import org.apache.ibatis.logging.slf4j.Slf4jImpl;
import org.apache.ibatis.session.AutoMappingBehavior;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.util.Properties;

/**
 * 持久层配置类:连接池、sqlSessionFactory、Mapper代理对象
 *
 *  方式2:不保留配置文件
 *      TODO:问题:BUG dataSource和mybatis配置在一起会出现问题
 *              原因:mybatis的组件优先加载,@Value没有读取到
 *              解决:分开配置,写到不同的类就行。
 */
@Configuration //配置类
public class MapperJavaConfigNew {

    //    sqlSessionFactory加入ioc容器
    @Bean
    public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
//        指定配置文件等信息
//        指定数据库连接池对象
        sqlSessionFactoryBean.setDataSource(dataSource);
////        指定外部的mybatis文件
////        Resource是spring.core的包
//        Resource resource = new ClassPathResource("mybatis-config.xml");
//        sqlSessionFactoryBean.setConfigLocation(resource);

//        方式2:使用java的代码配置类
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
//        ①设置驼峰映射
        configuration.setMapUnderscoreToCamelCase(true);
//        ②设置日志输出
        configuration.setLogImpl(Slf4jImpl.class);
//        ③开启resultType自动映射
        configuration.setAutoMappingBehavior(AutoMappingBehavior.FULL);
//        把①、②、③存入到sqlSessionFactoryBean中
        sqlSessionFactoryBean.setConfiguration(configuration);

//        ④别名设置
        sqlSessionFactoryBean.setTypeAliasesPackage("com.atguigu.pojo");

//        ⑤加入插件,分页插件
        PageInterceptor pageInterceptor = new PageInterceptor();
        Properties properties = new Properties();
//        设置数据库类型
        properties.setProperty("helperDialect","mysql");
//        给pageInterceptor设置数据库类型
        pageInterceptor.setProperties(properties);
//        把添加的⑤插件加入到存入到sqlSessionFactoryBean中
        sqlSessionFactoryBean.addPlugins(pageInterceptor);

        return  sqlSessionFactoryBean;
    }

//    Mapper代理对象加入ioc容器
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer(){
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();

//        指定Mapper接口的包
        mapperScannerConfigurer.setBasePackage("com.atguigu.mapper");
        return  mapperScannerConfigurer;
    }
}

5、DataSourceJavaConfig.java

package com.atguigu.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import javax.sql.DataSource;

/**
 * 连接池的配置类
 */
@Configuration //配置类
@PropertySource("classpath:jdbc.properties") //引入外部文件
public class DataSourceJavaConfig {

    @Value("${jdbc.user}")
    private String user;
    @Value("${jdbc.password}")
    private String password;
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;

    @Bean
    public DataSource dataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setPassword(password);
        dataSource.setUsername(user);
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        return dataSource;
    }
}

6、SpringIoCInit.java

package com.atguigu.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

/**
 * spring的初始化类
 */
public class SpringIoCInit extends AbstractAnnotationConfigDispatcherServletInitializer {

//    root容器配置类
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{DataSourceJavaConfig.class, MapperJavaConfigNew.class, ServiceJavaConfig.class};
    }
//   webioc容器配置类指定
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebMvcJavaConfig.class};
    }

//    dispatcherServlet的拦截路径
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

2、功能实现

1、总体的步骤

1、先在controller编写路径方法,service中的方法

2、在serviceimpl编写业务方法,然后调用Mapper中的方法

3、在Mapper接口中编写接口方法,然后调用Mapper.xml中的映射

4、最后在Mapper.xml中实现sql语句的编写

5、最后依次将数据传回给前端

2、增删改查代码

1、ScheduleController.java

package com.atguigu.controller;

import com.atguigu.pojo.Schedule;
import com.atguigu.service.ScheduleService;
import com.atguigu.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

//@RestController
@RequestMapping("schedule")
@CrossOrigin    //允许其他源访问这个controller中的资源。
@RestController
@Slf4j
public class ScheduleController {
    @Autowired
    private ScheduleService scheduleService;

//    查询所有数据
    @GetMapping("/{pageSize}/{currentPage}")
    public R page(@PathVariable(name = "pageSize") int pageSize,
                  @PathVariable(name = "currentPage") int  currentPage){
        R r = scheduleService.page(pageSize,currentPage);
//          log4j日志输出
        log.info("查询所有数据为{}",r);
        return r;
    }

    /**
     * 删除日程信息
     * @param id
     * @return
     */
    @DeleteMapping("/{id}")
    public R remove(@PathVariable Integer id){
        R r = scheduleService.remove(id);
        return r;
    }
//添加,保存
    @PostMapping
    public R save(@Validated @RequestBody Schedule schedule, BindingResult bindingResult){
        if(bindingResult.hasErrors()){
            return R.fail("参数为null,保存失败");
        }
        R r = scheduleService.save(schedule);
        return r;
    }

//    修改
    @PutMapping
    public R update(@Validated @RequestBody Schedule schedule, BindingResult bindingResult){
        if(bindingResult.hasErrors()){
            return R.fail("参数为null,修改失败");
        }
        R r = scheduleService.update(schedule);
        return r;
    }
}

2、ScheduleService.java 接口类

package com.atguigu.service;

import com.atguigu.pojo.Schedule;
import com.atguigu.utils.R;

public interface ScheduleService {
    R page(int pageSize, int currentPage);

    R remove(Integer id);

    R save(Schedule schedule);

    R update(Schedule schedule);
}

3、ScheduleServiceImpl.java实现类

package com.atguigu.service.impl;

import com.atguigu.mapper.ScheduleMapper;
import com.atguigu.pojo.Schedule;
import com.atguigu.service.ScheduleService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.atguigu.utils.PageBean;
import com.atguigu.utils.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class ScheduleServiceImpl implements ScheduleService {
    @Autowired
    private ScheduleMapper scheduleMapper;
    @Override
    public R page(int pageSize, int currentPage) {
//        分页
        PageHelper.startPage(currentPage,pageSize);
//        查询
        List<Schedule> scheduleList = scheduleMapper.queryList();
//        分页数据装配
        PageInfo<Schedule> info = new PageInfo<>(scheduleList);
//        装配PageBean
        PageBean<Schedule> pageBean = new PageBean<>(currentPage,pageSize,info.getTotal(),info.getList());
        R ok = R.ok(pageBean);
        return ok;

    }

    @Override
    public R remove(Integer id) {
        int rows = scheduleMapper.deleteById(id);

        if (rows>0){
            return R.ok(null);
        }
        return R.fail(null);
    }

    @Override
    public R save(Schedule schedule) {
        int rows = scheduleMapper.insert(schedule);
        if (rows>0){
            return R.ok(null);
        }
        return R.fail(null);
    }

    @Override
    public R update(Schedule schedule) {
//        判断id为空
        if (schedule.getId()==null) {
            return R.fail("核心参数为空");
        }

        int rows = scheduleMapper.update(schedule);
        if (rows>0){
            return R.ok(null);
        }
        return R.fail(null);
    }
}

4、ScheduleMapper.java接口类

package com.atguigu.mapper;

import com.atguigu.pojo.Schedule;

import java.util.List;

public interface ScheduleMapper {
    List<Schedule> queryList();

    int deleteById(Integer id);

    int insert(Schedule schedule);

    int update(Schedule schedule);
}

5、 resources/com/atguigu/mapper/ScheduleMapper.xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace等于mapper接口类的全限定名,这样实现对应 -->
<mapper namespace="com.atguigu.mapper.ScheduleMapper">

    <select id="queryList" resultType="schedule">
        select * from schedule
    </select>

<!--    删除-->
    <delete id="deleteById">
        delete
        from schedule
        where id = #{id}
    </delete>

<!--    添加-->
    <insert id="insert">
        insert into schedule(title,completed) value(#{title},#{completed});
    </insert>

<!--    修改-->
    <update id="update">
        update schedule set title=#{title},completed=#{completed}
        where id=#{id};
    </update>
</mapper>

3、使用postman进行测试

1、根据接口文档,设计postman的测试

2、使用postman测试

3、如图增删改查接口测试

image-20240119010911998

4、和前端、后端连调用

1、接口对应

1、前端的请求接口要对应后端的借口

2、还有传值方式

2、关键代码

1、查看前端的src下的api.js

import request from '../utils/request'
/* 
需求说明
    查询全部数据页数据
请求uri
    schedule/{pageSize}/{currentPage}
请求方式 
    get   
响应的json
    {
        "code":200,
        "flag":true,
        "data":{
            //本页数据
            data:
            [
            {id:1,title:'学习java',completed:true},
            {id:2,title:'学习html',completed:true},
            {id:3,title:'学习css',completed:true},
            {id:4,title:'学习js',completed:true},
            {id:5,title:'学习vue',completed:true}
            ], 
            //分页参数
            pageSize:5, // 每页数据条数 页大小
            total:0 ,   // 总记录数
            currentPage:1 // 当前页码
        }
    }
*/
export let loadByPage = (pageSize = 5,currentPage = 1)=>{
    return  request.get(`schedule/${pageSize}/${currentPage}`)
}

/* 
需求说明
    根据id修改数据
请求uri
    schedule
请求方式 
    put
请求体中的JSON
    {
        id: 1,
        title: '',
        completed: false
    }
响应的json
    {
        "code":200,
        "flag":true,
        "data":null
    }
*/
export let updateScheduleById =  (schedule)=>{
   return request.put(`schedule`,schedule)
}

/* 
需求说明
    根据id删除日程
请求uri
    schedule/{id}
请求方式 
    delete
响应的json
    {
        "code":200,
        "flag":true,
        "data":null
    }
*/
export let removeScheduleById =  (id) =>{
   return request.delete(`schedule/${id}`)
}

/* 
需求说明
    增加日程
请求uri
    schedule
请求方式 
    put
请求体中的JSON
    {
        title: '',
        completed: false
    }
响应的json
    {
        "code":200,
        "flag":true,
        "data":null
    }
*/
export let addSchedule =  (schedule)=>{
    return  request.post(`schedule`,schedule)
}

2、查看utils/request.js文件

import axios from 'axios'
import router from '../router/router'

// 创建 Axios 实例 设置一些基础属性
const request = axios.create({
  baseURL:'http://localhost:8080/ssm',
  timeout: 10000
})

// 添加请求拦截器
request.interceptors.request.use(
  config => {
    //可以前置设置,例如请求头token等
    config.headers.head1 = 'ceshi-head1'
    return config
  },
  error => {
    return Promise.reject(error)
  }
)
// 添加响应拦截器
request.interceptors.response.use(
  response => {
   return response
  },
  error => {
    if (error.response.status === 404) {
        //到404页面
        router.push('/404');
    }else{
        // 其他情况 返回一个promise    
        return Promise.reject(error)
    }
  }
)
//对外暴漏axios实例。
export default request

3、注意!!!!

1、这里前后端是两个项目

2、前端想访问后端项目的内容,浏览器会拦截

3、我们要在后端设置(告诉浏览器,前端可以来访问资源)

4、要在Controller代码中添加一个注解

  • @CrossOrigin //允许其他源访问这个controller中的资源。
  • 这个很重要!!!

5、画图理解

image-20240119011402472

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇