CRM毕设项目springboot开发系统

一、SpringBoot开发步骤

  1. pom.xml
    配置起步依赖
  2. application.yml
    设置数据源、端口、技术框架相关配置等
  3. 实体类domain
    使用Lombok快速制作实体类
  4. dao
    继承BaseMapper、设置@Mapper,整合Mybatis-Plus
    制作数据层dao测试类
  5. service
    调用数据层接口或Mybatis-Plus提供的接口快速开发
    制作业务层service测试类
  6. controller
    基于Restful开发、使用postman测试跑通功能
    前后端协作制作
  7. 页面
    放置在resource目录下的static目录中
    基于layui,前后端联调,页面数据处理,页面消息处理等等

二、毕设项目之创建springboot工程

1、创建springboot工程

CRM毕设项目springboot开发系统_第1张图片
下一步
CRM毕设项目springboot开发系统_第2张图片
在pom.xml文件中导入相关依赖
(配置起步依赖)
CRM毕设项目springboot开发系统_第3张图片

先将application.properties文件Rename修改成后缀为yml文件,
再修改配置文件yml
(设置数据源、端口、框架技术相关配置等)
CRM毕设项目springboot开发系统_第4张图片

2、实体类domain开发

  1. book的实体类
package com.example.demo_ssmp.domain;
//实体类book
//lombok
import lombok.Data;
//@Data是Getter和Setter,
@Data
public class Book {
    private Integer id;
    private String type;
    private String name;
    private String description;
}

  1. CompanyData的实体类
package com.crmbs.domain;
//模型类---公司基本资料
//lombok的@Data是Getter和Setter
import lombok.Data;

@Data
public class CompanyData {
    private Integer id;
    private String companyName;     //公司名称
    private String personLiable;    //负责人
    private String phone;   //联系电话
    private String fax; //传真
    private String email; //电子邮件
    private String postalCode;  //邮政编码
    private String address; //地址
    private String remarks; //备注
}

3、模型类dao开发

  1. book的模型类
package com.example.demo_ssmp.Dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo_ssmp.domain.Book;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface BookDao extends BaseMapper<Book> {
//public interface BookDao  {
    //BaseMapper作用
//    @Select("select * from tbl_book where id = #{id}")
//    Book getById(Integer id);
}
  1. CompanyData的模型类
package com.crmbs.Dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.crmbs.domain.CompanyData;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface CompanyDataDao extends BaseMapper<CompanyData> {

}

4、业务层service开发

数据层在定义的时候关注的是数据库相关的操作,
业务层在定义的时候关注的是业务名称

Service层接口定义与数据层接口定义具有较大区别,不要混用
selectByUserNameAndPassword(String username,String password);
login(String username,String password);

1.book的接口类IBookService

package com.example.demo_ssmp.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.demo_ssmp.domain.Book;

import java.util.LinkedHashMap;

//IBookService,I代表接口,一种命名规范
//继承范型方法:IService<模型类>
public interface IBookService extends IService<Book> {
//    新增保存增加
    boolean saveBook(Book book);
//    新增修改
    boolean modify(Book book);
//    新增删除
    boolean delete(Integer id);
//    新增分页操作
    IPage<Book> getPage(int currentPage, int pageSize);

    LinkedHashMap<String, Object> selectPage(int page, int limit);
}

  1. CompanyData的接口类ICompanyDataService
package com.crmbs.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.crmbs.domain.CompanyData;

import java.util.LinkedHashMap;

public interface ICompanyDataService extends IService<CompanyData> {
    //分页查询
    LinkedHashMap<String, Object> selectPage(int page, int limit, QueryWrapper<CompanyData> qus);
}

  1. book的接口实现类BookServiceImpl
package com.example.demo_ssmp.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo_ssmp.Dao.BookDao;
import com.example.demo_ssmp.domain.Book;
import com.example.demo_ssmp.service.IBookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.LinkedHashMap;
import java.util.List;

//业务层对应的bean
@Service
//在IBookService中定义的接口方法都实现了,ServiceImpl<实现类, 对应的模型类>
public class BookServiceImpl extends ServiceImpl<BookDao, Book> implements IBookService {

//    注入数据层
    @Autowired
    private BookDao bookDao;

    @Override
    public boolean saveBook(Book book) {
        return bookDao.insert(book)>0;
    }

    @Override
    public boolean modify(Book book) {
        return bookDao.updateById(book)>0;
    }

    @Override
    public boolean delete(Integer id) {
        return bookDao.deleteById(id)>0;
    }
    
    @Override
    public IPage<Book> getPage(int currentPage, int pageSize) {
        IPage page=new Page(currentPage,pageSize);
        bookDao.selectPage(page,null);
//        List booklist=page.getRecords()
        return page;
    }

// 	分页功能实现
    @Override
    public LinkedHashMap<String, Object> selectPage(int page, int limit) {
        QueryWrapper<Book> queryWrapper=new QueryWrapper<Book>();
        Page<Book>pages=new Page<Book>(page,limit);
        IPage<Book>iPage=bookDao.selectPage(pages, queryWrapper);
        List<Book> list=iPage.getRecords();
        long count=iPage.getTotal();
        LinkedHashMap<String, Object>linkedHashMap=new LinkedHashMap<String, Object>();
        linkedHashMap.put("code", 0);
        linkedHashMap.put("flag", true);
        linkedHashMap.put("msg", "");
        linkedHashMap.put("count", count);
        linkedHashMap.put("data", list);
        return linkedHashMap;
    }

    @Override
    public Book getOne(Wrapper<Book> Wrapper) {

//        QueryWrapper Wrapper = new QueryWrapper<>();
//        Wrapper.eq("type",)
        return  this.bookDao.selectOne(Wrapper) ;
    }
}

  1. CompanyData的接口实现类CompanyDataServiceImpl
package com.crmbs.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.crmbs.Dao.CompanyDataDao;
import com.crmbs.domain.CompanyData;
import com.crmbs.service.ICompanyDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.LinkedHashMap;
import java.util.List;

@Service
public class CompanyDataServiceImpl extends ServiceImpl<CompanyDataDao, CompanyData> implements ICompanyDataService {

    //注入数据层
    @Autowired
    private CompanyDataDao companyDataDao;

    //分页查询
    @Override
    public LinkedHashMap<String, Object> selectPage(int page, int limit,QueryWrapper<CompanyData> qus) {
        QueryWrapper<CompanyData> queryWrapper=new QueryWrapper<CompanyData>();
        Page<CompanyData>pages=new Page<CompanyData>(page,limit);
        IPage<CompanyData>iPage=companyDataDao.selectPage(pages, qus);
        List<CompanyData> list=iPage.getRecords();
        long count=iPage.getTotal();
        LinkedHashMap<String, Object>linkedHashMap=new LinkedHashMap<String, Object>();
        linkedHashMap.put("code", 0);
        linkedHashMap.put("flag", true);
        linkedHashMap.put("msg", "");
        linkedHashMap.put("count", count);
        linkedHashMap.put("data", list);
        return linkedHashMap;
    }

}

5、表现层controller层

  1. 先进行格式统一处理(通用book和CompanyData)
package com.crmbs.controller.utils;

import lombok.Data;

//表现层数据格式统一处理----前后端数据协议
@Data
public class R {

//    标记操作是否成功,turn和false
    private Boolean flag;
    private Object count;
//    操作返回的数据
    private Object data=null;
    private String msg;

    public R(){}

    public R(Boolean flag,Object count){
        this.flag=flag;
        this.count = count;
    }

//    有参数传递的
    public R(Boolean flag,Object data,Object count){
        this.flag = flag;
        this.data = data;
        this.count = count;
    }

    //需要备注信息msg
    public R(Boolean flag,Object data,Object count,String msg){
        this.flag = flag;
        this.data = data;
        this.count = count;
        this.msg = msg;
    }

    public R(Boolean flag,String msg,Object data){
        this.flag = flag;
        this.msg = msg;
        this.data = data;
    }

    //登录成功返回数据
    public static R ok(Object data){
        return new R(true,"操作成功",data);
    }
    //登录成功不返回数据
    public static R ok(){
        return new R(true,"操作成功",null);
    }
    //登录失败不返回数据
    public static R fail(){
        return new R(false,"操作失败密码或用户名错误",null);
    }
}

  1. book的表现层进行接口跳转
package com.example.demo_ssmp.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.demo_ssmp.controller.utils.R;
import com.example.demo_ssmp.domain.Book;
import com.example.demo_ssmp.service.IBookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.LinkedHashMap;

@RestController
@RequestMapping("/books")
public class BookController {
//    注入业务层
    @Autowired
    private IBookService bookService;

    @GetMapping("/page")
    public LinkedHashMap<String, Object> pageData(int page, int limit) {
        return bookService.selectPage(page, limit);
    }

    @GetMapping
    public R getAll(){
        return new R(true,bookService.list(),bookService.count(null));
    }

//  增加,通过请求体传json数据
    @PostMapping
    public R save(@RequestBody Book book){
        return new R(bookService.save(book),1);
    }

//    修改,通过请求体传json数据
    @PutMapping
    public R update(@RequestBody Book book){
//        return bookService.updateById(book);
        return new R(bookService.updateById(book),1); //自定义修改
    }

//    删除,通过路径变量来传参数
    @DeleteMapping("/{id}")
    public R delete(@PathVariable Integer id){
//        return bookService.removeById(id);
        return new R(bookService.delete(id),1); //自定义删除
    }

//    查单个,通过路径变量来传参数,例如:http://localhost:80/books/2
    @GetMapping("/{id}")
    public R getById(@PathVariable Integer id){
        return new R(true,bookService.getById(id),bookService.count(null));
    }

//    分页
    @GetMapping("/{currentPage}/{pageSize}")
    public R getPage(@PathVariable int currentPage,@PathVariable int pageSize){
        return new R(true,bookService.getPage(currentPage,pageSize).getRecords(),bookService.count(null));
    }

    @GetMapping("/login")
    public R get(String name,String type){
        QueryWrapper<Book> wrapper = new QueryWrapper<>();
        wrapper.eq("type",name);
        wrapper.eq("name",type);
        return new R(true,bookService.getOne(wrapper),bookService.count(null));
    }
}
  1. CompanyData的表现层进行接口跳转
package com.crmbs.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.crmbs.controller.utils.R;
import com.crmbs.domain.CompanyData;
import com.crmbs.service.ICompanyDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.LinkedHashMap;

@RestController
@RequestMapping("/CompanyDatas")
public class CompanyDataController {
//    注入业务层
    @Autowired
    private ICompanyDataService companyDataService;

    //分页查询
    @GetMapping("/page")
    public LinkedHashMap<String, Object> pageData(int page, int limit, HttpServletRequest request) {

        String companyName = request.getParameter("companyName");
        String personLiable = request.getParameter("personLiable");
        String phone = request.getParameter("phone");

        QueryWrapper<CompanyData> qus = new QueryWrapper<>();
        CompanyData cus = new CompanyData();

        if(null != companyName && ""!= companyName){
            qus.like("company_name",companyName);
            cus.setCompanyName(companyName);
        }

        if(null != personLiable && ""!= personLiable){
            qus.like("person_liable",personLiable);
            cus.setPersonLiable(personLiable);
        }

        if(null != phone && ""!= phone){
            qus.like("phone",phone);
            cus.setPhone(phone);
        }

        return companyDataService.selectPage(page, limit,qus);
    }

    //查询所有数据
    @GetMapping
    public R getAll(){
        return new R(true,companyDataService.list(),companyDataService.count(null));
    }

//  增加,通过请求体传json数据
    @PostMapping
    public R save(@RequestBody CompanyData book){
        return new R(companyDataService.save(book),1);
    }

//    修改,通过请求体传json数据
    @PutMapping
    public R update(@RequestBody CompanyData book){
        return new R(companyDataService.updateById(book),1); //自定义修改
    }

//    删除,通过路径变量来传参数
    @DeleteMapping("/{id}")
    public R delete(@PathVariable Integer id){
        return new R(companyDataService.removeById(id),1); //自定义删除
    }

//    查单个,通过路径变量来传参数,例如:http://localhost:80/books/2
    @GetMapping("/{id}")
    public R getById(@PathVariable Integer id){
        return new R(true,companyDataService.getById(id),companyDataService.count(null));
    }

}

数据库数据获取

链接:https://pan.baidu.com/s/1KzZ6Rau0j2biTCTll-XY6w
提取码:qoj6
–来自百度网盘超级会员V4的分享

三、细节处理1之json

1、axios介绍

axios是一个基于promise的HTTP库,可以用在浏览器和node.js中。
首先需要知道:axios不是一种新的技术。
axios是基于Promise用于浏览器和node.js的HTTP客户端,
本质上也是对原生XHR的封装,只不过它是Promise的现实版本,符合最新的ES规范,

2、axios特征

  1. 从浏览器中创建XMLHttpRequests
  2. 从node.js创建http请求
  3. 支持Promise API
  4. 拦截请求和响应数据
  5. 取消请求
  6. 自动转换json数据
  7. 客户端支持防御XSPF

axios发送请求不同方式get、post、delete、put

3、axios引入

//引入axios
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

4、axios请求

<script>
        axios({
            // 请求类型get\post\put\delete
            method: 'post',
            //请求地址
            url: '/books',
            //请求数据
            data: index
        }).then(response =>{	//打印请求数据日志
            console.log(response);
        }).catch(err=>{		//打印错误日志信息
        	console.log(err);
        });
</script>

5、axios请求简化

<script>
		//删除
        axios.delete('/books/'+data.id).then(res =>{
        	console.log(res);
        });
        //获取数据
        axios.get('/books/',{id:2}).then(response =>{
        	console.log(res);
        });
</script>

6、axios全局配置信息

<script>
		//设置全局配置信息
		axios.defaults.baseURL = 'http://localhost:80/';
		//删除
        axios.delete('/books/'+data.id).then(res =>{
        	console.log(res);
        });
        //获取数据
        axios.get('/books/',{id:2}).then(response =>{
        	console.log(res);
        });
</script>

7、axios拦截器

  1. 拦截器分为request请求拦截器和response响应拦截器
    request请求拦截器:发送请求前统一处理,如:设置请求头headers、应用的版本号、终端类型等。
  2. response响应拦截器:有时候我们要根据响应的状态码来进行下一步操作,例如:由于当前的token过期,接口返回401未授权,那我们就要进行重新登录的操作。
<script>
		//设置全局配置信息
		axios.defaults.baseURL = 'http://localhost:80/';
		//添加请求拦截器
        axios.interceptiors.request.use(
        	function(config){
	        	//在发送请求之前做些什么
	        	return config;
        	},
        	function(error){
	        	//对请求错误做些什么
	        	return Promise.reject(error);
        	},
        );


		//添加响应拦截器
        axios.interceptiors.request.use(
        	function(response){
	        	//对响应数据做点什么
	        	return response;
        	},
        	function(error){
	        	//对响应错误做些什么
	        	return Promise.reject(error);
        	},
        );
</script>

四、细节处理2之跨域处理

1、何为跨域?

Url的一般格式:协议+域名(子域名+主域名)+端口号+资源地址示例:https://www.dustyblog.cn:8080/say/Hello是由
https + www + dustyblog.crl+ 8080 + say/Hello组成。
只要协议,子域名,主域名,端口号这四项组成部分中有一项不同,就可以认为是不同的域,不同的域之间互相访问资源,就被称之为跨域。

2、解决跨域问题

跨域配置类/添加注解/—一般都在后端解决跨域问题(解决跨域问题答案不唯一)

package com.crmbs.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

//解决跨域问题
@Configuration
public class CorsConfig implements WebMvcConfigurer {

    //使用CorsFilter解决跨域的问题
    @Bean
    public CorsFilter corsFilter(){
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        //允许跨域请求的域名
        corsConfiguration.addAllowedOrigin("*");
        //允许任何方法(post、get等)
        corsConfiguration.addAllowedMethod("*");
        //允许任何请求头
        corsConfiguration.addAllowedHeader("*");
        UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**",corsConfiguration);
        CorsFilter corsFilter = new CorsFilter(urlBasedCorsConfigurationSource);
        return corsFilter;
    }
}

五、细节处理3之mybatis-plus

1、mybatis 和mybatis-plus区别

  1. mybatis需要写各种各样的sql语句,即xml文件
    需要编写EmployeeMapper接口,并手动编写CRUD方法
    提供EmployeeMapper.xml映射文件,并手动编写每个方法对应的SQL语句
  2. mybatis-plus是mybatis的增强工具,简化开发提高效率而生(简称MP)
    只需要创建EmployeeMapper接口,并继承BeanMapper接口,这就是使用MP需要完成的所有操作,甚至不需要创建SQL映射文件。

mybatis-plus通用CRUD----不用写任何SQL语句就可以完成单表的CRUD的操作(增查改删)

mabtis-plus依赖(pom.xml):

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.3</version>
        </dependency>

2、mybatis-plus特性

强大的CRUD操作:内置通用Mapper、通用Service
支持Lambda形式调用:无需担心字段写错 @Data,lombok自动生成get和set以及构造方法方法,简化java bean开发。
支持多种数据库、内置分页插件、内置代码生成器:Mapper、Service等

3、mybatis整合MP一般有三种用法:

  1. mybatis+MP :第一步,将BookDao继承BaseMapper,将拥有了BaseMapper中的所有方法;
  2. Spring+Mybatis+MP:引入了Spring框架、数据源、构建等工作就交给了Spring管理。创建子module;
  3. springBoot+mybatis+MP:使用springBoot将进一步的简化Mp的整合,需要注意的是,由于使用springboot需要继承parent,所以需要重新创建工程,不是创建子Module。

4、springBoot+mybatis+MP(重点)

第一步,将BookDao继承BaseMapper,将拥有了BaseMapper中的所有方法;

package com.example.demo_ssmp.Dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo_ssmp.domain.Book;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface BookDao extends BaseMapper<Book> {
}

5、mybatis-plus的通用CRUD

实体类继承BaesMapper后就可以获取到各种各样的单表操作,已经定义好了各种各样的CRUD方法 所有不需要自己写了
CRM毕设项目springboot开发系统_第5张图片

根据条件做更新的测试类:update(service层)

    @Test
    void testUpdate2(){
        Book book =new Book();

        //要更新的字段
        book.setType("测试数据更新条件更新");
        book.setName("测试数据123Updata业务层lmpl");
        book.setDescription("测试数据123Updata业务层lmpl");

        //根据条件做更新
        QueryWrapper<Book> wrapper =new QueryWrapper<>();
        wrapper.eq("type","测试数据123Updata业务层lmpl");

        //执行更新
        bookService.update(book,wrapper);
    }

根据条件删除Map:deleteByMap

    @Test
    void testDeleteByMap() {
        Map<String,Object> map = new HashMap<>();
        map.put("type","测试数据123Updata");
        map.put("name","测试数据123Updata");

        //根据条件删除数据。多条件是and的关系
        bookDao.deleteByMap(map);
    }

根据条件删除:delete

    @Test
    void testDelete() {
        Book book =new Book();
        book.setType("测试数据更新条件更新");
        book.setName("测试数据123Updata业务层lmpl");

        //根据包装条件做删除
        QueryWrapper<Book> wrapper =new QueryWrapper<>(book);

        //根据条件删除数据。多条件是and的关系
        bookDao.delete(wrapper);
    }

六、springboot框架中的层以及作用

1. entity( model)层:

model是模型的意思,与entity、domain、pojo类似,是存放实体的类,类中定义了多个类属性,并与数据库表的字段保持一致,一张表对应一个model类。主要用于定义与数据库对象应的属性,提供get/set方法,tostring方法,有参无参构造函数。

2. dao(mapper)层:

被称为mapper层,叫数据持久层,先设计接口,然后在配置文件中进行配置其实现的关联。dao层的作用为访问数据库,向数据库发送sqi语句,完成数据的增删改查任务。数据持久化操作就是指,把数据放到持久化的介质中,同时提供增删改查操作,比如数据通过hibernate插入到数据库中

3. service层:

业务逻辑层,完成功能的设计和dao层一样都是先设计接口,再创建要实现的类,然后在配置文件中进行配置其实现的关联。接下来就可以在service层调用dao层的接口进行业务逻辑应用的处理。service的impl是把mapper和service进行整合的文件封装Service层的业务逻辑有利于业务逻辑的独立性和重复利用性。

4. controller层:

控制层,控制业务逻辑service,控制请求和响应,负责前后端交互controller层主要调用Service层里面的接口控制具体的业务流程,控制的配置也要在配置文件中进行

5. 业务逻辑总结

controller层(处理前台发送的请求)—>service定义接口(业务逻辑)—>erviceImpl(对接口函数进行实现)—>mapper(Mapper接口,方法名与Mapper.xml中定义的statement的id相同)—>mapper.xml(写sql语句查询数据库)

6. springboot框架层的结构图

CRM毕设项目springboot开发系统_第6张图片

crm系统资源

链接:https://pan.baidu.com/s/1nyEfGUt8SZP5aQVmATOS8w
提取码:4y70
–来自百度网盘超级会员V4的分享

你可能感兴趣的:(spring,boot,restful,java)