springboot学习03(从搭建到熟悉)

【SpringBoot】 什么是springboot(一)?如何搭建springboot项目? Spring框架是Java平台上的一种开源应用框架,提供具有控制反转特性的容器。尽管Spring框架自身对编程模型没有限制,但其在Java应用中的频繁使用让它备受青睐,以至于后来让它作为EJB(EnterpriseJavaBeans)模型的补充,甚至是替补。Spring框架为开发提供了一系列的解决方案,比如利用控制反转的核心特性,并通过依赖注入实现控制反转来实现管理对象生命周期容器化,利用面向切面编程进行声明式的事务管理,整合多种持久化技术管理数据访问,提供大量优秀的Web框架方便开发等等。Spring框架 阅读详情

注意springboot中的改变

  1. 首页配置:注意点,所有页面的静态资源都需要使用thymeleaf接管;@{}
  2. 页面国际化:
    • 我们需要配置i18n文件
    • 我们如果需要在项目中进行按钮切换,我们需要自定义一个组件LocalResolver
    • 记得将自己写的组件配置到spring容器 @bean
    • #{} 去除自定义的message

thymeleaf魔板引擎

首先静态资源在项目中的存储位置
在这里插入图片描述
在网页文件中,首先的引入thymeleaf的声明:

<html lang="en" xmlns:th=http://www.thymeleaf.org>

之后利用thymeleaf的语法对模板中的部分组件进行改写,并对应好静态资源路径,使用适合其语法。
在这里插入图片描述
thymeleaf语法总结:链接: thymeleaf语法总结.
如果遇到thymeleaf不起作用,可以试着清理浏览器缓存,也可以在application.properties中,定义关闭thymeleaf缓存并重启服务

#关闭魔板引擎缓存
spring.thymeleaf.cache=false
# 访问的资源路径前进行自动的拼接
server.servlet.context-path=/chaoxi  

国际化

即根据需求,我们可以对网页中的语言进行切换。
在这里插入图片描述
首先,我们得对页面中得中文部分和英文部分,分别设置对应得properties,

在这里插入图片描述

针对需要更改得语言部分,进行对应得翻译。可以随意起名字。
根据springboot底层代码,有一个Localresolver的区域解析器,那么我们可以在自己的config文件中,继承他,并重写她的方法。

import org.springframework.web.servlet.LocaleResolver;
import org.thymeleaf.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;

/**
 * 
 * @create 2022-04-06 18:15
 */
//自定义自己的语言请求解析
public class MyLocaleResolver implements LocaleResolver {

    //解析请求
    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        String language = request.getParameter("l");

        Locale locale = Locale.getDefault(); //如果没有就使用默认的
        //如果请求的链接带了国际化参数
        if (!StringUtils.isEmpty(language)){
            //zh_CN
            String[] split = language.split("_");
            //国家,地区
            locale=new Locale(split[0],split[1]);
        }
        return locale;
    }

    @Override
    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {

    }
}

记住,我们自定义好解析器后,一定要将其注册并托管到springboot

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {

    //自定义的视图转发器
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("index");
        registry.addViewController("/index.html").setViewName("index");
    }

    //自定义国际化语言解析器
    @Bean  //******
    public LocaleResolver localeResolver(){
        return new MyLocaleResolver();
    }
}

网页中,需要带有语言选项的请求参数。通过后端解析,来随时切换语言。当然,我们还需要在application.properties中配置国际化配置,
在这里插入图片描述
在这里插入图片描述

登录功能的实现+拦截器

前端传递用户名和密码的时候需要用name标签进行传递

<input type="email" id="inputEmail" name="username" class="form-control" th:placeholder="#{login.username}" required="" autofocus="">

      <input type="password" id="inputPassword" name="password" class="form-control" th:placeholder="#{login.password}" required="">

首先定义登录的路由(Controller),针对业务对传递的用户名和密码进行判断。当然这里的路由需要和网页中设置的action必须一致:

<form class="form-signin" th:action="@{/user/login}">

设置,登录后反馈的消息,展示在前端,注意thymeleaf的语法

<p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>

import org.springframework.boot.autoconfigure.cassandra.CassandraProperties;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.thymeleaf.util.StringUtils;

import javax.servlet.http.HttpSession;

/**
 * @author chaoxi
 * @create 2022-04-06 20:13
 */
@Controller
public class loginController {

    @RequestMapping("/user/login")
    //@ResponseBody //这个注解的意思是将返回的字符串视为字符串,不在视为视图
    public String login(@RequestParam("username") String username, @RequestParam("password") String password, Model model, HttpSession session){


        //之后就是验证的业务
        //System.out.println(username);
        if(!StringUtils.isEmpty(username) && "123456".equals(password)){
            session.setAttribute("loginUser",username); //登录成功后,携带session信息去验证拦截器
            return "redirect:/main.html"; //登录成功后,重定向
        }else {
            model.addAttribute("msg","用户名或者密码错误");
            return "index";
        }

    }
}

为了避免在浏览器的url中暴露用户的用户名和密码,我们需要设置视图映射:

 registry.addViewController("/main.html").setViewName("dashboard"); //地址映射,这样才可以避免url显示用户名和密码

拦截器设置(我们的业务需求是必须要用户登录才能访问我们的内部系统,那么再未登录前需要对请求进行检测)
自定义拦截器,需要继承HandlerInterceptor类,并重写三个方法。但是由于我们只需要在登陆前检测,所以只需要重写第一个方法。利用登陆后,用户的session进行判断

import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author chaoxi
 * @create 2022-04-06 20:57
 */
public class LoginHandlerIntercepter implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //登录成功后,应该有用户的session
        Object loginUser = request.getSession().getAttribute("loginUser");

        if (loginUser==null){
            request.setAttribute("msg","没有权限,请先登录"); //设置一个消息返回给前端
            request.getRequestDispatcher("/index.html").forward(request,response); //将request重新定向到index.html,并携带请求
            return false;
        }else {
            return true;
        }

    }


      //这两个可以不用实现,因为我们要做的是在登录前的验证
//    @Override
//    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
//
//    }
//
//    @Override
//    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//
//    }
}

重写完自定义的拦截器后,我们需要将其注册到WebMvcConfigurer中令其生效。静态资源其实也是通过request请求得到的,需要对其放行。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;



/**
 * @author chaoxi
 * @create 2022-04-05 16:25
 */
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {

    //自定义的视图转发器
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("index");
        registry.addViewController("/index.html").setViewName("index");
        registry.addViewController("/main.html").setViewName("dashboard"); //地址映射,这样才可以避免url显示用户名和密码
    }

    //自定义国际化语言解析器
    @Bean
    public LocaleResolver localeResolver(){
        return new MyLocaleResolver();
    }


    //addPathPatterns匹配拦截的请求,excludePathPatterns排除一些请求
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginHandlerIntercepter()).
                addPathPatterns("/**").excludePathPatterns("/index.html","/","/user/login","/css/*","/img/**","/js/**");
    }
}

跳转页面后,显示用户名。
我们会对登录的用户利用session进行存储用户的信息,那么前端也可以通过调用session,进行数据回显。

<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="https://getbootstrap.com/docs/4.0/examples/dashboard/#dashboard.html">[[${session.loginUser}]]</a>

这样,登录后,跳转的页面中如果有需要显示用户名的地方,就可以直接显示出来。

员工页面展示

  1. 即我们需要从后台将数据查询出来,展示到对应的网页上面。
    在这里插入图片描述
    一个网页项目,必然存在着大量的重复的组件,我们可以将这些组件提取出来,单独放在一个文件中,让其余模板文件,直接引用,便可以大幅度减少代码量,也方便维护。比如上述页面,顶部和侧边栏都可以提取出来进行复用。这也是thymeleaf的功能。
<!DOCTYPE html>
<html lang="en" xmlns:th=http://www.thymeleaf.org>


<!--头部导航栏-->

<!--顶部导航栏-->
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="topbar">
    <a class="navbar-brand col-sm-3 col-md-2 mr-0" href="https://getbootstrap.com/docs/4.0/examples/dashboard/#dashboard.html">[[${session.loginUser}]]</a>
    <input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search">
    <ul class="navbar-nav px-3">
        <li class="nav-item text-nowrap">
            <a class="nav-link" th:href="@{/user/logout}">注销</a>
        </li>
    </ul>
</nav>



<!--侧边栏-->
<nav class="col-md-2 d-none d-md-block bg-light sidebar" th:fragment="siderbar"> <!--将重复的侧边栏,定义标签。重复页面引用即可-->
    <div class="sidebar-sticky">
        <ul class="nav flex-column">
            <li class="nav-item">
                <!--thymeleaf可以利用这种三元运算符进行选择性激活属性-->
                <a th:class="${active=='main.html'?'nav-link active':'nav-link'}" th:href="@{/index.html}">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-home"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>
                    首页 <span class="sr-only">(current)</span>
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="https://getbootstrap.com/docs/4.0/examples/dashboard/#dashboard.html">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline></svg>
                    Orders
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="https://getbootstrap.com/docs/4.0/examples/dashboard/#dashboard.html">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-shopping-cart"><circle cx="9" cy="21" r="1"></circle><circle cx="20" cy="21" r="1"></circle><path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path></svg>
                    Products
                </a>
            </li>
            <li class="nav-item">
                <a th:class="${active=='list.html'?'nav-link active':'nav-link'}" th:href="@{/emps}"> <!--定义员工管理页面的controller-->
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-users"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="9" cy="7" r="4"></circle><path d="M23 21v-2a4 4 0 0 0-3-3.87"></path><path d="M16 3.13a4 4 0 0 1 0 7.75"></path></svg>
                    员工管理
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="https://getbootstrap.com/docs/4.0/examples/dashboard/#dashboard.html">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-bar-chart-2"><line x1="18" y1="20" x2="18" y2="10"></line><line x1="12" y1="20" x2="12" y2="4"></line><line x1="6" y1="20" x2="6" y2="14"></line></svg>
                    Reports
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="https://getbootstrap.com/docs/4.0/examples/dashboard/#dashboard.html">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-layers"><polygon points="12 2 2 7 12 12 22 7 12 2"></polygon><polyline points="2 17 12 22 22 17"></polyline><polyline points="2 12 12 17 22 12"></polyline></svg>
                    Integrations
                </a>
            </li>
        </ul>

        <h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
            <span>Saved reports</span>
            <a class="d-flex align-items-center text-muted" href="https://getbootstrap.com/docs/4.0/examples/dashboard/#dashboard.html">
                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-plus-circle"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="16"></line><line x1="8" y1="12" x2="16" y2="12"></line></svg>
            </a>
        </h6>
        <ul class="nav flex-column mb-2">
            <li class="nav-item">
                <a class="nav-link" href="https://getbootstrap.com/docs/4.0/examples/dashboard/#dashboard.html">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline></svg>
                    Current month
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="https://getbootstrap.com/docs/4.0/examples/dashboard/#dashboard.html">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline></svg>
                    Last quarter
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="https://getbootstrap.com/docs/4.0/examples/dashboard/#dashboard.html">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline></svg>
                    Social engagement
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="https://getbootstrap.com/docs/4.0/examples/dashboard/#dashboard.html">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline></svg>
                    Year-end sale
                </a>
            </li>
        </ul>
    </div>
</nav>

</html>

通过,thymeleaf语法进行组件标记:th:fragment=“topbar”。并在一个commons中存储:
在这里插入图片描述
之后定义Controller来访问后台数据:(我今天才明白,当model封装数据的并命名,然后转发到对应的网页,网页中中只要这个msg对应了后台中model取得名字,就可以取数据了。以对象的方式取数据。)取数据的方式,参照thymeleaf的语法。

@RequestMapping("/emps")
    public String listEmplyees(Model model){

        Collection<Employee> employees = employeeDao.getAll();
        model.addAttribute("emps",employees);
        return "emp/list";

    }
        <main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4"><div class="chartjs-size-monitor" style="position: absolute; inset: 0px; overflow: hidden; pointer-events: none; visibility: hidden; z-index: -1;"><div class="chartjs-size-monitor-expand" style="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;"><div style="position:absolute;width:1000000px;height:1000000px;left:0;top:0"></div></div><div class="chartjs-size-monitor-shrink" style="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;"><div style="position:absolute;width:200%;height:200%;left:0; top:0"></div></div></div>
            <!--增加添加员工的按钮-->
            <h2><a class="btn btn-sm btn-success" th:href="@{/emp}">添加员工</a></h2>
          <div class="table-responsive">
            <table class="table table-striped table-sm">
              <thead>
                <tr>
                  <th>id</th>
                  <th>lastName</th>
                  <th>email</th>
                  <th>gender</th>
                  <th>department</th>
                  <th>birth</th>
                  <th>操作</th>
                </tr>
              </thead>
              <tbody>
                 <tr th:each="emp:${emps}">
                     <td th:text="${emp.getId()}"></td>
                     <td>[[${emp.getLastName()}]]</td>
                   <td th:text="${emp.getEmail()}"></td>
                   <td th:text="${emp.getGender()==0?'女':'男'}"></td>
                   <td th:text="${emp.getDepartment().getDepartmentName()}"></td>
                   <td th:text="${#dates.format(emp.getBirth(),'yyyy-MM-dd HH:mm:ss')}"></td>
                   <td>
                       <!--对编辑功能进行完善 ${emp.getId()拼接在链接后的参数-->
                     <a class="btn btn-sm btn-primary" th:href="@{/emp/}+${emp.getId()}">编辑</a>
                     <a class="btn btn-sm btn-danger" th:href="@{/delete/}+${emp.getId()}">删除</a>
                   </td>
                 </tr>
              </tbody>
            </table>
          </div>
        </main>

员工管理系统的CRUD

开发,现在网页组件中,定义好路由,之后编写Controller。员工系统,对员工的增加和修改都需要跳转到对应的页面才能进行。

增加员工页面

首先,我们会在总的展示页面组件中,定义一个可以跳转到添加页面的路由

 <h2><a class="btn btn-sm btn-success" th:href="@{/emp}">添加员工</a></h2>

编写对应的Controller:

//前端点击,get请求到添加员工页面
    @GetMapping("/emp")
    public String toAddpage(Model model){
        Collection<Department> department = departmentDao.getDepartment();
        model.addAttribute("departments",department);
        return "emp/add";
    }

跳转到add界面:

<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4"><div class="chartjs-size-monitor" style="position: absolute; inset: 0px; overflow: hidden; pointer-events: none; visibility: hidden; z-index: -1;"><div class="chartjs-size-monitor-expand" style="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;"><div style="position:absolute;width:1000000px;height:1000000px;left:0;top:0"></div></div><div class="chartjs-size-monitor-shrink" style="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;"><div style="position:absolute;width:200%;height:200%;left:0; top:0"></div></div></div>
            <!--添加员工的表单-->
            <form th:action="@{/emp}" method="post">
                <div class="form-group">
                    <label>LastName</label>
                    <input type="text" name="lastName" class="form-control" placeholder="chaoxi">
                </div>
                <div class="form-group">
                    <label>Email</label>
                    <input type="email" name="email" class="form-control" placeholder="admin@qq.com">
                </div>
                <div class="form-group">
                    <label>Gender</label>
                    <div class="form-check form-check-inline">
                        <input class="form-check-input" type="radio" name="gender" value="1">
                        <label class="form-check-label">男</label>
                    </div>
                    <div class="form-check form-check-inline">
                        <input class="form-check-input" type="radio" name="gender" value="0">
                        <label class="form-check-label">女</label>
                    </div>
                    <div class="form-group">
                        <label>department</label>
                        <select class="form-control" name="department.id">
                            <!--这里需要从后台查询已存在的部门放到这里来进行显示-->
                            <!--注意,我们再Controller接收的是一个employee,所以我们需要提交的是其中的一个属性-->
                            <option th:each="dept:${departments}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"></option>

                        </select>
                    </div>
                    <div class="form-group">
                        <label>Birth</label>
                        <input type="text" name="birth" class="form-control" placeholder="chaoxi">
                    </div>
                    <button type="submit" class="btn btn-primary">添加</button>
                </div>
            </form>
        </main>

通过页面中的组件,取出数据展示。
在这里插入图片描述
点击添加后。form以post请求去传递数据,保存给后台。并重定向到list的主页面。

//填写完信息后,提交到后台并定向到list页面
    @PostMapping("/emp")
    public String addEmp(Employee employee){
        //前端穿过来的对象
        employeeDao.add(employee);
        return "redirect:/emps";
    }

修改员工信息

在list的页面中,点击编辑,跳转到update页面

<a class="btn btn-sm btn-primary" th:href="@{/emp/}+${emp.getId()}">编辑</a>

由于编辑某个员工的信息,跳转页面后应该直接加载那个员工的信息,所以需要取出她的id一起传递。由于bug原因,“+”连接符,可能会爆红,但是不影响运行。
定义路由:

//去员工的修改页面,链接形式都是getmapping
    @GetMapping("/emp/{id}")
    public String toUpdatePage(@PathVariable("id")int id,Model model){
        //点击编辑按钮,需要将对应的员工信息加载到修改页面.通过前端穿过来的参数取id
        Employee employee = employeeDao.getEmployeeById(id);
        //让更新页面去取值
        model.addAttribute("emp",employee);

        Collection<Department> department = departmentDao.getDepartment();
        model.addAttribute("departments",department);
        return "/emp/update";
    }
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4"><div class="chartjs-size-monitor" style="position: absolute; inset: 0px; overflow: hidden; pointer-events: none; visibility: hidden; z-index: -1;"><div class="chartjs-size-monitor-expand" style="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;"><div style="position:absolute;width:1000000px;height:1000000px;left:0;top:0"></div></div><div class="chartjs-size-monitor-shrink" style="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;"><div style="position:absolute;width:200%;height:200%;left:0; top:0"></div></div></div>
            <!--添加员工的表单-->
            <form th:action="@{/update}" method="post">
                <input type="hidden" name="id" th:value="${emp.getId()}"> <!--这样就可以把员工id拿过来,封装成对象返回后台,后台对比id,就不会增加员工了-->
                <div class="form-group">
                    <label>LastName</label>
                    <input th:value="${emp.getLastName()}" type="text" name="lastName" class="form-control" placeholder="chaoxi">
                </div>
                <div class="form-group">
                    <label>Email</label>
                    <input th:value="${emp.getEmail()}" type="email" name="email" class="form-control" placeholder="admin@qq.com">
                </div>
                <div class="form-group">
                    <label>Gender</label>
                    <div class="form-check form-check-inline">
                        <input th:checked="${emp.getGender()==1}" class="form-check-input" type="radio" name="gender" value="1">
                        <label class="form-check-label">男</label>
                    </div>
                    <div class="form-check form-check-inline">
                        <input th:checked="${emp.getGender()==0}" class="form-check-input" type="radio" name="gender" value="0">
                        <label class="form-check-label">女</label>
                    </div>
                    <div class="form-group">
                        <label>department</label>
                        <select class="form-control" name="department.id">
                            <!--这里需要从后台查询已存在的部门放到这里来进行显示-->
                            <!--注意,我们再Controller接收的是一个employee,所以我们需要提交的是其中的一个属性-->
                            <option th:selected="${dept.getId()==emp.getDepartment().getId()}" th:each="dept:${departments}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"></option>

                        </select>
                    </div>
                    <div class="form-group">
                        <label>Birth</label>
                        <input th:value="${#dates.format(emp.getBirth(),'yyyy-MM-dd HH:mm:ss')}" type="text" name="birth" class="form-control" placeholder="chaoxi">
                    </div>
                    <button type="submit" class="btn btn-primary" th:href="@{/update}">提交修改</button>
                </div>
            </form>
        </main>

注意定义隐藏域:

<input type="hidden" name="id" th:value="${emp.getId()}">

这样才能将信息修改后与id绑定,封装成对象传给后台,避免重复生成。
修改完成后,跳转到主页:

<button type="submit" class="btn btn-primary" th:href="@{/update}">提交修改</button>
//修改完成后,跳回员工主页
    @PostMapping("/update")
    public String UpdateEmp(Employee employee){
        employeeDao.add(employee);
        return "redirect:/emps";
    }

员工的删除(最简单)

定义路由

<a class="btn btn-sm btn-danger" th:href="@{/delete/}+${emp.getId()}">删除</a>

编写controller:

@GetMapping("/delete/{id}")
    public String deleteEmp(@PathVariable("id")int id){
        employeeDao.delEmployee(id);
        return "redirect:/emps";
    }

自定义404页面

springboot中,直接在templates中建立一个error文件夹,将我们定义好的404模板文件放进去就行了。
当我们在url输错的时候,就会自动跳转到404页面。不需要写任何代码。
如图:
在这里插入图片描述

总结

其实一个网页应该有的功能都基本可以实现了。对数据的增删改查。其实对于后端开发人员来说,需要有一个自己的前端框架。后面就不断地在这个框架中添加分布式,数据库,消息队列等等。

模型参考自适应控制(MRAC):让PID参数动态优化 本文深入解析模型参考自适应控制(MRAC)技术,它通过实时调整PID参数,使控制系统能自动适应系统特性变化和外部干扰。文章详细介绍了MRAC的工作原理、数学基础,并提供了用C语言实现的实战代码示例,帮助工程师解决传统PID控制在非线性、时变系统中参数整定繁琐的难题。 阅读详情

相关推荐

OpenCV函数用法之calibrateCamera

参考链接:opencv中标定函数calibrateCamera_ychl87的专栏-优快云博客 世界坐标系的三维点投影到成像坐标系中的二维点的投影公式如下: 其中(X,Y,Z)为世界坐标系中的三维点; (u,v)为成像面坐标系中的二维点; A为相机的内参数矩阵:(cx,cy)为主光轴点,一般为图像的中心;fx和fy为焦距; [R|t]为相机的外参数矩阵:R为旋转矩阵,t为位移矩阵; 上述公式的简单推理过程如下 考虑到镜头畸变 其中,k1,k2,k3,k4,k5和k6为径向畸变,p1和.

tiger&sheep的博客 3万+

ThymeleafUtil - 文件生成 Utils-ThymeleafUtil - 工具类

ThymeleafUtil - 工具类 maven依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId&g...

scdncby的博客 2238

TMS320F280049C 学习笔记11 控制率加速器 CLA 例程

总结了TI官方在C2000Ware_3_01_00_00版本中提供的7个与CLA相关的例程。

whyorwhnt的专栏 1万+

springboot--thymeleaf

修改pom文件,引入对应坐标 &lt;dependencies&gt; &lt;!--web项目启动坐标--&gt; &lt;dependency&gt; &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt; &lt;artifactId&gt;sp...

zyp的博客 846

FIddler+Proxifer 实现PC客户端抓包详细教程

FIddler+Proxifer 实现PC客户端抓包详细教程

森明帮大于黑虎帮的博客 1万+

高通平台蓝牙学习-- 基于WCN6750 Bluetooth 5.2的讲解

摘要:蓝牙5.2解决方案WCN6750具备多项先进特性:完全兼容5.2标准及ANT+协议,支持2Mbps高速BLE和长距离传输;采用射频集成方案,与WLAN共享天线并支持5G并发;内置功率放大器,支持Class1/2传输;提供双音频流和Slimbus接口优化。其HCI UART接口支持3.2Mbps速率,通过BlueZ协议栈实现蓝牙5.2功能,包括2Mbps模式和长距离传输,符合核心规范要求。(149字)

专业开发者的博客,一个从事Android WiFi和蓝牙的工程师 3万+

Thymeleaf 使用后台自定义工具类处理文本

⏹Thymeleaf 使用后台自定义工具类处理文本

菜鸟记录 796

基于C#开发ABB机器人上位机系统:从操作控制到数据交互的全方位实现

ABB工业机器人是世界领先的自动化设备之一,广泛应用于焊接、装配、搬运、喷涂、包装等多个行业。机器人控制器:用于控制机器人运动、路径规划、状态监控等。上位机系统:提供人机交互界面,允许操作员与机器人进行交互,实现实时控制、参数调整和数据分析。上位机系统通过与机器人控制器通信,采集机器人状态数据,发送控制指令,实现远程监控和控制操作。通过高效的操作界面和数据交互,可以大大提高机器人的工作效率和系统的可维护性。基于C#开发ABB机器人上位机系统,能够实现高效的机器人控制与实时数据交互。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1178

SpringBoot学习笔记之五-Web开发Thymeleaf模板引擎

模板引擎 常用的模板引擎:JSP,Velocity,Freemarker,Thymeleaf等等 SpringBoot使用嵌入式的Tomcat,默认不支持JSP 模板引擎的作用:写一个页面模板 SpringBoot推荐Thymeleaf,语法更简单,功能更强大 用法: (1)引入模板引擎,在pom.xml文件中添加依赖: &lt;!--引入模板引擎--&gt; &lt;depe...

Stephanie的专栏 903

视觉-语言模型:BLIP与Flamingo如何理解图文?

视觉-语言模型:BLIP与Flamingo如何理解图文? ,人工智能,计算机视觉,大模型,AI,在当今人工智能飞速发展的时代,视觉 - 语言模型作为多模态领域的关键技术,正逐渐改变着我们与数字世界交互的方式。它们致力于打破图像与文本之间的模态壁垒,使计算机能够像人类一样,综合理解和处理视觉与语言信息。其中,BLIP 和 Flamingo 两款模型脱颖而出,以独特的架构和创新的训练方法,在图像描述生成、视觉问答、图文检索等任务中展现出卓越的性能。本文将深入剖析 BLIP 与 Flamingo 模型的工作原理。

不踩坑,不知道坑有多深;不总结,踩过的坑白踩。 4万+

【IxNetwork】史上最全IxNetwork测试仪使用精讲(一),图文教程超赞超详细!!!

IXIA使用的是Server-client模式,Server端在测试仪表的主机上,在开机后会随着主机内的操作系统的启动而自动启动,一般情况下不需要人为的手工启动。因此在通常不需要为主机配置专用的显示器和键盘。client端包括两个测试软件: Ixia Explorer和ScriptMate。这两个软件一般安装在测试用计算机上,在仪表自带的主机中也有这两个软件。根据测试项目的不同来选择使用不同的软件。Ixia Explorer主要提供数据流的测试,针对设备的功能进行测试;

风云说通信 2055

thymeleaf依赖

<dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring5</artifactId> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-java8ti

lazy_zhuo的博客 715

SolidWorks 小车底盘 装配体

通过制作小车底盘了解solidworks装配体的部分知识

及时总结 2226

如果我说熟悉SpringBoot 面试官会怎么问?

SpringBoot 因简化了 Spring 框架使用难度,极大地提高了Java企业级应用开发的效率,成为企业考核人才的重要标准之一。但随着现今互联网行业快速发展、企业业务不断深入,相应地对 SpringBoot 技术要求也愈来愈高。春节时期有一位打算金三银四面试的读者私信问我:如果我说熟悉SpringBoot 面试官会怎么问? ​ 可能不少朋友跟他一样,不清楚当下企业真实生产环境下对 SpringBoot 有哪些具体要求,需要掌握到什么程度。为此,结合这些年的面试经历及各大厂的职位要求,给

wdj_yyds的博客 8847

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

springboot学习01(从搭建到熟悉)

springboot学习,idea版本创建一个Springboot项目叫你怎么修改或者生成自己想要的springboot的自定义bannerspringboot的自动装配原理SpringApplicationapplication.yaml的配置JSR-303校验(注解:对类对象的数据进行数据校验,) springboot的最核心的原理:自动装配 创建一个Springboot项目 可以在官网直接下载,导入idea开发 直接使用idea创建一个springboot项目(开发选择第二种方式) 一般来说的,创

Smallcloudy的博客 598

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

springboot学习02(从搭建到熟悉)

springboot学习,idea版本

Smallcloudy的博客 377

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

SpringBoot的搭建(两种方式)

springboot搭建

感谢阅读 1万+

SpringBoot项目的搭建

一.有关SpringBoot的概念 1.使用SpringBoot的好处 简化开发难度,满足快速开发的需求。 如何实现快速开发:根据约定优于配置的设计原则来实现简化开发。 二.如何搭建SpringBoot项目 可以通过网页版或者Idea中自带的Spring Initializr (社区版需要下载一个插件也可以),这里我们通过使用Maven也可以搭建一个SpringBoot项目,首先需要知道SpringBoot的项目结构。 1.搭建框架第一步 通过之前Maven项目创建的默认步骤,然后创建好M

weixin_47651920的博客 1万+

springboot学习04(从搭建到熟悉)

springboot中的各种额外组件引用springboot整合JDBC使用整个Druid数据源整合mybatis springboot整合JDBC使用 一个网站离不开与数据库的交互,我们在创建springboot项目的时候,需要勾选至少以下组件。此处以JDBC为例子。 之后需要在项目中,引入jdbc和MYSQL的驱动依赖。 <dependency> <groupId>org.springframework.boot</groupId>

Smallcloudy的博客 377

SpringBoot搭建OAuth2

本文描述了通过SpringBoot从无到有的搭建OAuth2服务器的一系列实践过程。其中包括OAuth2的授权方式介绍,测试场景,过程中遇到的困难等,对新接触OAuth2的人有较大帮助。

m0_60681411的博客 3690

SpringBoot+jpa学习笔记一:SpringBoot+jpa+Maven框架搭建

文章目录1. SpringBoot+jpa学习笔记一:SpringBoot+jpa+Maven框架搭建1.1. 扩展知识1.2. 框架搭建步骤(IDE编译器)1.3. 创建SpringBoot+Maven框架1.4. 配置Jpa+hibernate接口1.5. 配置resource中的application.properties1.6. 参考文档 1. SpringBoot+jpa学习笔记一:Sp...

公子&小白的博客 5790

SpringBoot项目搭建

一. 前言 该文使用IDEA搭建SpringBoot项目。并配置日志打印 AOP mybatis语句打印 Result结果集等等。 二.项目搭建 1.File->new->project 2.Spring initializr --->选择JDK版本 --->Next 3.配置相关路径及名称 4.Web下勾选Spring Web Start 并调整SpringBoot版本 ---> Next 5.配置项目存储路径 ...

xiaoq的博客 1万+

Java——SpringBoot搭建(一)

本文仅仅简单介绍了springboot的简单搭建方法之一,而springboot还提供了大量功能,需要我们慢慢地去挖掘其他作用。

hxxxxm_w的博客 1553

springboot学习--maven+springboot项目搭建

一、简介 1.springboot Spring Boot使您可以轻松创建独立的生产级基于Spring的应用程序,您可以“运行”。我们对Spring平台和第三方库有自己的看法,所以你可以从最小的麻烦开始。大多数Spring Boot应用程序只需要很少的Spring配置。 特征 创建独立的Spring应用程序 直接嵌入Tomcat,Jetty或Undertow(无需部署W...

Destiny宿命的博客 1849

springBoot学习笔记(1)—— 搭建springBoot项目

springBoot学习系列笔记文章 文章目录springBoot学习系列笔记文章一、搭建项目1.步骤说明2.步骤截图二、项目代码1.引入jar包2.java代码运行截图总结 说明:此次项目的构建都是基于IDE软件。 一、搭建项目 1.步骤说明 点击“File”->“New”->“Module”。 选择"Spring Initializr",选择JDK8环境,点击“Next” 填入项目名Name,这里我填写的是springbootdemo,选择Java Version为8。 Web中引入Sp

xiayz的博客 731

SpringBoot-三种方式搭建

对SpringBoot的搭建,一心同学主要整理出了以上三种,在我们平时的开发当中,建议使用IDEA进行SpringBoot的搭建,因为这样更快,更方便。在这里,由于面试中MySQL问的比较多,因此也就在此以MySQL为例为大家总结分享。但是你要学习的往往不止这一点,还有一些主流框架的使用,Spring源码的学习,Mybatis源码的学习等等都是需要掌握的,我也把这些知识点都整理起来了《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!,更方便。

2401_84046545的博客 745
上一篇: springboot中druid数据源配置无效的问题和jar包找不到问题
下一篇: C语言数据结构学习
Smallcloudy
博客等级 码龄10年 53粉丝 36原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值