配套视频:【编程不良人】2021年SpringBoot最新最全教程_哔哩哔哩_bilibili
【编程不良人】2021年SpringBoot最新最全教程_哔哩哔哩_bilibili
Thymeleaf是一个用于web和独立环境的现代服务器端Java模板引擎。
Jsp也是Java模板引擎,Thymeleaf完全可以用来替代Jsp,在使用时Jsp和Thymeleaf不要混用
--摘自官网Thymeleaf
Thymeleaf
是跟Velocity、FreeMarker类似的模板引擎,它可以完全替代JSP,相较与其他的模板引擎相比, Thymeleaf在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。注意:使用时必须要经过controller。
<!--引入thymeleaf依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>
server:port: 8888servlet:context-path: /spring-boot-day7# 配置Thymeleafspring:thymeleaf:prefix: classpath:/templates/ # 指定Thymeleaf前缀目录suffix: .html # 指定模板后缀是否开启Thymeleaf缓存,默认是true开启缓存# 在开发过程中推荐使用false(类似jsp加载)
编写控制器测试
package ller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;/*** @ClassName HelloController* @Description TODO* @Author Jiangnan Cui* @Date 2022/6/11 15:59* @Version 1.0*/@Controller //一定要是@Controller,不能再使用@RestController注解@RequestMapping("hello")public class HelloController {@RequestMapping("hello")public String hello(){System.out.println("测试springboot与Thymeleaf的集成");return "index";// templates/index.html,最终封装成index.html进行返回// 直接访问根路径(localhost:8888/spring-boot-day7/)加载出index.html,但无渲染效果}}
在templates目录中定义模板index.html
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>测试SpringBoot与Thymeleaf的集成</title></head><body><h1>Hello,Thymeleaf!</h1></body></html>
测试路径:直接访问根路径定位到templates/index.html
localhost:8888/spring-boot-day7/
localhost:8888/spring-boot-day7/hello/hello
新建demo.html用于页面展示
使用Thymeleaf时必须在html页面中加入唯一的命名空间(namespace):Thymeleaf简写th,在xmlns:名字处写th
<html lang="en" xmlns:th="">
注意:有的插件可以导入/提示命名空间!
初始的demo.html页面
<!DOCTYPE html><html lang="en" xmlns:th=""><head><meta charset="UTF-8"><title>用来测试Thymeleaf语法</title></head><body><h1>测试Thymeleaf语法基本使用</h1></body></html>
新建控制器DemoController
package ller;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;/*** @ClassName DemoController* @Description TODO* @Author Jiangnan Cui* @Date 2022/6/13 20:36* @Version 1.0*/@Controller@RequestMapping("demo")public class DemoController {@RequestMapping("demo")public String demo(HttpServletRequest request, Model model, HttpSession session){System.out.println("demo ok!");return "demo"; //templates/demo.html,最终封装成demo.html进行返回}}
测试路径:localhost:8888/spring-boot-day7/demo/demo
DemoController
package ller;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;/*** @ClassName DemoController* @Description TODO* @Author Jiangnan Cui* @Date 2022/6/13 20:36* @Version 1.0*/@Controller@RequestMapping("demo")public class DemoController {@RequestMapping("demo")//model底层封装的也是request作用域public String demo(HttpServletRequest request, Model model, HttpSession session){System.out.println("demo ok!");/*** 1.传递单个数据:String、Integer、解析超链接*/String name = "小崔";request.setAttribute("name",name);Integer age = 27;model.addAttribute("age",age);String content = "<a href=''>百度一下</a>";model.addAttribute("content",content);return "demo";}}
demo.html
<h2>1.获取单个数据</h2><!--th:text="${属性名}"获取request作用域数据:直接将获取到的数据以文本形式渲染到页面中th:utext="${属性名}"获取request作用域数据:先将获取到的数据解析成html标签,再以文本形式渲染到页面中--><h3>String类型数据:<span th:text="${name}"/></h3><h3>Integer类型数据:<span th:text="${age}"/></h3><h3>超链接:<span th:utext="${content}"/></h3><h3>输入框:</h3><input type="text" name="username" th:value="${name}"><input type="text" name="age" th:value="${age}">
新建对象User
package ity;import java.util.Date;/*** @ClassName User* @Description TODO* @Author Jiangnan Cui* @Date 2022/6/13 20:33* @Version 1.0*/public class User {private Integer id;private String name;private Double salary;private Date birthday;public User() {}public User(Integer id, String name, Double salary, Date birthday) {this.id = id;this.name = name;this.salary = salary;this.birthday = birthday;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + ''' +", salary=" + salary +", birthday=" + birthday +'}';}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Double getSalary() {return salary;}public void setSalary(Double salary) {this.salary = salary;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}}
DemoController
package ller;import ity.User;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;import java.util.Arrays;import java.util.Date;import java.util.List;/*** @ClassName DemoController* @Description TODO* @Author Jiangnan Cui* @Date 2022/6/13 20:36* @Version 1.0*/@Controller@RequestMapping("demo")public class DemoController {@RequestMapping("demo")//model底层封装的也是request作用域public String demo(HttpServletRequest request, Model model, HttpSession session){System.out.println("demo ok!");/*** 2.传递对象类型数据*/User user = new User(1,"小崔",1234.56,new Date());model.addAttribute("user",user);return "demo";}}
demo.html
<h2>2.获取对象类型数据</h2><h3>user.id:<span th:text="${user.id}"/><br>user.name:<span th:text="${user.name}"/><br>user.salary:<span th:text="${user.salary}"/><br><!--格式化日期:${#dates.format(格式化值,'格式化的格式')}},其中,dates.format为内置函数-->user.birthday:<span th:text="${#dates.format(user.birthday,'yyyy-MM-dd HH:mm:ss')}"/></h3>
DemoController
package ller;import ity.User;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;import java.util.Arrays;import java.util.Date;import java.util.List;/*** @ClassName DemoController* @Description TODO* @Author Jiangnan Cui* @Date 2022/6/13 20:36* @Version 1.0*/@Controller@RequestMapping("demo")public class DemoController {@RequestMapping("demo")//model底层封装的也是request作用域public String demo(HttpServletRequest request, Model model, HttpSession session){System.out.println("demo ok!");/*** 3.传递集合类型数据*/List<User> users = Arrays.asList(new User(11,"熊大",1111.11,new Date()),new User(22,"熊二",2222.22,new Date()),new User(33,"光头强",3333.33,new Date()));model.addAttribute("users",users);return "demo";}}
demo.html
<h2>3.获取集合类型数据</h2><ul><!--遍历数据:th:each="变量(current_element当前遍历元素),变量(state遍历状态对象):集合"--><li th:each="user,state:${users}">state count: <span th:text="${unt}"></span>state odd: <span th:text="${state.odd}"></span>state even: <span th:text="${state.even}"></span>state size: <span th:text="${state.size}"></span>id: <span th:text="${user.id}"></span>name: <span th:text="${user.name}"></span>salary: <span th:text="${user.salary}"></span>birthday: <span th:text="${#dates.format(user.birthday,'yyyy年MM月dd日')}"></span></li></ul>
补充:展示多条数据
直接遍历集合
<ul th:each="user:${users}"><li th:text="${user.id}"></li><li th:text="${user.name}"></li><li th:text="${user.age}"></li><li th:text="${#dates.format(user.bir,'yyyy-MM-dd')}"></li></ul>
遍历时获取遍历状态
<ul th:each="user,userStat:${users}"><li><span th:text="${unt}"/>-<span th:text="${user.id}"/></li> 获取遍历次数 count 从1开始 index 从0开始<li><span th:text="${userStat.odd}"/>-<span th:text="${user.name}"/></li> 获取当前遍历是否是奇数行<li><span th:text="${userStat.even}"/>-<span th:text="${user.age}"/></li> 获取当前遍历是否是偶数行<li><span th:text="${userStat.size}"/>-<span th:text="${user.bir}"/></li> 获取当前集合的总条数</ul>
demo.html
<h2>4.有条件的展示数据</h2><!-- th:if="${age>=25}" 作用:有条件的显示数据--><div style="width: 100px;height: 100px;background: red" th:if="${age>25}">我是小红</div><div style="width: 100px;height: 100px;background: blue" th:if="${age<=25}">我是小蓝</div>
补充运算符:
gt: great than(大于) >ge: great equal(大于等于) >=eq: equal(等于) ==lt: less than(小于) <le: less equal(小于等于) <=ne: not equal(不等于) !=
DemoControlleer
package ller;import ity.User;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;import java.util.Arrays;import java.util.Date;import java.util.List;/*** @ClassName DemoController* @Description TODO* @Author Jiangnan Cui* @Date 2022/6/13 20:36* @Version 1.0*/@Controller@RequestMapping("demo")public class DemoController {@RequestMapping("demo")//model底层封装的也是request作用域public String demo(HttpServletRequest request, Model model, HttpSession session){System.out.println("demo ok!");/*** 5.向session作用域存储数据*/session.setAttribute("username","猪猪侠");return "demo";}}
demo.html
<h2>5.获取session作用域数据</h2><span th:text="${session.username}"></span>
访问路径:localhost:8888/spring-boot-day7/demo/demo
# 总结- 1.使用 th:text="${属性名}" 获取对应数据,获取数据时会将对应标签中数据清空,因此最好是空标签- 2.使用 th:utext="${属性名}" 获取对应的数据,可以将数据中html先解析在渲染到页面- 3.使用 th:value="${属性名}" 获取数据直接作为表单元素value属性
使用thymeleaf模板时项目中的静态资源默认放在resources路径下的static目录中
demo.css
h2{background: yellow;}
demo.js
function test() {alert('test');}
demo.html
<!DOCTYPE html><html lang="en" xmlns:th=""><head><meta charset="UTF-8"><title>用来测试Thymeleaf语法</title><!--th:href="@{/}",其中,@{/}用来获取应用名称--><!--引入css资源--><link rel="stylesheet" th:href="@{/demo.css}"><!--引入js资源--><script th:src="@{/demo.js}"></script><script>test();/*** 通过js代码获取应用名:* 通过Thymeleaf语法获取项目名,使用Thymeleaf内联表达式 [[thymeleaf]]*/let contentPath = "[[@{/}]]";console.log("项目名",contentPath);</script></head><body><h1>测试Thymeleaf语法基本使用</h1><h2>1.获取单个数据</h2><!--th:text="${属性名}"获取request作用域数据:直接将获取到的数据以文本形式渲染到页面中th:utext="${属性名}"获取request作用域数据:先将获取到的数据解析成html标签,再以文本形式渲染到页面中-->String类型数据:<span th:text="${name}"/><br>Integer类型数据:<span th:text="${age}"/><br>超链接:<span th:utext="${content}"/><br>输入框:<br><input type="text" name="username" th:value="${name}"><br><input type="text" name="age" th:value="${age}"><h2>2.获取对象类型数据</h2>user.id:<span th:text="${user.id}"/><br>user.name:<span th:text="${user.name}"/><br>user.salary:<span th:text="${user.salary}"/><br><!--格式化日期:${#dates.format(格式化值,'格式化的格式')}},其中,dates.format为内置函数-->user.birthday:<span th:text="${#dates.format(user.birthday,'yyyy-MM-dd HH:mm:ss')}"/><h2>3.获取集合类型数据</h2><ul><!--遍历数据:th:each="变量(current_element当前遍历元素),变量(state遍历状态对象):集合"--><li th:each="user,state:${users}">state count: <span th:text="${unt}"></span>state odd: <span th:text="${state.odd}"></span>state even: <span th:text="${state.even}"></span>state size: <span th:text="${state.size}"></span>id: <span th:text="${user.id}"></span>name: <span th:text="${user.name}"></span>salary: <span th:text="${user.salary}"></span>birthday: <span th:text="${#dates.format(user.birthday,'yyyy年MM月dd日')}"></span></li></ul><h2>4.有条件的展示数据</h2><!-- th:if="${age>=25}" 作用:有条件的显示数据--><div style="width: 100px;height: 100px;background: red" th:if="${age>25}">我是小红</div><div style="width: 100px;height: 100px;background: blue" th:if="${age<=25}">我是小蓝</div><h2>5.获取session作用域数据</h2><span th:text="${session.username}"></span></body></html>
或者
<link rel="stylesheet" th:href="@{/css/index.css}"><script th:src="@{/js/jquery-min.js}"></script>
注意: @{/}代表通过thymeleaf语法动态获取应用名
在js代码中获取项目名:
<script>const ctx = '[[@{/}]]';</script>
注意:[[书写thymeleaf语法]],这里[[ ]]是thymeleaf内嵌表达式。
最终效果:
配套视频:【编程不良人】2021年SpringBoot最新最全教程_哔哩哔哩_bilibili
【编程不良人】2021年SpringBoot最新最全教程_哔哩哔哩_bilibili
需求分析: 分析这个项目含有哪些功能模块用户模块:注册登录验证码安全退出真实用户员工模块:添加员工+上传头像展示员工列表+展示员工头像删除员工信息+删除员工头像更新员工信息+更新员工头像库表设计(概要设计): 1.分析系统有哪些表 2.分析表与表关系 3.确定表中字段(显性字段 隐性字段(业务字段))2张表 1.用户表 userid username realname password gender2.员工表 employeeid name salary birthday photo创建一个库: ems-thymeleaf详细设计:省略编码(环境搭建+业务代码开发)1.创建一个springboot项目 项目名字: ems-thymeleaf2.修改配置文件为 l l 2.5.03.修改端口 8888 项目名: ems-thymeleaf4.springboot整合thymeleaf使用a.引入依赖:thymeleafb.配置文件中指定thymeleaf相关配置c.编写控制器测试5.springboot整合mybatisa.引入依赖:mysql、druid、mybatis-springboot-staterb.配置文件中 6.导入项目页面static 存放静态资源templates 目录 存放模板文件测试上线部署维护发版======================================================================用户相关:1.登录2.注册3.验证码1.验证码工具类
新建spring Initializr项目,引入Spring Web,项目命名为ems-thymeleaf
<!--引入Thymeleaf依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId><version>2.7.0</version></dependency>
修改application.properties为l,添加如下配置:
# 公共配置server:port: 8888servlet:context-path: /ems-thymeleaf# Thymeleaf配置spring:thymeleaf:cache: falseprefix: classpath:/templates/suffix: .html
新建demo.html
<!DOCTYPE html><html lang="en" xmlns=""><head><meta charset="UTF-8"><title>测试Thymeleaf</title></head><body><h1>测试Thymeleaf</h1><h4>获取数据:<span th:text="${msg}"></span></h4></body></html>
DemoController
package ller;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;/*** @ClassName DemoController* @Description TODO* @Author Jiangnan Cui* @Date 2022/6/27 9:45* @Version 1.0*/@Controller@RequestMapping("demo")public class DemoController {private static final Logger log = Logger(DemoController.class);@RequestMapping("demo")public String demo(Model model){log.debug("demo ok");model.addAttribute("msg","hello,Thymeleaf!");return "demo";}}
启动项目,访问路径:localhost:8888/ems-thymeleaf/demo/demo
<!--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><!--mybatis-spring-boot-starter--><dependency><groupId&batis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.0</version></dependency>
# 公共配置server:port: 8888servlet:context-path: /ems-thymeleaf# Thymeleaf配置spring:thymeleaf:cache: falseprefix: classpath:/templates/suffix: .html# 配置数据源datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: sql.jdbc.Driverurl: jdbc:mysql://localhost:3306/ems-thymeleaf?characterEncoding=UTF-8username: rootpassword: 123456# 配置mybatismybatis:mapper-locations: classpath:com/study/mapper/*.xmltype-aliases-package: ity# 配置日志logging:level:root: infocom.study: debug
启动类添加注解扫描
package com.study;batis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication@MapperScan("com.study.dao")public class EmsThymeleafApplication {public static void main(String[] args) {SpringApplication.run(EmsThymeleafApplication.class, args);}}
重新启动一下项目,运行不报错即可。
在static目录下导入css、img、js等静态资源,导入之后Rebuild一下项目
新建MVC配置类:不用单独开发controller来访问html页面
package fig;import t.annotation.Configuration;import org.springframework.fig.annotation.ViewControllerRegistry;import org.springframework.fig.annotation.WebMvcConfigurer;/*** @ClassName MvcConfig* @Description TODO* @Author Jiangnan Cui* @Date 2022/6/27 10:35* @Version 1.0*/@Configurationpublic class MvcConfig implements WebMvcConfigurer {@Override//通过在这里面配置,不需要再为每一个访问thymeleaf模板页面单独开发一个controller请求了public void addViewControllers(ViewControllerRegistry registry) {//ViewController: 请求路径,ViewName: 跳转视图registry.addViewController("login").setViewName("login");registry.addViewController("register").setViewName("regist");//注意与HTML页面对应}}
启动项目,访问页面:
(1)注册页面:localhost:8888/ems-thymeleaf/register
(2)登录页面:localhost:8888/ems-thymeleaf/login
配套视频:【编程不良人】2021年SpringBoot最新最全教程_哔哩哔哩_bilibili
验证码工具类
package com.study.utils;import javax.imageio.ImageIO;import java.awt.*;import AffineTransform;import java.awt.image.BufferedImage;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStream;import java.util.Arrays;import java.util.Random;/***@创建人 cx*@创建时间 2018/11/27 17:36*@描述 验证码生成*/public class VerifyCodeUtils{//使用到Algerian字体,系统里没有的话需要安装字体,字体只显示大写,去掉了1,0,i,o几个容易混淆的字符public static final String VERIFY_CODES = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";private static Random random = new Random();/*** 使用系统默认字符源生成验证码* @param verifySize 验证码长度* @return*/public static String generateVerifyCode(int verifySize){return generateVerifyCode(verifySize, VERIFY_CODES);}/*** 使用指定源生成验证码* @param verifySize 验证码长度* @param sources 验证码字符源* @return*/public static String generateVerifyCode(int verifySize, String sources){if(sources == null || sources.length() == 0){sources = VERIFY_CODES;}int codesLen = sources.length();Random rand = new Random(System.currentTimeMillis());StringBuilder verifyCode = new StringBuilder(verifySize);for(int i = 0; i < verifySize; i++){verifyCode.append(sources.Int(codesLen-1)));}String();}/*** 生成随机验证码文件,并返回验证码值* @param w* @param h* @param outputFile* @param verifySize* @return* @throws IOException*/public static String outputVerifyImage(int w, int h, File outputFile, int verifySize) throws IOException{String verifyCode = generateVerifyCode(verifySize);outputImage(w, h, outputFile, verifyCode);return verifyCode;}/*** 输出随机验证码图片流,并返回验证码值* @param w* @param h* @param os* @param verifySize* @return* @throws IOException*/public static String outputVerifyImage(int w, int h, OutputStream os, int verifySize) throws IOException{String verifyCode = generateVerifyCode(verifySize);outputImage(w, h, os, verifyCode);return verifyCode;}/*** 生成指定验证码图像文件* @param w* @param h* @param outputFile* @param code* @throws IOException*/public static void outputImage(int w, int h, File outputFile, String code) throws IOException{if(outputFile == null){return;}File dir = ParentFile();if(!ists()){dir.mkdirs();}ateNewFile();FileOutputStream fos = new FileOutputStream(outputFile);outputImage(w, h, fos, code);fos.close();} catch(IOException e){throw e;}}/*** 输出指定验证码图片流* @param w* @param h* @param os* @param code* @throws IOException*/public static void outputImage(int w, int h, OutputStream os, String code) throws IOException{int verifySize = code.length();BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);Random rand = new Random();Graphics2D g2 = ateGraphics();g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);Color[] colors = new Color[5];Color[] colorSpaces = new Color[] { Color.WHITE, Color.CYAN,Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE,Color.PINK, Color.YELLOW };float[] fractions = new float[colors.length];for(int i = 0; i < colors.length; i++){colors[i] = Int(colorSpaces.length)];fractions[i] = Float();}Arrays.sort(fractions);g2.setColor(Color.GRAY);// 设置边框色g2.fillRect(0, 0, w, h);Color c = getRandColor(200, 250);g2.setColor(c);// 设置背景色g2.fillRect(0, 2, w, h-4);//绘制干扰线Random random = new Random();g2.setColor(getRandColor(160, 200));// 设置线条的颜色for (int i = 0; i < 20; i++) {int x = Int(w - 1);int y = Int(h - 1);int xl = Int(6) + 1;int yl = Int(12) + 1;g2.drawLine(x, y, x + xl + 40, y + yl + 20);}// 添加噪点float yawpRate = 0.05f;// 噪声率int area = (int) (yawpRate * w * h);for (int i = 0; i < area; i++) {int x = Int(w);int y = Int(h);int rgb = getRandomIntColor();image.setRGB(x, y, rgb);}shear(g2, w, h, c);// 使图片扭曲g2.setColor(getRandColor(100, 160));int fontSize = h-4;Font font = new Font("Algerian", Font.ITALIC, fontSize);g2.setFont(font);char[] chars = CharArray();for(int i = 0; i < verifySize; i++){AffineTransform affine = new AffineTransform();affine.setToRotation(Math.PI / 4 * Double() * (Boolean() ? 1 : -1), (w / verifySize) * i + fontSize/2, h/2);g2.setTransform(affine);g2.drawChars(chars, i, 1, ((w-10) / verifySize) * i + 5, h/2 + fontSize/2 - 10);}g2.dispose();ImageIO.write(image, "jpg", os);}private static Color getRandColor(int fc, int bc) {if (fc > 255)fc = 255;if (bc > 255)bc = 255;int r = fc + Int(bc - fc);int g = fc + Int(bc - fc);int b = fc + Int(bc - fc);return new Color(r, g, b);}private static int getRandomIntColor() {int[] rgb = getRandomRgb();int color = 0;for (int c : rgb) {color = color << 8;color = color | c;}return color;}private static int[] getRandomRgb() {int[] rgb = new int[3];for (int i = 0; i < 3; i++) {rgb[i] = Int(255);}return rgb;}private static void shear(Graphics g, int w1, int h1, Color color) {shearX(g, w1, h1, color);shearY(g, w1, h1, color);}private static void shearX(Graphics g, int w1, int h1, Color color) {int period = Int(2);boolean borderGap = true;int frames = 1;int phase = Int(2);for (int i = 0; i < h1; i++) {double d = (double) (period >> 1)* Math.sin((double) i / (double) period+ (6.2831853071795862D * (double) phase)/ (double) frames);g.copyArea(0, i, w1, 1, (int) d, 0);if (borderGap) {g.setColor(color);g.drawLine((int) d, i, 0, i);g.drawLine((int) d + w1, i, w1, i);}}}private static void shearY(Graphics g, int w1, int h1, Color color) {int period = Int(40) + 10; // 50;boolean borderGap = true;int frames = 20;int phase = 7;for (int i = 0; i < w1; i++) {double d = (double) (period >> 1)* Math.sin((double) i / (double) period+ (6.2831853071795862D * (double) phase)/ (double) frames);g.copyArea(i, 0, 1, h1, 0, (int) d);if (borderGap) {g.setColor(color);g.drawLine(i, (int) d, i, 0);g.drawLine(i, (int) d + h1, i, h1);}}}}
添加控制器UserController
package ller;import com.study.utils.VerifyCodeUtils;import com.sun.deploy.HttpResponse;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.io.IOException;/*** @ClassName UserController* @Description TODO* @Author Jiangnan Cui* @Date 2022/6/27 11:53* @Version 1.0*/@Controller@RequestMapping("user")public class UserController {/*** @MethodName generateImageCode* @Description 生成图片验证码 * @param: session* @param: response * @Author Jiangnan Cui* @Date 2022/6/27 12:08*/@RequestMapping("generateImageCode")public void generateImageCode(HttpSession session, HttpServletResponse response) throws IOException {//1.生成4位随机数String code = ateVerifyCode(4);//2.保存到session作用域session.setAttribute("code",code);//3.设置响应类型response.setContentType("image/png");//4.获得输出流ServletOutputStream sos = OutputStream();//5.根据随机数生成图片VerifyCodeUtils.outputImage(220,60,sos,code);}}
register.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" ".dtd"><html xmlns:th=""><head><title>regist</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" th:href="@{/css/style.css}" /></head><body><div id="wrap"><div id="top_content"><div id="header"><div id="rightheader"><p>2009/11/20<br /></p></div><div id="topheader"><h1 id="title"><a href="#">main</a></h1></div><div id="navigation"></div></div><div id="content"><p id="whereami"></p><h1>注册</h1><form th:action="@{/user/register}" method="post"><table cellpadding="0" cellspacing="0" border="0"class="form_table"><tr><td valign="middle" align="right">用户名:</td><td valign="middle" align="left"><input type="text" class="inputgri" name="username" /></td></tr><tr><td valign="middle" align="right">真实姓名:</td><td valign="middle" align="left"><input type="text" class="inputgri" name="realname" /></td></tr><tr><td valign="middle" align="right">密码:</td><td valign="middle" align="left"><input type="password" class="inputgri" name="password" /></td></tr><tr><td valign="middle" align="right">性别:</td><td valign="middle" align="left">男<input type="radio" class="inputgri" name="gender" value="1" checked="checked"/>女<input type="radio" class="inputgri" name="gender" value="0"/></td></tr><tr><td valign="middle" align="right">验证码:<img id="num" th:src="@{/user/generateImageCode}" /><a href="javascript:;" οnclick="changeImageCode()">换一张</a><script>function changeImageCode(){ElementById('num').src = '[[@{/user/generateImageCode}]]?'+(new Date()).getTime()}</script></td><td valign="middle" align="left"><input type="text" class="inputgri" name="code" /></td></tr></table><p><input type="submit" class="button" value="立即注册 »" /><a href="login.html">已有账号,返回登录</a></p></form></div></div><div id="footer"><div id="footer_bg">ABC@126</div></div></div></body></html>
测试路径
(1)localhost:8888/ems-thymeleaf/user/generateImageCode
(2)localhost:8888/ems-thymeleaf/register
配套视频:【编程不良人】2021年SpringBoot最新最全教程_哔哩哔哩_bilibili
创建数据库ems-thymeleaf、表user
create database if not exists `ems-thymeleaf`;
use `ems-thymeleaf`;
create table if not exists `user`(id int(20) not null auto_increment comment '用户ID',username varchar(100) not null comment '用户名',realname varchar(100) comment '真实姓名',password varchar(100) comment '密码',gender boolean comment '性别',primary key(id)
)engine=innodb charset=utf8;
新建实体类User
package ity;/*** @ClassName User* @Description TODO* @Author Jiangnan Cui* @Date 2022/6/27 15:49* @Version 1.0*/public class User {private Integer id;private String username;private String realname;private String password;private Boolean gender;public User() {}public User(Integer id, String username, String realname, String password, Boolean gender) {this.id = id;this.username = alname = realname;this.password = der = gender;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + ''' +", realname='" + realname + ''' +", password='" + password + ''' +", gender=" + gender +'}';}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getRealname() {return realname;}public void setRealname(String realname) {alname = realname;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public Boolean getGender() {return gender;}public void setGender(Boolean gender) {der = gender;}}
创建UserDAO
package com.study.dao;import ity.User;/*** @ClassName UserDAO* @Description TODO* @Author Jiangnan Cui* @Date 2022/6/27 16:02* @Version 1.0*/public interface UserDAO {/*** @MethodName findByUserName* @Description 根据用户名查找用户* @param: username* @return: ity.User* @Author Jiangnan Cui* @Date 2022/6/27 16:03*/User findByUserName(String username);/*** @MethodName register* @Description 用户注册* @param: user* @Author Jiangnan Cui* @Date 2022/6/27 16:03*/void register(User user);}
创建UserDAOMapper
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapperPUBLIC "-//mybatis//DTD Mapper 3.0//EN"".dtd" ><mapper namespace="com.study.dao.UserDAO"><!--findByUserName--><select id="findByUserName" parameterType="String" resultType="User">selectid,username,realname,password,genderfrom `user`where username=#{username}</select><!--register--><insert id="register" parameterType="User" useGeneratedKeys="true" keyProperty="id">insert into `user` values(#{id},#{username},#{realname},#{password},#{gender})</insert></mapper>
创建UserService
package com.study.service;import ity.User;/*** @ClassName UserService* @Description TODO* @Author Jiangnan Cui* @Date 2022/6/27 15:48* @Version 1.0*/public interface UserService {/*** @MethodName register* @Description 用户注册* @param: user* @Author Jiangnan Cui* @Date 2022/6/27 15:50*/void register(User user);}
创建UserServiceImpl
package com.study.service;import com.study.dao.UserDAO;import ity.User;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import ansaction.annotation.Transactional;import org.springframework.util.DigestUtils;import org.springframework.util.ObjectUtils;import java.nio.charset.StandardCharsets;/*** @ClassName UserServiceImpl* @Description TODO* @Author Jiangnan Cui* @Date 2022/6/27 16:14* @Version 1.0*/@Service@Transactionalpublic class UserServiceImpl implements UserService{//业务逻辑层调用数据访问层private UserDAO userDAO;@Autowiredpublic UserServiceImpl(UserDAO userDAO) {this.userDAO = userDAO;}/*** @MethodName register* @Description* @param: user* @Author Jiangnan Cui* @Date 2022/6/27 16:22*/@Overridepublic void register(User user) {//1.根据用户名从数据库中查询是否存在已经注册的用户User userDB = userDAO.Username());//2.判断该用户是否存在if(!ObjectUtils.isEmpty(userDB))throw new RuntimeException("当前用户已被注册!");//不为空时抛出异常//3.为空时表明用户不存在,继续注册用户//对明文密码进行加密:相同字符串多次使用md5加密后结果一致String newPassword = DigestUtils.Password().getBytes(StandardCharsets.UTF_8));user.setPassword(newPassword);ister(user);}}
新建UserController
package ller;import ity.User;import com.study.service.UserService;import com.study.utils.VerifyCodeUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.io.IOException;/*** @ClassName UserController* @Description TODO* @Author Jiangnan Cui* @Date 2022/6/27 11:53* @Version 1.0*/@Controller@RequestMapping("user")public class UserController {//新建日志对象private static final Logger log = Logger(UserController.class);/*** @MethodName generateImageCode* @Description 生成图片验证码* @param: session* @param: response* @Author Jiangnan Cui* @Date 2022/6/27 12:08*/@RequestMapping("generateImageCode")public void generateImageCode(HttpSession session, HttpServletResponse response) throws IOException {//1.生成4位随机数String code = ateVerifyCode(4);//2.保存到session作用域session.setAttribute("code",code);//3.设置响应类型response.setContentType("image/png");//4.获得输出流ServletOutputStream sos = OutputStream();//5.根据随机数生成图片VerifyCodeUtils.outputImage(220,60,sos,code);}private UserService userService;@Autowiredpublic UserController(UserService userService) {this.userService = userService;}/*** @MethodName register* @Description 用户注册* @param: user* @param: code* @param: session* @return: java.lang.String* @Author Jiangnan Cui* @Date 2022/6/27 15:57*/@RequestMapping("register")public String register(User user,String code,HttpSession session){log.debug("用户名:{},真实姓名:{},密码:{},性别:{}",Username(),Realname(),Password(),Gender());log.debug("用户输入的验证码: {}",code);try {//1.判断用户输入验证码和session中的验证码是否一致String sessionCode = Attribute("code").toString();if(!sessionCode.equalsIgnoreCase(code))throw new RuntimeException("验证码输入错误!");//2.注册用户ister(user);} catch (RuntimeException e) {e.printStackTrace();return "redirect:/register";//注册失败回到注册}return "redirect:/login";//注册成功转到登录}}
访问路径:localhost:8888/ems-thymeleaf/register,进行注册,成功跳转到登录页面,失败回到注册页面!
配套视频:【编程不良人】2021年SpringBoot最新最全教程_哔哩哔哩_bilibili
在UserService添加登录方法
/*** @MethodName login* @Description 用户登录* @param: username* @param: password* @return: ity.User* @Author Jiangnan Cui* @Date 2022/6/27 17:02*/User login(String username,String password);
在UserServiceImpl实现登录方法
/*** @MethodName login* @Description 用户登录* @param: username* @param: password* @return: ity.User* @Author Jiangnan Cui* @Date 2022/6/27 17:03*/@Overridepublic User login(String username, String password) {//1.根据用户名查询用户User user = userDAO.findByUserName(username);//2.判断用户是否存在,存在执行登录;不存在,抛出异常if(ObjectUtils.isEmpty(user))throw new RuntimeException("用户名不存在!");//3.在用户存在的前提下,比较密码是否正确,正确执行登录;不正确,抛出异常//密码加密String passwordSecret = DigestUtils.Bytes(StandardCharsets.UTF_8));if(!Password().equals(passwordSecret))throw new RuntimeException("密码错误!");return user;}
UserController添加登录方法
/*** @MethodName login* @Description 用户登录* @param: username* @param: password* @param: session* @return: java.lang.String* @Author Jiangnan Cui* @Date 2022/6/27 17:11*/@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";//登录成功,跳转到查询所有员工信息控制器路径}
添加EmpployeeController
package ller;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;/*** @ClassName EmployeeController* @Description TODO* @Author Jiangnan Cui* @Date 2022/6/27 17:15* @Version 1.0*/@Controller@RequestMapping("employee")public class EmployeeController {private static final Logger log = Logger(EmployeeController.class);@RequestMapping("lists")public String list(Model model){log.debug("查询所有员工信息");return "emplist";}}
login.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" ".dtd"><html xmlns:th=""><head><title>login</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css"href="css/style.css" /></head><body><div id="wrap"><div id="top_content"><div id="header"><div id="rightheader"><p>2009/11/20<br /></p></div><div id="topheader"><h1 id="title"><a href="#">main</a></h1></div><div id="navigation"></div></div><div id="content"><p id="whereami"></p><h1>欢迎进入,请登录!</h1><form th:action="@{/user/login}" method="post"><table cellpadding="0" cellspacing="0" border="0"class="form_table"><tr><td valign="middle" align="right">用户名:</td><td valign="middle" align="left"><input type="text" class="inputgri" name="username" /></td></tr><tr><td valign="middle" align="right">密码:</td><td valign="middle" align="left"><input type="password" class="inputgri" name="password" /></td></tr></table><p><input type="submit" class="button" value="点我登录 »" /> <a href="regist.html">还没有账号,立即注册</a></p></form></div></div><div id="footer"><div id="footer_bg">ABC@126</div></div></div></body></html>
emplists.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" ".dtd"><html xmlns:th=""><head><title>emplist</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" th:href="@{/css/style.css}" /></head><body><div id="wrap"><div id="top_content"> <div id="header"><div id="rightheader"><p>2009/11/20 <br /><a th:if="${session.user!=null}" th:href="@{/user/logout}">安全退出</a><a th:if="${session.user==null}" th:href="@{/login}">点我登录</a></p></div><div id="topheader"><h1 id="title"><a href="#">main</a></h1></div><div id="navigation"></div></div><div id="content"><p id="whereami"></p><h1>欢迎 <span th:if="${session.user!=null}" th:text="${session.user.username}"></span><span th:if="${session.user==null}" >游客</span>!</h1><table class="table"><tr class="table_header"><td>编号</td><td>姓名</td><td>头像</td><td>工资</td><td>生日</td><td>操作</td></tr><tr th:each="employee,state:${employeeList}" th:class="${state.odd?'row1':'row2'}"><td><span th:text="${employee.id}"></span></td><td><span th:text="${employee.name}"></span></td><td><img th:src="@{/}+${employee.photo}" width="60"></td><td><span th:text="${employee.salary}"></span></td><td><span th:text="${#dates.format(employee.birthday,'yyyy/MM/dd')}"></span></td><td><a href="javascript:;" th:οnclick="'deleteEmployee('+${employee.id}+')'">删除</a><!-- <a th:href="@{/employee/detail?id=}+${employee.id}+'&name='+${employee.name}">更新</a>--><!-- <a th:href="@{/employee/detail(id=${employee.id},name=${employee.name})}">更新</a>--><a th:href="@{/employee/detail(id=${employee.id})}">更新</a></td></tr><script>function deleteEmployee(id){console.log(id);firm('确定要删除这条记录吗?')){location.href='[[@{/employee/delete?id=}]]'+id;}}</script></table><p><input type="button" class="button" value="添加" οnclick="addEmp()"/><script>function addEmp(){location.href = '[[@{/addEmp}]]';}</script></p></div></div><div id="footer"><div id="footer_bg">ABC@126</div></div></div></body></html>
测试路径:localhost:8888/ems-thymeleaf/login,登录成功跳转到员工列表页面,登录失败回到登录页面。
配套视频:【编程不良人】2021年SpringBoot最新最全教程_哔哩哔哩_bilibili
创建employee表
create table if not exists `employee`(id int(20) not null auto_increment comment '员工ID',name varchar(100) not null comment '姓名',salary double not null comment '工资',birthday datetime not null comment '生日',photo varchar(100) not null comment '头像',primary key(id)
)engine=innodb charset=utf8;
新建实体类Employee
package ity;import java.util.Date;/*** @ClassName Employee* @Description TODO* @Author Jiangnan Cui* @Date 2022/6/27 18:11* @Version 1.0*/public class Employee {private Integer id;private String name;private Double salary;private Date birthday;private String photo;public Employee() {}public Employee(Integer id, String name, Double salary, Date birthday, String photo) {this.id = id;this.name = name;this.salary = salary;this.birthday = birthday;this.photo = photo;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Double getSalary() {return salary;}public void setSalary(Double salary) {this.salary = salary;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}public String getPhoto() {return photo;}public void setPhoto(String photo) {this.photo = photo;}@Overridepublic String toString() {return "Employee{" +"id=" + id +", name='" + name + ''' +", salary=" + salary +", birthday=" + birthday +", photo='" + photo + ''' +'}';}}
新建EmployeeDAO
package com.study.dao;import ity.Employee;import java.util.List;/*** @ClassName EmployeeDAO* @Description TODO* @Author Jiangnan Cui* @Date 2022/6/27 18:23* @Version 1.0*/public interface EmployeeDAO {/*** @MethodName lists* @Description 员工列表* @return: java.util.List<ity.Employee>* @Author Jiangnan Cui* @Date 2022/6/27 18:24*/List<Employee> lists();}
新建EmployeeDAOMapper
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapperPUBLIC "-//mybatis//DTD Mapper 3.0//EN"".dtd" ><mapper namespace="com.study.dao.EmployeeDAO"><!--lists--><select id="lists" resultType="Employee">selectid,name,salary,birthday,photofrom employee</select></mapper>
新建EmployeeService
package com.study.service;import ity.Employee;import java.util.List;/*** @ClassName EmployeeService* @Description TODO* @Author Jiangnan Cui* @Date 2022/6/27 18:26* @Version 1.0*/public interface EmployeeService {/*** @MethodName lists* @Description 员工列表* @return: java.util.List<ity.Employee>* @Author Jiangnan Cui* @Date 2022/6/27 18:27*/List<Employee> lists();}
新建EmployeeServiceImpl
package com.study.service;import com.study.dao.EmployeeDAO;import ity.Employee;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import ansaction.annotation.Transactional;import java.util.List;/*** @ClassName EmployeeServiceImpl* @Description TODO* @Author Jiangnan Cui* @Date 2022/6/27 18:27* @Version 1.0*/@Service@Transactionalpublic class EmployeeServiceImpl implements EmployeeService{//业务逻辑层调用数据访问层private EmployeeDAO employeeDAO;@Autowiredpublic EmployeeServiceImpl(EmployeeDAO employeeDAO) {ployeeDAO = employeeDAO;}/*** @MethodName lists* @Description 员工列表* @return: java.util.List<ity.Employee>* @Author Jiangnan Cui* @Date 2022/6/27 18:29*/@Overridepublic List<Employee> lists() {return employeeDAO.lists();}}
完善EmployeeController
package ller;import ity.Employee;import com.study.service.EmployeeService;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import java.util.List;/*** @ClassName EmployeeController* @Description TODO* @Author Jiangnan Cui* @Date 2022/6/27 17:15* @Version 1.0*/@Controller@RequestMapping("employee")public class EmployeeController {//日志对象private static final Logger log = Logger(EmployeeController.class);//控制层调用业务逻辑层private EmployeeService employeeService;@Autowiredpublic EmployeeController(EmployeeService employeeService) {ployeeService = employeeService;}/*** @MethodName list* @Description 员工列表* @param: model* @return: java.lang.String* @Author Jiangnan Cui* @Date 2022/6/27 18:04*/@RequestMapping("lists")public String list(Model model){log.debug("查询所有员工信息");List<Employee> employeeList = employeeService.lists();model.addAttribute("employeeList",employeeList);return "emplist";}}
测试路径:localhost:8888/ems-thymeleaf/employee/lists
完善EmployeDAO
/*** @MethodName addEmp* @Description 保存员工信息* @param: employee* @Author Jiangnan Cui* @Date 2022/6/27 20:11*/void addEmp(Employee employee);
完善EmpDAOMapper
<!--addEmp--><insert id="addEmp" parameterType="Employee" useGeneratedKeys="true" keyProperty="id">insert into employee values(#{id},#{name},#{salary},#{birthday},#{photo})</insert>
完善EmployeeService
/*** @MethodName addEmp* @Description* @param: employee* @Author Jiangnan Cui* @Date 2022/6/27 20:12*/void addEmp(Employee employee);
完善EmpEmployeeServiceImpl
/*** @MethodName addEmp* @Description 添加员工信息* @param: employee* @Author Jiangnan Cui* @Date 2022/6/27 20:13*/@Overridepublic void addEmp(Employee employee) {employeeDAO.addEmp(employee);}
EmployeeController
//定义文件路径@Value("${photo.file.dir}")private String realpath;/*** @MethodName uploadPhoto* @Description 上传头像* @param: img* @param: originalFileName* @return: java.lang.String* @Author Jiangnan Cui* @Date 2022/6/27 20:23*/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 + ansferTo(new File(realpath,newFileName));return newFileName;}/*** @MethodName addEmp* @Description 添加员工信息* @param: employee* @param: img* @return: java.lang.String* @Author Jiangnan Cui* @Date 2022/6/27 20:15*/@RequestMapping("addEmp")public String addEmp(Employee employee, MultipartFile img) throws IOException {log.debug("姓名:{},工资:{},生日:{}",Name(),Salary(),Birthday());//获得图片原始文件名String originalFilename = OriginalFilename();log.debug("头像名称:{}",originalFilename);log.debug("头像大小:{}",Size());log.debug("上传路径:{}",realpath);//1.处理头像的上传String newFileName = uploadPhoto(img, originalFilename);//2.保存员工信息employee.setPhoto(newFileName);//保存头衔名字employeeService.addEmp(employee);return "redirect:/employee/lists";//保存成功跳转到员工列表}
# 公共配置server:port: 8888servlet:context-path: /ems-thymeleaf# Thymeleaf配置spring:thymeleaf:cache: falseprefix: classpath:/templates/suffix: .html# 配置数据源datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: sql.jdbc.Driverurl: jdbc:mysql://localhost:3306/ems-thymeleaf?characterEncoding=UTF-8username: rootpassword: 123456# 暴露哪些资源可以通过项目名直接访问web:resources:static-locations: classpath:/static/,file:${photo.file.dir}# 配置mybatismybatis:mapper-locations: classpath:com/study/mapper/*.xmltype-aliases-package: ity# 配置日志logging:level:root: infocom.study: debug# 指定文件上传位置photo:file:dir: D:Software_DevelopmentIDEA_codeSpringBootems-thymeleafphotos
完善MvcConfig
@Configurationpublic class MvcConfig implements WebMvcConfigurer {@Override//通过在这里面配置,不需要再为每一个访问thymeleaf模板页面单独开发一个controller请求了public void addViewControllers(ViewControllerRegistry registry) {//ViewController: 请求路径,ViewName: 跳转视图registry.addViewController("login").setViewName("login");registry.addViewController("register").setViewName("regist");registry.addViewController("addEmp").setViewName("addEmp");}}
addEmp.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" ".dtd"><html xmlns:th=""><head><title>添加员工信息</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css"href="css/style.css" /></head><body><div id="wrap"><div id="top_content"><div id="header"><div id="rightheader"><p>2009/11/20<br /></p></div><div id="topheader"><h1 id="title"><a href="#">main</a></h1></div><div id="navigation"></div></div><div id="content"><p id="whereami"></p><h1>添加员工信息:</h1><form th:action="@{/employee/addEmp}" method="post" enctype="multipart/form-data"><table cellpadding="0" cellspacing="0" border="0"class="form_table"><tr><td valign="middle" align="right">姓名:</td><td valign="middle" align="left"><input type="text" class="inputgri" name="name" /></td></tr><tr><td valign="middle" align="right">头像:</td><td valign="middle" align="left"><input type="file" width="" name="img" /></td></tr><tr><td valign="middle" align="right">工资:</td><td valign="middle" align="left"><input type="text" class="inputgri" name="salary" /></td></tr><tr><td valign="middle" align="right">生日:</td><td valign="middle" align="left"><input type="text" class="inputgri" name="birthday" /></td></tr></table><p><input type="submit" class="button" value="确认添加" /><input type="submit" class="button" value="返回列表" /></p></form></div></div><div id="footer"><div id="footer_bg">ABC@126</div></div></div></body></html>
访问路径:localhost:8888/ems-thymeleaf/employee/lists,添加员工信息
配套视频:【编程不良人】2021年SpringBoot最新最全教程_哔哩哔哩_bilibili
完善EmployeeController
/*** @MethodName detail* @Description 根据id查询员工详细信息* @param: id* @param: model* @return: java.lang.String* @Author Jiangnan Cui* @Date 7:05 2022/6/29*/@RequestMapping("detail")public String detail(Integer id,Model model){log.debug("当前查询员工id:{}",id);//根据id查询员工详细信息Employee employee = employeeService.findById(id);model.addAttribute("employee",employee);return "updateEmp";//查询到的员工信息显示在更新页面}/*** @MethodName updateEmp* @Description 更新员工信息* @param: employee* @return: java.lang.String* @Author Jiangnan Cui* @Date 7:15 2022/6/29*/@RequestMapping("updateEmp")public String updateEmp(Employee employee,MultipartFile img) throws IOException {//1.判断是否更新头像 为空时说明头像未更新,boolean notEmpty = !img.isEmpty();log.debug("是否更新了头像:{}",notEmpty);//不为空时说明头像更新了:需要删除老的头像,重新上传新的头像if(notEmpty){//1.根据id查询原始头像String oldPhoto = employeeService.Id()).getPhoto();//2.删除老的头像File file = new File(realpath,oldPhoto);ists())file.delete();//3.处理新的头像上传String originalFilename = OriginalFilename();String newFileName = uploadPhoto(img, originalFilename);//4.修改员工新的头像名称employee.setPhoto(newFileName);}//为空时说明头像未更新,只需要更新基本信息即可employeeService.updateEmp(employee);//更新成功后跳转到员工列表页面return "redirect:/employee/lists";}
完善updateEmp.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" ".dtd"><html xmlns:th=""><head><title>更新员工信息</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css"th:href="@{/css/style.css}" /></head><body><div id="wrap"><div id="top_content"><div id="header"><div id="rightheader"><p>2009/11/20<br /></p></div><div id="topheader"><h1 id="title"><a href="#">main</a></h1></div><div id="navigation"></div></div><div id="content"><p id="whereami"></p><h1>更新员工信息:</h1><form th:action="@{/employee/updateEmp}" method="post" enctype="multipart/form-data"><table cellpadding="0" cellspacing="0" border="0"class="form_table"><tr><td valign="middle" align="right">编号:</td><td valign="middle" align="left"><span th:text="${employee.id}"></span><input type="hidden" name="id" th:value="${employee.id}"></td></tr><tr><td valign="middle" align="right">姓名:</td><td valign="middle" align="left"><input type="text" class="inputgri" name="name" th:value="${employee.name}"/></td></tr><tr><td valign="middle" align="right">当前头像:</td><td valign="middle" align="left"><img th:src="@{/}+${employee.photo}" width="60"><input type="hidden" th:value="${employee.photo}" name="photo"></td></tr><tr><td valign="middle" align="right">选择新头像:</td><td valign="middle" align="left"><input type="file" name="img" /></td></tr><tr><td valign="middle" align="right">工资:</td><td valign="middle" align="left"><input type="text" class="inputgri" name="salary" th:value="${employee.salary}"/></td></tr><tr><td valign="middle" align="right">生日:</td><td valign="middle" align="left"><input type="text" class="inputgri" name="birthday" th:value="${#dates.format(employee.birthday,'yyyy/MM/dd')}"/></td></tr></table><p><input type="submit" class="button" value="更新" /><input type="button" class="button" value="返回列表" /></p></form></div></div><div id="footer"><div id="footer_bg">ABC@126</div></div></div></body></html>
完善EmployeeService
/*** @MethodName findById* @Description 根据id查询员工详细信息* @param: id* @return: ity.Employee* @Author Jiangnan Cui* @Date 7:03 2022/6/29*/Employee findById(Integer id);/*** @MethodName updateEmp* @Description 更新员工信息* @param: employee* @Author Jiangnan Cui* @Date 7:44 2022/6/29*/void updateEmp(Employee employee);
完善EmployeeServiceImpl
/*** @MethodName findById* @Description 根据id查询员工信息* @param: id* @return: ity.Employee* @Author Jiangnan Cui* @Date 7:03 2022/6/29*/@Overridepublic Employee findById(Integer id) {return employeeDAO.findById(id);}/*** @MethodName updateEmp* @Description 更新员工信息* @param: employee* @Author Jiangnan Cui* @Date 7:45 2022/6/29*/@Overridepublic void updateEmp(Employee employee) {employeeDAO.updateEmp(employee);}
完善EmployeeDAO
/*** @MethodName findById* @Description 根据id查询员工详细信息* @param: id* @return: ity.Employee* @Author Jiangnan Cui* @Date 7:04 2022/6/29*/Employee findById(Integer id);/*** @MethodName updateEmp* @Description 更新员工信息* @param: employee* @Author Jiangnan Cui* @Date 7:47 2022/6/29*/void updateEmp(Employee employee);
完善EmployeeDAOMapper
<!--findById--><select id="findById" parameterType="Integer" resultType="Employee">selectid,name,salary,birthday,photofrom employeewhere id=#{id}</select><!--updateEmp--><update id="updateEmp" parameterType="Employee">update employeeset name=#{name},salary=#{salary},birthday=#{birthday},photo=#{photo}where id=#{id}</update>
测试路径:localhost:8888/ems-thymeleaf/employee/lists
(1)点击更新,进行员工信息更新
(2)填写要修改的员工信息,修改完成后,点击更新
(3)更新后的员工信息
配套视频:【编程不良人】2021年SpringBoot最新最全教程_哔哩哔哩_bilibili
完善EmpController
/*** @MethodName deleteEmp* @Description 删除员工信息* @param: id* @return: java.lang.String* @Author Jiangnan Cui* @Date 8:43 2022/6/29*/@RequestMapping("deleteEmp")public String deleteEmp(Integer id){log.debug("删除的员工id:{}",id);//1.删除数据String photo = employeeService.findById(id).getPhoto();employeeService.deleteEmp(id);//2.删除头像File file = new File(realpath,photo);ists())file.delete();return "redirect:/employee/lists";//删除成功后跳转到员工列表}
完善emplist.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" ".dtd"><html xmlns:th=""><head><title>emplist</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" th:href="@{/css/style.css}" /></head><body><div id="wrap"><div id="top_content"> <div id="header"><div id="rightheader"><p>2009/11/20 <br /><a th:if="${session.user!=null}" th:href="@{/user/logout}">安全退出</a><a th:if="${session.user==null}" th:href="@{/login}">点我登录</a></p></div><div id="topheader"><h1 id="title"><a href="#">main</a></h1></div><div id="navigation"></div></div><div id="content"><p id="whereami"></p><h1>欢迎 <span th:if="${session.user!=null}" th:text="${session.user.username}"></span><span th:if="${session.user==null}" >游客</span>!</h1><table class="table"><tr class="table_header"><td>编号</td><td>姓名</td><td>头像</td><td>工资</td><td>生日</td><td>操作</td></tr><tr th:each="employee,state:${employeeList}" th:class="${state.odd?'row1':'row2'}"><td><span th:text="${employee.id}"></span></td><td><span th:text="${employee.name}"></span></td><td><img th:src="@{/}+${employee.photo}" width="60"></td><td><span th:text="${employee.salary}"></span></td><td><span th:text="${#dates.format(employee.birthday,'yyyy/MM/dd')}"></span></td><td><a href="javascript:;" th:οnclick="'deleteEmployee('+${employee.id}+')'">删除</a><!-- <a th:href="@{/employee/detail?id=}+${employee.id}+'&name='+${employee.name}">更新</a>--><!-- <a th:href="@{/employee/detail(id=${employee.id},name=${employee.name})}">更新</a>--><a th:href="@{/employee/detail(id=${employee.id})}">更新</a></td></tr><script>function deleteEmployee(id){console.log(id);firm('确定要删除这条记录吗?')){location.href='[[@{/employee/deleteEmp?id=}]]'+id;}}</script></table><p><input type="button" class="button" value="添加" οnclick="addEmp()"/><script>function addEmp(){location.href = '[[@{/addEmp}]]';}</script></p></div></div><div id="footer"><div id="footer_bg">ABC@126</div></div></div></body></html>
完善EmpService
/*** @MethodName deleteEmp* @Description 删除员工信息* @param: id* @Author Jiangnan Cui* @Date 8:48 2022/6/29*/void deleteEmp(Integer id);
完善EmpServiceImpl
/*** @MethodName deleteEmp* @Description 删除员工信息* @param: id* @Author Jiangnan Cui* @Date 8:49 2022/6/29*/@Overridepublic void deleteEmp(Integer id) {employeeDAO.deleteEmp(id);}
完善EmployeeDAO
/*** @MethodName deleteEmp* @Description 删除员工信息* @param: id* @Author Jiangnan Cui* @Date 8:49 2022/6/29*/void deleteEmp(Integer id);
完善EmployeeDAOMapper
<!--deleteEmp--><delete id="deleteEmp" parameterType="Integer">delete from employee where id=#{id}</delete>
测试路径:localhost:8888/ems-thymeleaf/employee/lists,点击删除的同时,员工信息删除且photos中的头像图片也删除。
配套视频:【编程不良人】2021年SpringBoot最新最全教程_哔哩哔哩_bilibili
完善UserController
/*** @MethodName logout* @Description 安全退出* @return: java.lang.String* @Author Jiangnan Cui* @Date 14:08 2022/6/29*/@RequestMapping("logout")public String logout(HttpSession session){session.invalidate();//session失效return "redirect:/login";//跳转到登录页面}
完善emplist.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" ".dtd"><html xmlns:th=""><head><title>emplist</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" th:href="@{/css/style.css}" /></head><body><div id="wrap"><div id="top_content"> <div id="header"><div id="rightheader"><p>2009/11/20 <br /><a th:if="${session.user!=null}" th:href="@{/user/logout}">安全退出</a><a th:if="${session.user==null}" th:href="@{/login}">点我登录</a></p></div><div id="topheader"><h1 id="title"><a href="#">main</a></h1></div><div id="navigation"></div></div><div id="content"><p id="whereami"></p><h1>欢迎 <span th:if="${session.user!=null}" th:text="${session.user.username}"></span><span th:if="${session.user==null}" >游客</span>!</h1><table class="table"><tr class="table_header"><td>编号</td><td>姓名</td><td>头像</td><td>工资</td><td>生日</td><td>操作</td></tr><tr th:each="employee,state:${employeeList}" th:class="${state.odd?'row1':'row2'}"><td><span th:text="${employee.id}"></span></td><td><span th:text="${employee.name}"></span></td><td><img th:src="@{/}+${employee.photo}" width="60"></td><td><span th:text="${employee.salary}"></span></td><td><span th:text="${#dates.format(employee.birthday,'yyyy/MM/dd')}"></span></td><td><a href="javascript:;" th:οnclick="'deleteEmployee('+${employee.id}+')'">删除</a><!-- <a th:href="@{/employee/detail?id=}+${employee.id}+'&name='+${employee.name}">更新</a>--><!-- <a th:href="@{/employee/detail(id=${employee.id},name=${employee.name})}">更新</a>--><a th:href="@{/employee/detail(id=${employee.id})}">更新</a></td></tr><script>function deleteEmployee(id){console.log(id);firm('确定要删除这条记录吗?')){location.href='[[@{/employee/deleteEmp?id=}]]'+id;}}</script></table><p><input type="button" class="button" value="添加" οnclick="addEmp()"/><script>function addEmp(){location.href = '[[@{/addEmp}]]';}</script></p></div></div><div id="footer"><div id="footer_bg">ABC@126</div></div></div></body></html>
测试路径:localhost:8888/ems-thymeleaf/employee/lists
(1)未登录
(2)登录后
(3)安全登出后,需要重新登录
本文发布于:2024-02-08 19:43:35,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170739266768408.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |