springboot基础案例(二)

news2024/11/15 22:51:09

文章目录

  • 前言
  • 一.需求分析: 分析这个项目含有哪些功能模块
  • 二.库表设计(概要设计): 1.分析系统有哪些表 2.分析表与表关系 3.确定表中字段(显性字段 隐性字段(业务字段))
    • 2.1 创建一个库: ems-thymeleaf
    • 2.2 创建 2张表
    • 三.编码(环境搭建)
      • 1.创建一个springboot项目 项目名字: ems-thymeleaf
      • 2.修改配置文件为 application.yml pom.xml
      • 3.修改端口 9999 项目名: ems-thymeleaf
      • 4.springboot整合thymeleaf使用
      • 5.springboot整合mybatis
      • 6.导入项目页面
      • 7.配置thymeleaf模版controller统一请求
    • 四.编码(业务代码开发)
      • 1.验证码实现
      • 2.用户注册实现
      • 3.用户登录实现
      • 3.员工列表实现
      • 4.增加员工信息
      • 5.更新员工的实现
      • 6.删除员工的实现

前言

一.需求分析: 分析这个项目含有哪些功能模块

	用户模块:
		注册
		登录
		验证码
		安全退出
		真是用户
	员工模块:
		添加员工+上传头像
		展示员工列表+展示员工头像
		删除员工信息+删除员工头像
		更新员工信息+更新员工头像

二.库表设计(概要设计): 1.分析系统有哪些表 2.分析表与表关系 3.确定表中字段(显性字段 隐性字段(业务字段))

2.1 创建一个库: ems-thymeleaf

2.2 创建 2张表

1.用户表 user
id username realname password gender

CREATE TABLE `employee` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(60) DEFAULT NULL COMMENT '员工姓名',
  `salary` double(10,2) DEFAULT NULL COMMENT '员工工资',
  `birthday` datetime DEFAULT NULL COMMENT '员工生日',
  `photo` varchar(200) DEFAULT NULL COMMENT '头像路径',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

2.员工表 employee
id name salary birthday photo

CREATE TABLE `user` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(40) DEFAULT NULL COMMENT '用户名',
  `realname` varchar(60) DEFAULT NULL COMMENT '真实姓名',
  `password` varchar(40) DEFAULT NULL COMMENT '密码',
  `gender` tinyint(1) unsigned DEFAULT NULL COMMENT '性别',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

三.编码(环境搭建)

1.创建一个springboot项目 项目名字: ems-thymeleaf

在这里插入图片描述

2.修改配置文件为 application.yml pom.xml

修改poml版本为 springboot版本为2.7.14
在这里插入图片描述

把application.properties修改为application.yml
在这里插入图片描述

3.修改端口 9999 项目名: ems-thymeleaf

在这里插入图片描述

4.springboot整合thymeleaf使用

a.引入依赖

<!--		引入thymeleaf-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>

b.配置文件中指定thymeleaf相关配置

spring:
  thymeleaf:
    prefix: classpath:/templates/  #指定thymeleaf模板前缀目录
    suffix: .html                  #指定模板的后缀
    cache: false                    #是否开启thymeleaf缓存 默认值是true开启缓存  在开发过程中推荐使用false

c.编写控制器测试

@Controller
@RequestMapping("demo")
public class DemoController {

    private static final Logger log = LoggerFactory.getLogger(DemoController.class);

    @RequestMapping("demo")
    public String demo(Model model){
        log.debug("demo ok");
        model.addAttribute("msg","hello thymeleaf");
        return "demo";
    }


}

d.最后访问
在这里插入图片描述

5.springboot整合mybatis

a.引入依赖
mysql、druid、mybatis-springboot-stater

<!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>

        <!--druid-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.4</version>
        </dependency>

        <!--myabtis-springboot-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.4</version>
        </dependency>

b.配置文件

# 数据库的配置
# 数据库的配置
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ems-thymeleaf?characterEncoding=UTF-8
    username: root
    password: 123456

#配置mybatis
mybatis:
  mapper-locations: classpath:mapper/**Mapper.xml
  type-aliases-package: com.demo.entity

# 日志配置
logging:
  level:
    root: info
    com.demo: debug

6.导入项目页面

static 存放静态资源
在这里插入图片描述

templates 目录 存放模板文件
在这里插入图片描述

7.配置thymeleaf模版controller统一请求

因为我们thymeleaf模板开发,要访问静态资源的时候,我们必须建controller请求,这样比较麻烦,我们可以统一配置,具体操作如下:

@Configuration
public class MvcConfig implements WebMvcConfigurer {
    通过这里面配置: 不需要为每一个访问thymeleaf模板页面单独开发一个controller请求了
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        //viewController 请求路径    viewName: 跳转视图
        registry.addViewController("login").setViewName("login");
        registry.addViewController("register").setViewName("regist");
    }
}

四.编码(业务代码开发)

1.验证码实现

在这里插入图片描述
Controller代码如下:

 @RequestMapping("generateImageCode")
    public void generateImageCode(HttpSession session, HttpServletResponse response) throws IOException {
        //1.生成4位随机数
        String code = VerifyCodeUtils.generateVerifyCode(4);
        //2.保存到session作用域
        session.setAttribute("code",code);
        //3.根据随机数生成图片 && 4.通过response响应图片  && 5.设置响应类型
        response.setContentType("image/png");
        ServletOutputStream os = response.getOutputStream();
        VerifyCodeUtils.outputImage(220,60, os,code);
    }
}

前端页面改的位置
在这里插入图片描述

2.用户注册实现

在这里插入图片描述
Controller

  @RequestMapping("register")
    public String register(User user, String code,HttpSession session){
        log.debug("用户名: {},真是姓名: {},密码: {},性别: {},",user.getUsername(),user.getRealname(),user.getPassword(),user.getGender());
        log.debug("用户输入验证码: {}",code);

        try {
            //1.判断用户输入验证码和session中验证码是否一致
            String sessionCode = session.getAttribute("code").toString();
            if(!sessionCode.equalsIgnoreCase(code))throw new RuntimeException("验证码输入错误!");
            //2.注册用户
            userService.register(user);
        } catch (RuntimeException e) {
            e.printStackTrace();
            return "redirect:/register"; //注册失败回到注册
        }
        return  "redirect:/login";  //注册成功跳转到登录
    }

实体类

public class User {
    private Integer id;
    private String username;
    private String realname;
    private String password;
    private Boolean gender;
    }

Service

public class UserService {
    /**
     * 注册用户
     */
    private UserMapper userMapper;
    @Autowired
    public UserService(UserMapper userMapper){
        this.userMapper=userMapper;

    }
    public void register(User user) {
        //1.根据用户名查询数据库中是否存在改用户
        User userDB = userMapper.findByUserName(user.getUsername());
        //2.判断用户是否存在
        if(!ObjectUtils.isEmpty(userDB)) throw new RuntimeException("当前用户名已被注册!");
        //3.注册用户&明文的密码加密  特点: 相同字符串多次使用md5就行加密 加密结果始终是一致
        String newPassword = DigestUtils.md5DigestAsHex(user.getPassword().getBytes(StandardCharsets.UTF_8));
        user.setPassword(newPassword);
        userMapper.save(user);
    }
}

Mapper

    <!--findByUserName-->
    <select id="findByUserName" parameterType="String" resultType="User">
        select id,username,realname,password,gender from `user`
        where username = #{username}
    </select>

    <!--save-->
    <insert id="save" parameterType="User" useGeneratedKeys="true" keyProperty="id">
        insert into `user` values(#{id},#{username},#{realname},#{password},#{gender})
    </insert>

3.用户登录实现

在这里插入图片描述
Controller

 @RequestMapping("login")
    public String login(String username,String password,HttpSession session){
        log.debug("本次登录用户名: {}",username);
        log.debug("本地登录密码: {}",password);
        try {
            //1.调用业务层进行登录
            User user = userService.login(username,password);
            //2.保存用户信息
            session.setAttribute("user",user);
        } catch (Exception e) {
            e.printStackTrace();
            return "redirect:/login";//登录失败回到登录界面
        }
        return "redirect:/employee/lists";//登录成功之后,跳转到查询所有员工信息控制器路径
    }

Service

 public User login(String username, String password) {
        //1.根据用户名查询用户
        User user = userMapper.findByUserName(username);
        if(ObjectUtils.isEmpty(user)) throw new RuntimeException("用户名不正确!");
        //2.比较密码
        String passwordSecret = DigestUtils.md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8));
        if(!user.getPassword().equals(passwordSecret)) throw new RuntimeException("密码输入错误!");
        return user;
    }

Mapper

    <!--findByUserName-->
    <select id="findByUserName" parameterType="String" resultType="User">
        select id,username,realname,password,gender from `user`
        where username = #{username}
    </select>

3.员工列表实现

在这里插入图片描述
实体类

public class Employee {
    private Integer id;
    private String name;
    private Double salary;
    private Date birthday;
    private String photo;//头像路径
    }

Controller

 @RequestMapping("lists")
    public String lists(Model model){
        log.debug("查询所有员工信息");
        List<Employee> employeeList=employeeService.lists();
        model.addAttribute("employeeList",employeeList);

        return "emplist";
    }

Service

public List<Employee> lists(){
        return employeeMapper.lists();
    }

Mapper

 <!--lists-->
    <select id="lists" resultType="Employee">
        select id,name,salary,birthday,photo from `employee`
    </select>

4.增加员工信息

在这里插入图片描述

Controller

 @RequestMapping("save")
    public String save(Employee employee, MultipartFile img) throws IOException {
        log.debug("姓名:{}, 薪资:{}, 生日:{} ", employee.getName(), employee.getSalary(), employee.getBirthday());
        String originalFilename = img.getOriginalFilename();
        log.debug("头像名称: {}", originalFilename);
        log.debug("头像大小: {}", img.getSize());
        log.debug("上传的路径: {}",realpath);
        //1.处理头像的上传&& 修改文件名
        String fileNamePrefix = new SimpleDateFormat("yyyyMMddHHmmsssSSS").format(new Date());
        String fileNameSuffix = originalFilename.substring(originalFilename.lastIndexOf("."));
        String newFileName=fileNamePrefix+fileNameSuffix;
        img.transferTo(new File(realpath,newFileName));
        //2.保存员工信息
        employee.setPhoto(newFileName);
        employeeService.save(employee);
        return "redirect:/employee/lists";
    }

Service

 public void save(Employee employee) {
    employeeMapper.save(employee);
    }

Mapper

    <insert id="save" parameterType="Employee" useGeneratedKeys="true" keyProperty="id">
        insert into `employee` values (#{id},#{name},#{salary},#{birthday},#{photo})
    </insert>

5.更新员工的实现

在这里插入图片描述

Controller

 /**
     * 更新员工信息
     * @param employee
     * @param img
     * @return
     */
    @RequestMapping("update")
    public String update(Employee employee,MultipartFile img) throws IOException {
        log.debug("更新之后员工信息: id:{},姓名:{},工资:{},生日:{},", employee.getId(), employee.getName(), employee.getSalary(), employee.getBirthday());
        //1.判断是否更新头像
        boolean notEmpty = !img.isEmpty();
        log.debug("是否更新头像: {}", notEmpty);
        if (notEmpty) {
            //1.删除老的头像 根据id查询原始头像
            String oldPhoto = employeeService.findById(employee.getId()).getPhoto();
            File file = new File(realpath, oldPhoto);
            if (file.exists()) file.delete();//删除文件
            //2.处理新的头像上传
            String originalFilename = img.getOriginalFilename();
            String newFileName = uploadPhoto(img, originalFilename);
            //3.修改员工新的头像名称
            employee.setPhoto(newFileName);
        }
        //2.没有更新头像直接更新基本信息
        employeeService.update(employee);
        return "redirect:/employee/lists";//更新成功后,跳转到所有员工列表
    }
    //上传头像方法
    private String uploadPhoto(MultipartFile img, String originalFilename) throws IOException {
        String fileNamePrefix = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
        String fileNameSuffix = originalFilename.substring(originalFilename.lastIndexOf("."));
        String newFileName = fileNamePrefix + fileNameSuffix;
        img.transferTo(new File(realpath, newFileName));
        return newFileName;
    }

Service

  public void update(Employee employee) {
        employeeMapper.update(employee);
    }

Mapper

 <update id="update" parameterType="Employee" >
        update `employee` set name=#{name},salary=#{salary},birthday=#{birthday},photo=#{photo}
        where id = #{id}
    </update>

6.删除员工的实现

Controller

    @RequestMapping("delete")
    public String delete(Integer id){
        log.debug("删除的员工id: {}",id);
        //1.删除数据
        String photo = employeeService.findById(id).getPhoto();
        employeeService.delete(id);
        //2.删除头像
        File file = new File(realpath, photo);
        if (file.exists()) file.delete();
        return "redirect:/employee/lists";//跳转到员工列表
    }

Service

public void delete(Integer id) {
        employeeMapper.delete(id);
    }

Mapper

  <!--delete-->
    <delete id="delete" parameterType="Integer">
        delete from `employee` where id = #{id}
    </delete>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1438751.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【IDEA】反编译Jar包

反编译步骤 使用IDEA安装decompiler插件 找到decompiler插件文件夹所在位置&#xff08;IDEA安装路径/plugins/java-decompiler/lib &#xff09;&#xff0c;将需要反编译的jar包放到decompiler插件文件夹下&#xff0c;并创建一个空的文件夹&#xff0c;用来存放反编译后的…

Docker 有哪些常见的用途?

Docker 是一种容器化技术&#xff0c;它允许应用程序在不同的环境之间具有一致的运行环境。这使得 Docker 在开发和运维领域中非常受欢迎&#xff0c;因为它简化了应用程序的部署和管理。以下是 Docker 的一些常见用途&#xff1a; 快速部署应用程序 Docker 允许开发人员和运…

【TCP】高频面试题

前言 在IT行业的求职过程中&#xff0c;传输控制协议&#xff08;TCP&#xff09;作为网络通信的核心协议之一&#xff0c;其相关面试题常常出现在各大公司面试中。TCP的稳定性和可靠性是支撑互联网数据传输的基石&#xff0c;因此&#xff0c;对TCP有深入理解不仅能够帮助求职…

Linux大集合

Linux Linux是什么&#xff1f; Linux是一套免费使用和自由传播的类Unix操作系统&#xff0c;是一个基于POSIX和UNIX的多用户、多任务、 支持多线程和多CPU的操作系统。它能运行主要的UNIX工具软件、应用程序和网络协议。它支持32位和 64位硬件。 Linux内核 是一个Linux系统…

Backtrader 文档学习- Sizers

Backtrader 文档学习- Sizers 1.概述 智能仓位 Strategy提供了交易方法&#xff0c;即&#xff1a;buy&#xff0c;sell和close。看一下buy的定义&#xff1a; def buy(self, dataNone,sizeNone, priceNone, plimitNone,exectypeNone, validNone, tradeid0, **kwargs):注意&…

电路设计(13)——生产线易拉罐自动计数装置的proteus仿真

1.设计要求 使用指定元件&#xff0c;用模电、数电等有关知识&#xff0c;设计并制作一个易拉罐饮料计数自动化的模拟装置。生产单位常采用红外自动计数装置&#xff0c;将装有饮料的易拉罐放在马达带动的传动带上&#xff0c;在传动带运动的过程中让每个易拉罐依次同一方向地穿…

Linux第43步_移植ST公司uboot的第4步_uboot测试

uboot移植结束后&#xff0c;需要进行测试。 1、烧录程序 1)、将STM32MP157开发板的网络接口与路由器的网络接口通过网线连接起来。 2)、将开发板的串口和电脑通过USB线连接起来。 3)、将开发板的USB OTG接口和电脑通过USB线连接起来。 4)、将开发板上拨码开关拨到“000”…

RTthread线程间通信(邮箱,消息队列,信号/软件中断)---01实际使用API函数

layout: post title: “RT-Thread线程间通信” date: 2024-2-5 15:39:08 0800 tags: RT-Thread 线程间通信 这一篇是实际使用, 代码分析看后面的文章 一般可以使用全局变量以及线程间同步进行实现 RT-Thread也提供了一部分的通信机制 邮箱 一个线程发送, 另外的线程接受信息…

二叉树的最近公共祖先,力扣

目录 题目地址&#xff1a; 题目&#xff1a; 审题目事例提示&#xff1a; 解题方法&#xff1a; 解题分析&#xff1a; 解题思路&#xff1a; 代码实现&#xff1a; 补充说明&#xff1a; 代码优化&#xff1a; 代码实现(存储父节点) : 题目地址&#xff1a; 236. 二叉树的最近…

人工智能的运维服务有哪些?智能化运维发展方向有哪些

当前人工智能运维服务的主要类型和特点&#xff1f;智能化运维的未来发展趋势&#xff0c;包括但不限于技术进步、行业应用以及潜在的挑战和机遇。 目前人工智能运维服务的主要类型和优点包括&#xff1a; 基于规则的专家系统:根据事先定义的规则和逻辑进行故障检测和处理。特…

linux centos 安装teleport

效果 安装 1.创建目录 mkdir -p /opt/teleport/data cd /opt/teleport/2.下载解压文件 wget https://tp4a.com/static/download/teleport-server-linux-x64-3.6.4-b3.tar.gz tar -xvf teleport-server-linux-x64-3.6.4-b3.tar.gz3.安装 cd /opt/teleport/teleport-server-l…

每日一题来啦!请查收~(至少是其他数字两倍,两个数组的交集)

今天要写的题目有哪些呢&#xff1f; 747. 至少是其他数字两倍的最大数 - 力扣&#xff08;LeetCode&#xff09; int dominantIndex(int* nums, int numsSize) {int max0;maxnums[0];int index0;for(int i1;i<numsSize;i){if(nums[i]>max){maxnums[i];indexi;i;//找出最…

c++之说_12|模板

关于模板&#xff0c;至少我们要先了解几个概念 一&#xff1a;函数模板 二&#xff1a;类模板 三&#xff1a;模板特化 四&#xff1a;形参参数包 模板覆盖的东西太多 我目前也不了解太多 函数模板 语法 template<typename 类型名,typename 类型名,typename ...多参…

KMP算法|next指针|详细讲解学习

KMP 算法介绍 KMP 算法是基于串的朴素模式匹配算法优化的。 串的朴素模式匹配算法是将主串中所有的与模式串长度相等的子串与模式串进行比较&#xff0c;如果模式串与进行比较的的子串相等&#xff0c;就匹配成功&#xff0c;否则匹配失败。 在 KMP 算法的理解的基础上&#x…

SpringFramework实战指南(六)

SpringFramework实战指南(六) 4.4 基于 配置类 方式管理 Bean4.4.1 完全注解开发理解4.4.2 实验一:配置类和扫描注解4.4.3 实验二:@Bean定义组件4.4.4 实验三:高级特性:@Bean注解细节4.4.5 实验四:高级特性:@Import扩展4.4.6 实验五:基于注解+配置类方式整合三层架构组…

C#(C Sharp)学习笔记_前言及Visual Studio Code配置C#运行环境【一】

前言 这可以说是我第一次正式的踏入C#的学习道路&#xff0c;我真没想过我两年前是怎么跳过C#去学Unity3D游戏开发的&#xff08;当然了&#xff0c;游戏开发肯定是没有成功的&#xff0c;都是照搬代码&#xff09;。而现在&#xff0c;我真正地学习一下C#&#xff0c;就和去年…

调和平均

L1-4 调和平均 分数 10 作者 陈越 单位 浙江大学 N 个正数的算数平均是这些数的和除以 N&#xff0c;它们的调和平均是它们倒数的算数平均的倒数。本题就请你计算给定的一系列正数的调和平均值。 输入格式&#xff1a…

Springboot 整合 Elasticsearch(三):使用RestHighLevelClient操作ES ①

&#x1f4c1; 前情提要&#xff1a; Springboot 整合 Elasticsearch&#xff08;一&#xff09;&#xff1a;Linux下安装 Elasticsearch 8.x Springboot 整合 Elasticsearch&#xff08;二&#xff09;&#xff1a;使用HTTP请求来操作ES 目录 一、Springboot 整合 Elasticsea…

Pymysql之Connection中常用API

Connection中常用API 1、open() &#xff1a;检测数据库是否连接。 connect.open&#xff1a;如果数据库连接返回Trhe&#xff0c;否则返回False。 2、ping(reconnectTrue) connect.ping(reconnectTrue):如果reconnectTrue表示连接断开后&#xff0c;重新进行连接。 import…

Android Compose 一个音视频APP——Magic Music Player

Magic Music APP Magic Music APP Magic Music APP概述效果预览-视频资源功能预览Library歌曲播放效果预览歌曲播放依赖注入设置播放源播放进度上一首&下一首UI响应 歌词歌词解析解析成行逐行解析 视频播放AndroidView引入Exoplayer自定义Exoplayer样式横竖屏切换 歌曲多任…