• 【Spring Boot+Vue.js+JPA+Mysql】实现前后端分离的名片系统(附源码 超详细必看 可作为大作业使用)


    需要项目源码请点赞关注收藏后评论区留言并且私信~~~

    一、项目简介

    前后端分离的核心思想时前端页面通过掉用后端的RESTfulApI进行数据交互。本次项目使用Spring Boot+Spring Data JPA实现后端系统,使用Vue.js实现前端系统,数据库采用mysql,集成开发环境为Intellij IDEA

    二、名片系统功能介绍

    名片系统是针对注册用户使用的系统 有以下几种功能

    1:非注册用户可以注册为注册用户

    2:成功注册的用户可以登录系统

    3:成功登录的用户,可以添加,修改,删除以及浏览自己客户的名片信息

    三、构建后端系统cardmis 

    1:修改pom.xml

    添加mysql依赖和热部署依赖 具体代码如下

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    4. <modelVersion>4.0.0</modelVersion>
    5. <parent>
    6. <groupId>org.springframework.boot</groupId>
    7. <artifactId>spring-boot-starter-parent</artifactId>
    8. <version>2.1.9.RELEASE</version>
    9. <relativePath/> <!-- lookup parent from repository -->
    10. </parent>
    11. <groupId>com.ch</groupId>
    12. <artifactId>cardmis</artifactId>
    13. <version>0.0.1-SNAPSHOT</version>
    14. <name>cardmis</name>
    15. <description>Demo project for Spring Boot</description>
    16. <properties>
    17. <java.version>11</java.version>
    18. </properties>
    19. <dependencies>
    20. <dependency>
    21. <groupId>org.springframework.boot</groupId>
    22. <artifactId>spring-boot-starter-data-jpa</artifactId>
    23. </dependency>
    24. <dependency>
    25. <groupId>mysql</groupId>
    26. <artifactId>mysql-connector-java</artifactId>
    27. <version>8.0.30</version>
    28. </dependency>
    29. <!-- 热部署 -->
    30. <dependency>
    31. <groupId>org.springframework.boot</groupId>
    32. <artifactId>spring-boot-devtools</artifactId>
    33. <optional>true</optional>
    34. </dependency>
    35. <dependency>
    36. <groupId>org.springframework.boot</groupId>
    37. <artifactId>spring-boot-starter-web</artifactId>
    38. </dependency>
    39. <dependency>
    40. <groupId>org.springframework.boot</groupId>
    41. <artifactId>spring-boot-starter-test</artifactId>
    42. <scope>test</scope>
    43. </dependency>
    44. </dependencies>
    45. <build>
    46. <plugins>
    47. <plugin>
    48. <groupId>org.springframework.boot</groupId>
    49. <artifactId>spring-boot-maven-plugin</artifactId>
    50. </plugin>
    51. </plugins>
    52. </build>
    53. </project>

    2:配置数据源信息

    在配置文件application.properties中 配置端口号 数据源以及文件上传等信息

    1. server.port=8443
    2. ###
    3. ##数据源信息配置
    4. ###
    5. #数据库地址
    6. spring.datasource.url=jdbc:mysql://localhost:3306/card?characterEncoding=utf8
    7. #数据库用户名
    8. spring.datasource.username=root
    9. #数据库密码
    10. spring.datasource.password=root
    11. #数据库驱动
    12. spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    13. #要导入驱动包
    14. #数据库MySQL为8.x时,驱动类为com.mysql.cj.jdbc.Driver
    15. ####
    16. #JPA持久化配置
    17. ####
    18. #指定数据库类型
    19. spring.jpa.database=MYSQL
    20. #指定是否在日志中显示SQL语句
    21. spring.jpa.show-sql=true
    22. #指定自动创建、更新数据库表等配置,update表示如果数据库中存在持久化类对应的表就不创建,
    23. #不存在就创建对应的表
    24. spring.jpa.hibernate.ddl-auto=update
    25. #上传文件时,默认单个上传文件大小是1MB,max-file-size设置单个上传文件大小
    26. spring.servlet.multipart.max-file-size=50MB
    27. #默认总文件大小是10MB,max-request-size设置总上传文件大小
    28. spring.servlet.multipart.max-request-size=500MB

    3:创建持久化实体类

    根据名片系统功能可知,名片系统一共有两个实体:用户和卡片,并且是一对多的关系,因此后端系统的持久化实体类一共有两个 分别为UserEntitiy和CardEntity

    用户实体类代码如下

    1. package com.ch.cardmis.entity;
    2. import java.util.List;
    3. import java.io.Serializable;
    4. import javax.persistence.CascadeType;
    5. import javax.persistence.Entity;
    6. import javax.persistence.FetchType;
    7. import javax.persistence.GeneratedValue;
    8. import javax.persistence.GenerationType;
    9. import javax.persistence.Id;
    10. import javax.persistence.OneToMany;
    11. import javax.persistence.Table;
    12. import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
    13. @Entity
    14. @Table(name = "user_table")
    15. @JsonIgnoreProperties(value = { "hibernateLazyInitializer"})
    16. public class UserEntity implements Serializable{
    17. private static final long serialVersionUID = 1L;
    18. @Id
    19. @GeneratedValue(strategy = GenerationType.IDENTITY)
    20. private int id;//主键
    21. private String uname;
    22. private String upwd;
    23. //名片列表,用户与名片是一对多的关系
    24. @OneToMany(
    25. mappedBy = "user",
    26. cascade=CascadeType.ALL,
    27. targetEntity = CardEntity.class,
    28. fetch=FetchType.LAZY
    29. )
    30. private List<CardEntity> cardEntityList;
    31. public int getId() {
    32. return id;
    33. }
    34. public void setId(int id) {
    35. this.id = id;
    36. }
    37. public String getUname() {
    38. return uname;
    39. }
    40. public void setUname(String uname) {
    41. this.uname = uname;
    42. }
    43. public String getUpwd() {
    44. return upwd;
    45. }
    46. public void setUpwd(String upwd) {
    47. this.upwd = upwd;
    48. }
    49. public List<CardEntity> getCardEntityList() {
    50. return cardEntityList;
    51. }
    52. public void setCardEntityList(List cardEntityList) {
    53. this.cardEntityList = cardEntityList;
    54. }
    55. }

    卡片实体类代码如下

    1. package com.ch.cardmis.entity;
    2. import java.io.Serializable;
    3. import javax.persistence.*;
    4. import com.fasterxml.jackson.annotation.JsonIgnore;
    5. import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
    6. @Entity
    7. @Table(name = "card_table")
    8. @JsonIgnoreProperties(value = { "hibernateLazyInitializer"})
    9. public class CardEntity implements Serializable {
    10. private static final long serialVersionUID = 1L;
    11. @Id
    12. @GeneratedValue(strategy = GenerationType.IDENTITY)
    13. private int id;//主键
    14. private String name;
    15. private String telephone;
    16. private String email;
    17. private String company;
    18. private String post;
    19. private String address;
    20. private String logo;
    21. //所属用户,名片与用户是多对一的关系
    22. @ManyToOne(cascade={CascadeType.MERGE,CascadeType.REFRESH},optional=false)
    23. //可选属性optional=false,表示用户不能为空。删除名片,不影响用户
    24. @JoinColumn(name="id_user_id")//设置在card_table表中的关联字段(外键)
    25. @JsonIgnore
    26. private UserEntity user;
    27. public int getId() {
    28. return id;
    29. }
    30. public void setId(int id) {
    31. this.id = id;
    32. }
    33. public String getName() {
    34. return name;
    35. }
    36. public void setName(String name) {
    37. this.name = name;
    38. }
    39. public String getTelephone() {
    40. return telephone;
    41. }
    42. public void setTelephone(String telephone) {
    43. this.telephone = telephone;
    44. }
    45. public String getEmail() {
    46. return email;
    47. }
    48. public void setEmail(String email) {
    49. this.email = email;
    50. }
    51. public String getCompany() {
    52. return company;
    53. }
    54. public void setCompany(String company) {
    55. this.company = company;
    56. }
    57. public String getPost() {
    58. return post;
    59. }
    60. public void setPost(String post) {
    61. this.post = post;
    62. }
    63. public String getAddress() {
    64. return address;
    65. }
    66. public void setAddress(String address) {
    67. this.address = address;
    68. }
    69. public String getLogo() {
    70. return logo;
    71. }
    72. public void setLogo(String logo) {
    73. this.logo = logo;
    74. }
    75. public UserEntity getUser() {
    76. return user;
    77. }
    78. public void setUser(UserEntity user) {
    79. this.user = user;
    80. }
    81. }

    4:创建Repository持久层

    后端系统的数据访问是基于Spring Data JPA的,数据访问接口需要继承Repository接口,与持久化实体类一样,同样有用户和卡片两个数据访问接口

    用户访问接口代码如下

    1. package com.ch.cardmis.repository;
    2. import com.ch.cardmis.entity.UserEntity;
    3. import org.springframework.data.jpa.repository.JpaRepository;
    4. public interface UserRepository extends JpaRepository<UserEntity, Integer> {
    5. /**
    6. * 查询用户名是否已存在
    7. */
    8. public UserEntity findByUname(String uname);
    9. /**
    10. *登录
    11. */
    12. public UserEntity findByUnameAndUpwd(String uname, String upwd);
    13. }

    卡片访问接口代码如下

    1. package com.ch.cardmis.repository;
    2. import com.ch.cardmis.entity.CardEntity;
    3. import org.springframework.data.domain.Sort;
    4. import org.springframework.data.jpa.repository.JpaRepository;
    5. import java.util.List;
    6. public interface CardRepository extends JpaRepository<CardEntity, Integer> {
    7. //根据用户id查询该用户的名片
    8. public List<CardEntity> findByUser_id(Integer id, Sort sort);
    9. }

    5:创建业务层

    在Spring框架中 提倡使用接口,因此在业务层中涉及Service接口和Service实现类 代码如下

    卡片实现类 

    1. package com.ch.cardmis.service;
    2. import com.ch.cardmis.entity.CardEntity;
    3. import com.ch.cardmis.entity.UserEntity;
    4. import com.ch.cardmis.repository.CardRepository;
    5. import com.ch.cardmis.util.MyUtil;
    6. import org.springframework.beans.factory.annotation.Autowired;
    7. import org.springframework.data.domain.Sort;
    8. import org.springframework.stereotype.Service;
    9. import org.springframework.web.multipart.MultipartFile;
    10. import javax.servlet.http.HttpSession;
    11. import java.io.File;
    12. @Service
    13. public class CardServiceImpl implements CardService {
    14. @Autowired
    15. private CardRepository cardRepository;
    16. @Override
    17. public String add(CardEntity cardEntity, HttpSession session, MultipartFile file) {
    18. if("noLogin".equals(isLogin(session))){
    19. return "noLogin";
    20. }else{
    21. UserEntity user = (UserEntity)session.getAttribute("user");
    22. cardEntity.setUser(user);
    23. //防止文件名重名
    24. String newFileName = "";
    25. if(file != null){
    26. String fileName = file.getOriginalFilename();
    27. newFileName = MyUtil.getNewFileName(fileName);
    28. String realpath = "C:\\Users\\ChenHeng\\IdeaProjects\\cardmis-vue\\cardmis-vue\\static";
    29. File targetFile = new File(realpath, newFileName);
    30. if(!targetFile.exists()){
    31. targetFile.mkdirs();
    32. }
    33. //设置文件名
    34. cardEntity.setLogo("static/" + newFileName);
    35. //上传
    36. try {
    37. file.transferTo(targetFile);
    38. } catch (Exception e) {
    39. e.printStackTrace();
    40. }
    41. }
    42. cardRepository.save(cardEntity);
    43. return "ok";
    44. }
    45. }
    46. @Override
    47. public Object cards(HttpSession session) {
    48. if("noLogin".equals(isLogin(session))){
    49. return "noLogin";
    50. }/*
    51. else {
    52. Sort sort = new Sort(Sort.Direction.DESC, "id");
    53. UserEntity user = (UserEntity)session.getAttribute("user");
    54. return cardRepository.findByUser_id(user.getId(), sort);
    55. }
    56. */
    57. return null;
    58. }
    59. @Override
    60. public String delete(HttpSession session,Integer cid) {
    61. if("noLogin".equals(isLogin(session))){
    62. return "noLogin";
    63. }else {
    64. cardRepository.deleteById(cid);
    65. return "ok";
    66. }
    67. }
    68. @Override
    69. public Object aCard(HttpSession session, Integer cid) {
    70. if("noLogin".equals(isLogin(session))){
    71. return "noLogin";
    72. }else {
    73. return cardRepository.getOne(cid);
    74. }
    75. }
    76. @Override
    77. public String isLogin(HttpSession session) {
    78. Object user = session.getAttribute("user");
    79. if(user == null)
    80. return "noLogin";
    81. return "yes";
    82. }
    83. }

    用户实现类

    1. package com.ch.cardmis.service;
    2. import com.ch.cardmis.entity.UserEntity;
    3. import com.ch.cardmis.repository.UserRepository;
    4. import org.springframework.beans.factory.annotation.Autowired;
    5. import org.springframework.stereotype.Service;
    6. import javax.servlet.http.HttpSession;
    7. @Service
    8. public class UserServiceImpl implements UserService {
    9. @Autowired
    10. private UserRepository userRepository;
    11. @Override
    12. public String register(UserEntity requestUser) {
    13. UserEntity ue = userRepository.findByUname(requestUser.getUname());
    14. if(ue != null)
    15. return "no";
    16. else{
    17. userRepository.save(requestUser);
    18. return "yes";
    19. }
    20. }
    21. @Override
    22. public String login(UserEntity requestUser, HttpSession session) {
    23. UserEntity ue = userRepository.findByUnameAndUpwd(requestUser.getUname(), requestUser.getUpwd());
    24. if(ue != null){//登录成功
    25. session.setAttribute("user", ue);
    26. return "ok";
    27. }
    28. return "no";
    29. }
    30. }

    6:创建控制器层

    卡片控制器 

    1. package com.ch.cardmis.controller;
    2. import com.ch.cardmis.entity.CardEntity;
    3. import com.ch.cardmis.service.CardService;
    4. import org.springframework.beans.factory.annotation.Autowired;
    5. import org.springframework.web.bind.annotation.*;
    6. import org.springframework.web.multipart.MultipartFile;
    7. import javax.servlet.http.HttpSession;
    8. @RestController
    9. public class CardController {
    10. @Autowired
    11. private CardService cardService;
    12. @CrossOrigin//跨域访问
    13. @PostMapping(value = "cardmis/add")
    14. public String add(CardEntity cardEntity, HttpSession session, MultipartFile file) {
    15. return cardService.add(cardEntity, session, file);
    16. }
    17. @CrossOrigin//跨域访问
    18. @GetMapping(value = "cardmis/cards")
    19. public Object cards(HttpSession session) {
    20. return cardService.cards(session);
    21. }
    22. @CrossOrigin//跨域访问
    23. @PostMapping(value = "cardmis/delete")
    24. public String delete(HttpSession session,Integer cid) {
    25. return cardService.delete(session,cid);
    26. }
    27. @CrossOrigin//跨域访问
    28. @GetMapping(value = "cardmis/aCard")
    29. public Object aCard(HttpSession session,Integer cid) {
    30. return cardService.aCard(session,cid);
    31. }
    32. }

    用户控制器

    1. package com.ch.cardmis.controller;
    2. import com.ch.cardmis.entity.UserEntity;
    3. import com.ch.cardmis.service.UserService;
    4. import org.springframework.beans.factory.annotation.Autowired;
    5. import org.springframework.web.bind.annotation.*;
    6. import javax.servlet.http.HttpSession;
    7. @RestController
    8. public class UserController {
    9. @Autowired
    10. private UserService userService;
    11. @CrossOrigin//跨域访问
    12. @PostMapping(value = "cardmis/register")
    13. public String register(@RequestBody UserEntity requestUser) {
    14. return userService.register(requestUser);
    15. }
    16. @CrossOrigin//跨域访问
    17. @PostMapping(value = "cardmis/login")
    18. public String login(@RequestBody UserEntity requestUser, HttpSession session) {
    19. return userService.login(requestUser, session);
    20. }
    21. }

     

    7:创建跨域响应头设置过滤器

    8:创建工具类

    后端系统项目目录结构如下

    后面几个类代码省略不表 有需要请点赞关注收藏后评论区留言并且私信 

     

    四、构建前端系统cardmis-vue

    Node.js与Vue.js的部署请参考我这篇博客 此处不再赘述

    Vue环境部署

    项目结构目录如下

    开发前端页面

    在开发的时候,前端用前端的服务器开发,后端用后端的服务器开发。当开发前端内容时,可以把前端的请求通过前端服务器转发给后端,即可实现观察结果,并且不需要知道后端怎么实现,而只需要知道接口提供的功能,前后端的开发人员各司其职

    部分Vue代码如下

    1. <template>
    2. <div class="active">
    3. <NavMain></NavMain>
    4. <h3>添加名片</h3>
    5. <form>
    6. 姓名:<input type="text" v-model="name" placeholder="请输入用户名"/><br><br>
    7. 电话:<input type="text" v-model="telephone" placeholder="请输入电话"/><br><br>
    8. 邮箱:<input type="text" v-model="email" placeholder="请输入邮箱"/><br><br>
    9. 单位:<input type="text" v-model="company" placeholder="请输入单位"/><br><br>
    10. 邮编:<input type="text" v-model="post1" placeholder="请输入邮编"/><br><br>
    11. 地址:<input type="text" v-model="address" placeholder="请输入地址"/><br><br>
    12. 头像:
    13. <input type="file" @change="getFile($event)"/><br><br>
    14. <button type="button" @click="add($event)" :disabled="isDisable">添加</button>
    15. <button type="reset">重置</button>
    16. </form>
    17. <br>
    18. </div>
    19. </template>
    20. <script>
    21. import NavMain from '@/components/NavMain'
    22. export default {
    23. name: 'Add',
    24. components: {NavMain},
    25. data () {
    26. return {
    27. isDisable:false
    28. }
    29. },
    30. methods: {
    31. //获得文件对象
    32. getFile(event) {
    33. this.file = event.target.files[0];
    34. },
    35. add (event) {
    36. this.isDisable = true;
    37. event.preventDefault();
    38. let formData = new FormData();
    39. formData.append('name', this.name === undefined ? '': this.name);
    40. formData.append('telephone', this.telephone === undefined ? '': this.telephone);
    41. formData.append('email', this.email === undefined ? '': this.email);
    42. formData.append('company', this.company === undefined ? '': this.company);
    43. formData.append('post', this.post1 === undefined ? '': this.post1);
    44. formData.append('address', this.address === undefined ? '': this.address);
    45. formData.append('file', this.file === undefined ? null: this.file);
    46. let config = {
    47. headers:{'Content-Type':'multipart/form-data'}
    48. };
    49. this.$axios
    50. .post('/add', formData, config)//直接提交表单
    51. .then(successResponse => {
    52. if (successResponse.data === "ok") {
    53. alert("添加成功")
    54. this.$router.replace({path: '/main'})
    55. }else if(successResponse.data === "noLogin"){
    56. alert("没有登录,请登录!")
    57. this.$router.replace({path: '/login'})
    58. }else {
    59. alert("添加失败")
    60. this.isDisable = false
    61. }
    62. })
    63. .catch(failResponse => {
    64. alert("响应异常")
    65. })
    66. }
    67. }
    68. }
    69. </script>
    70. <style>
    71. .active {
    72. background-image: url("../assets/bb.jpg");
    73. }
    74. </style>

     同样还有修改路由配置,使用钩子函数判断是否登录等操作 此处不再赘述

    五、测试效果

    首先运行后端系统cardmis的主类,然后再启动前端系统cardmis-vue的主类 通过访问

    https://localhost:8080/测试运行 效果如下

    首页如下

    登录界面如下 会自动查询mysql数据库中有无匹配记录 

     

    注册界面如下 新用户可以先注册 

     

    主页面显示已有的名片信息 

     

    同时可以实现基本的增删改查功能 

     

     创作不易 觉得有帮助请点赞关注收藏~~~

  • 相关阅读:
    linux-4.19 内存
    Jenkins安装配置及插件安装使用
    365天搞定八股文——Day 005 MQ中的重要概念
    【JavaScript】 一万字 JavaScript 笔记(详细讲解 + 代码演示 + 图解)
    JVM——垃圾回收机制和内存分配策略
    颠覆出海营销,机器学习带来买量新变化
    Yarp 与 Nginx性能大比拼不出所料它胜利了!
    June 27 talk SofiE
    无条码商品新建商品档案,搭配蓝牙便携打印机移动打印条码标签
    OBS使用
  • 原文地址:https://blog.csdn.net/jiebaoshayebuhui/article/details/127989150