流程:

创建项目,勾选基本的几个开发工具还有webstarter

再创建包(service,control,config,dao,pojo)

再前往https://www.webjars.org/,选择bootstrap和jquery的依赖导入

注意:在导入jquery和bootstrap中如何导入我们的对应文件

  1. <script type="text/javascript" src="webjars/jquery/3.6.0/jquery.js"></script>
  2. <script type="text/javascript" src="webjars/bootstrap/5.0.1/js/bootstrap.js"></script>
  3. <link rel="stylesheet" type="text/css" href="webjars/bootstrap/5.0.1/css/bootstrap.min.css">

导入thmeleaf依赖,并配置(不导入这个依赖,在templates文件中加载的html模板是找不到的)

尝试写一个index.html

  1. <body class="text-center">
  2. <form class="form-sigin">
  3. <img class="mb-4 img-thumbnail" src="https://exploit-typora.oss-cn-shenzhen.aliyuncs.com/img/IMG_20210410_100617.png" alt="" width="200" height="200">
  4. <h1 class="h3 mb-3 font-weight-normal">please login in</h1>
  5. <label for="user-name" class="sr-only">username</label>
  6. <!--注意:一定要用label标签把input标签包含起来,不然就导致input标签不居中-->
  7. <label>
  8. <input id="user-name" type="text" name="username" class="form-control" required="" autofocus="">
  9. </label>
  10. <label for="password" class="sr-only">password</label>
  11. <label>
  12. <input id="password" type="password" name="password" class="form-control" required="" autofocus="">
  13. </label>
  14. <br>
  15. <div class="check-box mb-3">
  16. <label>
  17. <input type="checkbox" value="remember-me">remember
  18. </label>
  19. </div>
  20. <button type="submit" class="btn btn-lg btn-primary btn-block">login</button>
  21. <p class="mt-5 mb-3 text-muted"> 2020-2034</p>
  22. <p class="btn btn-sm">中文</p>
  23. <a class="btn btn-sm">English</a>
  24. </form>
  25. </body>

写一个配置类,把“/”和"/index"和"/index.html"都对应到index主页

  1. @Configuration
  2. public class ViewResolver implements WebMvcConfigurer {
  3. @Override
  4. public void addViewControllers(ViewControllerRegistry registry) {
  5. registry.addViewController("/").setViewName("index");
  6. registry.addViewController("/index").setViewName("index");
  7. registry.addViewController("/index.html").setViewName("index");
  8. }
  9. }

添加thmeleaf命名空间,和form的提交url

  1. <html lang="en" xmlns:th=http://www.thymeleaf.org
  2. xmlns:sec=http://www.thymeleaf.org/extras/spring-security
  3. xmlns:shiro=http://www.pollix.at/thymeleaf/shiro >
  4. <!--注意:url在thmeleaf中需要用@开头-->
  5. <form class="form-sigin" th:action="@{/test}" method="post">

测试编写对应的登录控制器

  1. @PostMapping("/test")
  2. @ResponseBody
  3. public String test(@RequestParam("username")String username,
  4. @RequestParam("password")String password){
  5. System.out.println(username+password);
  6. return "OK!!";
  7. }

添加功能:判断用户密码是否正确

  • 控制器:
  1. @PostMapping("login")
  2. public String login(@RequestParam("username")String username,
  3. @RequestParam("password")String password,
  4. Model model,
  5. HttpSession session){
  6. //判断用户密码是否正确,成功了,登录状态码为200且在session中会有用户名,否则登录状态码为200
  7. if (username.equals("admin") && password.equals("123456")){
  8. session.setAttribute("loginStatus",200);
  9. session.setAttribute("username",username);
  10. //成功了直接重定向到list去获取用户数据
  11. return "redirect:list";
  12. }else{
  13. session.setAttribute("loginStatus",400);
  14. //失败了加上session状态码,然后继续返回到index页面
  15. return "index";
  16. }
  17. }
  18. @GetMapping("list")
  19. public String list(){
  20. return "list";
  21. }
  • 模板:
  1. <!--只有当if里面的条件成立了才会显示这段语句-->
  2. <div th:if="${session.loginStatus==400}">
  3. <div class="alert alert-danger" role="alert">用户名或密码错误!!!</div>
  4. </div>

添加功能:当没有登录的时候进入其他页面会自动跳转到登录页面

这是一个拦截器功能,需要创建一个HandleInterceptor类,还有一个配置类

  • HandleInterceptor类
  1. //注意这个配置类必须要放置到IOC容器中去
  2. @Component
  3. public class LoginHandleInterceptor implements HandlerInterceptor {
  4. //把三个方法全部重写,主要是第一个方法,后面的方法可删去
  5. @Override
  6. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  7. Object loginStatus = request.getSession().getAttribute("loginStatus");
  8. if (loginStatus==null){
  9. //未登录状态
  10. response.sendRedirect("/");
  11. return false;
  12. }else{
  13. if ((Integer) loginStatus == 400){
  14. //登录失败状态
  15. response.sendRedirect("/");
  16. return false;
  17. }else{
  18. //登录成功
  19. return true;
  20. }
  21. }
  22. }
  23. @Override
  24. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  25. }
  26. @Override
  27. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  28. }
  29. }
  • 配置类
  1. @Configuration
  2. public class MyConfig implements WebMvcConfigurer {
  3. //视图控制
  4. @Override
  5. public void addViewControllers(ViewControllerRegistry registry) {
  6. registry.addViewController("/").setViewName("index");
  7. registry.addViewController("/index").setViewName("index");
  8. registry.addViewController("/index.html").setViewName("index");
  9. }
  10. @Override
  11. public void addInterceptors(InterceptorRegistry registry) {
  12. registry.addInterceptor(new LoginHandleInterceptor())
  13. .addPathPatterns("/**")
  14. .excludePathPatterns("/","/index","/index.html","/login");
  15. }
  16. }

首页到此为止

下面开始处理list员工列表

先把对应的url想好

  • list-input:(GET) /input (不带参数)

  • input-list: (POST) /saveEmployee(带了name,gender,email,departmentId参数)

  • list-delete: (GET)/delete (带一个对应的employee的id的参数)

  • list-update:(GET) /update(带一个对应的employee的id的参数)

  • update-list:(POST) /updateEmployee(带了email和departmentId的参数)

然后就是直接实现即可

注意:

关键是更新怎么实现:

list界面到input界面-带入对应的员工id的参数,在控制器处加入updateStatus状态码和对应的这个employee的对象,到了input界面则根据updateStatus状态码判断进入update部分用对应的这个employee对象进行手动回显,并且将name和gender设为disabled(隐藏提交id,name,gender),然后在控制器处new一个新对象,把这个新对象用save方法加入到employeeDao中去

get方法怎么携带参数?

两种方式:

  • /employee/1001

    1. <a th:href="@{/employee/{id}(id=1001)}"></a>
    2. 或者
    3. <a th:href="@{/employee/{id}(id=${employee.id})}"></a>
  • /employee?id=1001

    1. <a th:href="@{/employee(id=1001)}"></a>
    2. 或者
    3. <a th:href="@{/employee(id=${employee.id})}"></a>

怎么让表单不能被使用但又可以提交?

两种方式:

  • readonly:只读模式

    在最后面加上readonly属性即可,但是只有input才有效,seletor没用

    1. <input class="form-control" type="text" placeholder="Readonly input here…" readonly>
  • disabled:禁用模式

    在最后面加上disabled属性即可,但是会把要提交的信息也给禁用了,需要另外隐藏提交相关信息

    1. <input class="form-control" id="disabledInput" type="text" placeholder="Disabled input here..." disabled>

展示最终thmeleaf页面为:

  • list界面
  1. <body class="text-center">
  2. <div class="contaniner">
  3. <div class="row">
  4. <div class="col-md-4">
  5. <h4>【[[${session.username}]]】 sir</h4>
  6. </div>
  7. </div>
  8. <div class="row">
  9. <div class="col-md-4">
  10. <a th:href="@{/input}"><button class="bnt btn-primary">Add Employee</button></a>
  11. </div>
  12. </div>
  13. <div class="row">
  14. <div class="col-md-offset-2 col-md-10">
  15. <table class="table table-hover">
  16. <thead>
  17. <tr>
  18. <th>#</th>
  19. <th>name</th>
  20. <th>gender</th>
  21. <th>email</th>
  22. <th>departmentId</th>
  23. <th>departmentName</th>
  24. <th>handle</th>
  25. </tr>
  26. </thead>
  27. <tbody>
  28. <tr th:each="employee:${employees}">
  29. <th th:text="${employee.getId()}"></th>
  30. <th th:text="${employee.getLastName()}"></th>
  31. <div th:if="${employee.getGender()==1}">
  32. <th></th>
  33. </div>
  34. <div th:if="${employee.getGender()==0}">
  35. <th></th>
  36. </div>
  37. <th th:text="${employee.getEmail()}"></th>
  38. <th th:text="${employee.getDepartment().getDepartmentId()}"></th>
  39. <th th:text="${employee.getDepartment().getDepartmentName()}"></th>
  40. <th>
  41. <a th:href="@{/update(id=${employee.getId()})}"><button class="btn btn-danger">alter</button></a>
  42. <!--这个携带参数是用?携带参数,还有一种是比如:/employee/1001携带参数-->
  43. <!---->
  44. <a th:href="@{/delete(id=${employee.getId()})}"><button class="btn btn-primary">delete</button></a>
  45. </th>
  46. </tr>
  47. </tbody>
  48. </table>
  49. </div>
  50. </div>
  51. </div>
  52. </body>
  • input界面
  1. <body>
  2. <div class="container">
  3. <!--添加员工界面-->
  4. <div th:if="${updateStatus==null}">
  5. <form class="form-horizontal" th:action="@{/saveEmployee}" method="post">
  6. <h3>添加员工</h3>
  7. <!--name-->
  8. <div class="form-group">
  9. <label for="name" class="col-sm-4 control-label"><strong>Name</strong></label>
  10. <div class="col-sm-4">
  11. <input type="text" name="name" class="form-control" id="name" placeholder="name">
  12. </div>
  13. </div>
  14. <!--gender-->
  15. <div class="form-group">
  16. <label class="col-sm-4 "><strong>Gender</strong></label>
  17. <div class="col-sm-4">
  18. <select name="gender" class="form-control">
  19. <option value="1"></option>
  20. <option value="0"></option>
  21. </select>
  22. </div>
  23. </div>
  24. <!--email-->
  25. <div class="form-group">
  26. <label for="email" class="col-sm-4 control-label"><strong>Email</strong></label>
  27. <div class="col-sm-4">
  28. <input type="email" name="email" class="form-control" id="email" placeholder="email">
  29. </div>
  30. </div>
  31. <!--department-->
  32. `<div class="form-group">
  33. <label class="col-sm-4 control-label"><strong>Department</strong></label>
  34. <div class="col-sm-4">
  35. <select class="form-control" name="departmentId">
  36. <div th:each="department:${departments}">
  37. <option th:text="${department.getDepartmentId()}"></option>
  38. </div>
  39. </select>
  40. </div>
  41. </div>
  42. <div class="form-group">
  43. <div class="col-sm-offset-2 col-sm-10">
  44. <button type="submit" class="btn btn-success btn-sm">CONFIRM ADD</button>
  45. </div>
  46. </div>
  47. </form>
  48. </div>
  49. <!--修改员工界面-->
  50. <div th:if="${updateStatus=='update'}">
  51. <form class="form-horizontal" th:action="@{/updateEmployee}" method="post">
  52. <h3>修改员工</h3>
  53. <input type="hidden" th:value="${updateEmployee.getId()}" name="employeeId">
  54. <input type="hidden" th:value="${updateEmployee.getLastName()}" name="name">
  55. <input type="hidden" th:value="${updateEmployee.getGender()}" name="gender">
  56. <!--name-->
  57. <div class="form-group" readonly>
  58. <label for="updateName" class="col-sm-4 control-label"><strong>Name</strong></label>
  59. <div class="col-sm-4">
  60. <input th:value="${updateEmployee.getLastName()}" type="text" name="name" class="form-control" id="updateName" placeholder="name" disabled>
  61. </div>
  62. </div>
  63. <!--gender-->
  64. <div class="form-group">
  65. <label class="col-sm-4 "><strong>Gender</strong></label>
  66. <div class="col-sm-4">
  67. <div th:if="${updateEmployee.getGender()==1}">
  68. <select th:value="${updateEmployee.getGender()}" name="gender" class="form-control" disabled>
  69. <option value="1"></option>
  70. <option value="0"></option>
  71. </select>
  72. </div>
  73. <div th:if="${updateEmployee.getGender()==0}">
  74. <select id="disableInput" th:value="${updateEmployee.getGender()}" name="gender" class="form-control" disabled>
  75. <option value="0"></option>
  76. <option value="1"></option>
  77. </select>
  78. </div>
  79. </div>
  80. </div>
  81. <!--email-->
  82. <div class="form-group">
  83. <label for="updateEmail" class="col-sm-4 control-label"><strong>Email</strong></label>
  84. <div class="col-sm-4">
  85. <input th:value="${updateEmployee.getEmail()}" type="email" name="email" class="form-control" id="updateEmail" placeholder="email">
  86. </div>
  87. </div>
  88. <!--department-->
  89. <div class="form-group">
  90. <label class="col-sm-4 control-label"><strong>Department<span style="color: #c0392b;font-weight: 700">(NOW:[[${updateEmployee.getDepartment().getDepartmentId()+"."+updateEmployee.getDepartment().getDepartmentName()}]])</span></strong></label>
  91. <div class="col-sm-4">
  92. <select class="form-control" name="departmentId">
  93. <div th:each="department:${departments}">
  94. <option th:text="${department.getDepartmentId()}"></option>
  95. </div>
  96. </select>
  97. </div>
  98. </div>
  99. <div class="form-group">
  100. <div class="col-sm-offset-2 col-sm-10">
  101. <button type="submit" class="btn btn-success btn-sm">CONFIRM UPDATE</button>
  102. </div>
  103. </div>
  104. </form>
  105. </div>
  106. </div>
  107. </body>

springboot-4-CRUD开发实战的更多相关文章

  1. 小D课堂【SpringBoot】接口Http协议开发实战

    ---恢复内容开始--- ====================2.SpringBoot接口Http协议开发实战 ============================= 1.SpringBoot ...

  2. SpringBoot微服务电商项目开发实战 --- Redis缓存雪崩、缓存穿透、缓存击穿防范

    最近已经推出了好几篇SpringBoot+Dubbo+Redis+Kafka实现电商的文章,今天再次回到分布式微服务项目中来,在开始写今天的系列五文章之前,我先回顾下前面的内容. 系列(一):主要说了 ...

  3. SpringBoot微服务电商项目开发实战 --- api接口安全算法、AOP切面及防SQL注入实现

    上一篇主要讲了整个项目的子模块及第三方依赖的版本号统一管理维护,数据库对接及缓存(Redis)接入,今天我来说说过滤器配置及拦截设置.接口安全处理.AOP切面实现等.作为电商项目,不仅要求考虑高并发带 ...

  4. SpringBoot微服务电商项目开发实战 --- 模块版本号统一管理及Redis集成实现

    上一篇文章总结了基于SpringBoot实现分布式微服务下的统一配置.分环境部署配置.以及服务端模块的分离(每一个提供者就是一个独立的微服务).微服务落地.Dubbo整合及提供者.消费者的配置实现.本 ...

  5. 图书-技术-SpringBoot:《Spring Boot 企业级应用开发实战》

    ylbtech-图书-技术-SpringBoot:<Spring Boot 企业级应用开发实战> Spring Boot 企业级应用开发实战,全书围绕如何整合以 Spring Boot 为 ...

  6. 小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_5-10.Springboot2.x用户登录拦截器开发实战

    笔记 10.Springboot2.x用户登录拦截器开发实战     简介:实战开发用户登录拦截器拦截器 LoginInterceptor                  1.实现接口 LoginI ...

  7. SpringBoot:Web开发

    西部开源-秦疆老师:基于SpringBoot 2.1.6 的博客教程 , 基于atguigu 1.5.x 视频优化 秦老师交流Q群号: 664386224 未授权禁止转载!编辑不易 , 转发请注明出处 ...

  8. [原创].NET 分布式架构开发实战之四 构建从理想和实现之间的桥梁(前篇)

    原文:[原创].NET 分布式架构开发实战之四 构建从理想和实现之间的桥梁(前篇) .NET 分布式架构开发实战之四 构建从理想和实现之间的桥梁(前篇) 前言:上一篇文章讲述了一些实现DAL的理论,本 ...

  9. 《精通Spring 4.X企业应用开发实战》读书笔记1-1(IoC容器和Bean)

    很长一段时间关注在Java Web开发的方向上,提及到Jave Web开发就绕不开Spring全家桶系列,使用面向百度,谷歌的编程方法能够完成大部分的工作.但是这种不系统的了解总觉得自己的知识有所欠缺 ...

  10. 11. SpringBoot 之CRUD实例

    SpringBoot静态页路径,可直接通过URL访问的: /META-INF/resources /resources /static /public 而    5. /template 只和模板引擎 ...

随机推荐

  1. 从C到C++过渡的3个原因

    从C到C++过渡的3个原因 3 reasons to transition from C to C++ 几十年来,嵌入式软件工程师们一直在争论他们是否应该使用C或C++.根据2019年嵌入式市场调查, ...

  2. mybatis学习——properties属性实现引用配置文件

    Mybatis核心配置文件中有很多的配置项,配置文档的顶层结构如下: *注意:配置项的顺序不能颠倒,如果颠倒了它们的顺序,在MyBatis的自启动阶段会发生异常,导致程序无法运行. propertie ...

  3. LongAdder源码阅读笔记

    功能描述 LongAdder通过创建多个副本对象,解决了多线程使用CAS更新同一个对象造成的CPU阻塞,加快了对线程处理的速度.当多个线程同一时刻更新一个AtomicLong类型的变量时,只有一个线程 ...

  4. Netty 框架学习 —— ChannelHandler 与 ChannelPipeline

    ChannelHandler 1. Channel 生命周期 Channel 的生命周期状态如下: 状态 描述 ChannelUnregistered Channel 已经被创建,但还未注册到 Eve ...

  5. 谷歌chrome浏览器network中Stalled分析和优化

    谷歌chrome浏览器network中Stalled分析和优化 问题由来 最近项目上要求首页的加载速度,查看浏览器的network发现接口加载速度非常慢. 问题解决思路 SSL 网上有人因为图片加载, ...

  6. windows 7系统安装与配置Tomcat服务器环境

    windows 7系统安装与配置Tomcat服务器环境 学习了一个月的java基础,终于要迈向java web领域.学习java web开发就离不开服务器的支持,由于本人是菜鸟,只好求助度娘谷哥.在此 ...

  7. NOIP模拟测试29「爬山·学数数·七十和十七」

    爬山题解不想写了 学数数 离散化然后找到以每一个值为最大值的连续子段有多少个,然后开个桶维护 那么怎么找以每一个值为最大值的连续子段个数 方法1(我的极笨的方法) 考试时我的丑陋思路, 定义极左值为左 ...

  8. ESCMScript(1)let和const

    1.let命令 基本语法 ES6 新增了let命令,用来声明变量.它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效. { let a = 1 var b = 2 console ...

  9. Java行为参数化的演进

    首先感谢<java8实战>一书作者某某某. 需求场景: 为一位果农设计一款软件,可以根据果农的需求筛选出相应的水果. 例如: 根据颜色筛选 根据重量筛选 根据颜色和重量筛选 准备工作 定义 ...

  10. 一篇技术博文引发的stylelint项目实践

    背景 看到项目中团队成员写CSS样式风格迥异,CSS样式的书写顺序没有鲜明的规范.想到以前看过CSS样式书写顺序的文章,决定找出来,给团队成员科普一下.查阅了好几篇文章,觉得这篇文章给出的理由最硬核, ...