• 5、SpringBoot Web开发


    SpringBoot Web开发:

    springboot到底帮我们配置了什么?能不能修改,能修改哪些东西?能不能拓展

    • xxxxAutoConfigurartion…向容器中自动配置组件
    • xxxxProperties:自动配置类,装配配置文件中自定义的一些内容

    要解决的问题:

    • 导入静态资源…
    • 首页
    • jsp,模版引擎Thymeleaf
    • 装配扩展SpringMVC
    • 增删改查
    • 拦截器
    • 国际化

    1、静态资源的存放目录:


    我们在做以前项目的时候,有WebApp下可以放静态资源以及页面,SpringBoot中没有webapp了静态资源应该怎么放置呢?

    1. 在springboot,我们 可以使用以下方式处理静态资源
      • webjarslocalhost:8080/wbjars/
      • public, static,/**,resources
    2. 优先级:resources>static>(默认)>public

     WebMVCAutoConfiguration:可以看到webjars是通过以下路径来找到

    @Override
            protected void addResourceHandlers(ResourceHandlerRegistry registry) {
                super.addResourceHandlers(registry);
                if (!this.resourceProperties.isAddMappings()) {
                    logger.debug("Default resource handling disabled");
                    return;
                }
                ServletContext servletContext = getServletContext();
                addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
                addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
                    registration.addResourceLocations(this.resourceProperties.getStaticLocations());
                    if (servletContext != null) {
                        registration.addResourceLocations(new ServletContextResource(servletContext, SERVLET_LOCATION));
                    }
                });
            }

    Resources:是通过以下四个目录来找到静态资源

    private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",
                    "classpath:/resources/", "classpath:/static/", "classpath:/public/" };

    SpringBoot项目的静态资源文件夹的优先级:

      创建了三个文件名相同的文件,测试它们的优先级

     测试得到:resources目录 > static目录 > public目录

    2、网站首页存放目录

      将index页面放到静态资源目录:即上面的三个文件夹!优先级也是跟上面一样~

     自定义默认网站图标:

      1、将图片改为favicon.ico

      2、放在static目录下

      3、在application.yaml中添加,因为我使用的版本提示弃用的配置属性,不过不用管,可以运行成功!

    spring:
      mvc:
        favicon:
          enabled: false

       4、访问首页即可看到!

      我使用的是SpringBoot2.4.2,直接把ico图片放在static目录下,会自动识别

    3、☆模板引擎


      前端交给我们的页面,是html页面。如果是我们以前开发,我们需要把他们转成jsp页面,jsp好处就是当我们查出一些数据转发到JSP页面以后,我们可以用jsp轻松实现数据的显示,及交互等。jsp支持非常强大的功能,包括能写Java代码,

      但是呢,我们现在的这种情况,SpringBoot这个项目首先是以jar的方式,不是war,像第二,我们用的还是嵌入式的Tomcat,所以呢,他现在默认是不支持jsp的。

    那不支持jsp,如果我们直接用纯静态页面的方式,那给我们开发会带来非常大的麻烦,那怎么办呢,SpringBoot推荐你可以来使用模板引擎。

      那么这模板引擎,我们其实大家听到很多,其实jsp就是一个模板引擎,还有以用的比较多的freemarker,包括SpringBoot给我们推荐的Thymeleaf,模板引擎有非常多,但再多的模板引擎,他们的思想都是一样的,什么样一个思想呢我们来看一下这张图。

      模板引擎的作用就是我们来写一个页面模板,比如有些值呢,是动态的,我们写一些表达式。而这些值,从哪来呢,我们来组装一些数据,我们把这些数据找到。然后把这个模板和这个数据交给我们模板引擎,模板引擎按照我们这个数据帮你把这表达式解析、填充到我们指定的位置,然后把这个数据最终生成一个我们想要的内容给我们写出去,这就是我们这个模板引擎,不管是jsp还是其他模板引擎,都是这个思想。

      主要来介绍一下SpringBoot给我们推荐的Thymeleaf模板引擎,这模板引擎呢,是一个高级语言的模板引擎,他的这个语法更简单。而且呢,功能更强大。

    第一步:引入thymeleaf :

      怎么引入呢,对于springboot来说,什么事情不都是一个start的事情嘛,我们去在项目中引入一下。给大家三个网址:

    1、Thymeleaf 官网:https://www.thymeleaf.org/

    2、Thymeleaf 在Github 的主页:https://github.com/thymeleaf/thymeleaf

    3、Spring官方文档:“https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/htmlsingle/#using-boot-starter” , 找到我们对应的版本的maven依赖即可!

        <!--thymeleaf模板引擎-->
            <dependency>
                <groupId>org.thymeleaf</groupId>
                <artifactId>thymeleaf-spring5</artifactId>
            </dependency>
            <dependency>
                <groupId>org.thymeleaf.extras</groupId>
                <artifactId>thymeleaf-extras-java8time</artifactId>
            </dependency>    

    •  查看thymeleaf.properties源码

      通过前面的学习可以知道,每一个maven依赖对应的jar包都有一个对应的xxx.properties,所以我们找到thymeleaf.properties源码看一下:

    @ConfigurationProperties(
        prefix = "spring.thymeleaf"
    )
    public class ThymeleafProperties {
        private static final Charset DEFAULT_ENCODING;
        public static final String DEFAULT_PREFIX = "classpath:/templates/";
        public static final String DEFAULT_SUFFIX = ".html";
        private boolean checkTemplate = true;
        private boolean checkTemplateLocation = true;
        private String prefix = "classpath:/templates/";
        private String suffix = ".html";
        private String mode = "HTML";
        private Charset encoding;
    }

      我们可以在其中看到默认的前缀和后缀!我们只需要把我们的html页面放在类路径下的templates下,thymeleaf就可以帮我们自动渲染了。

      我们可以去测试一下 , 写一个Controller,跳转到一个指定页面,这个指定页面需要在 类路径下的模板目录下 【演示】使用thymeleaf什么都不需要配置,只需要将他放在指定的文件夹下即可!

    第二步:使用thymeleaf -取数据:


        我们做个最简单的练习 : 我们需要查出一些数据,在页面中展示

    我们去在controller编写一个请求,放进去一些数据;

     1 @Controller
     2 public class ThymeleafController {
     3     @RequestMapping("/some")
     4     public String demo(Model model) {
     5         model.addAttribute("msg", "Hello Thymeleaf!");
     6 
     7         // 添加数组数据
     8         String[] str = {"张三", "李四"};
     9         model.addAttribute("arr", str);
    10 
    11         // 添加list集合
    12         List list = new ArrayList<>();
    13         list.add("小二");
    14         list.add("小五");
    15         model.addAttribute("list", Arrays.asList(list));
    16 
    17         return "test";
    18     }
    19 }

      编写前端页面test.html,接收数据

     1 <!DOCTYPE html>
     2 <!--我们要使用thymeleaf,需要在html文件中导入命名空间的约束,方便提示-->
     3 <html lang="en" xmlns:th="http://www.thymeleaf.org">
     4 <head>
     5     <meta charset="UTF-8">
     6     <title>thymeleaf页面</title>
     7 </head>
     8 <body>
     9     <!--th:text就是将div中的内容设置为它指定的值,和之前学习的Vue一样-->
    10     <div th:text="${msg}"></div>
    11 
    12     <div>
    13         <!--遍历String数组-->
    14         <h3 th:each="strs:${arr}" th:text="${strs}"></h3>
    15     </div>
    16 
    17     <div>
    18         <!--遍历List集合-->
    19         <h3 th:each="arrList:${list}" th:text="${arrList}"></h3>
    20     </div>
    21 
    22 </body>
    23 </html>

    结果:


     4、Thymeleaf语法

     1 Selection Variable Expressions: *{...}:选择表达式:和${}在功能上是一样;
     2    补充:配合 th:object="${session.user}:
     3 
     4    <div th:object="${session.user}">
     5     <p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>
     6     <p>Surname: <span th:text="*{lastName}">Pepper</span>.</p>
     7     <p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
     8     </div>
     9     
    10 Message Expressions: #{...}:获取国际化内容
    11 Link URL Expressions: @{...}:定义URL;
    12             @{/order/process(execId=${execId},execType='FAST')}
    13 
    14 Fragment Expressions: ~{...}:片段引用表达式
    15             <div th:insert="~{commons :: main}">...</div>
    16             
    17 Literals(字面量)
    18       Text literals: 'one text' , 'Another one!' ,…
    19       Number literals: 0 , 34 , 3.0 , 12.3 ,…
    20       Boolean literals: true , false
    21       Null literal: null
    22       Literal tokens: one , sometext , main ,…
    23 Text operations:(文本操作)
    24     String concatenation: +
    25     Literal substitutions: |The name is ${name}|
    26 Arithmetic operations:(数学运算)
    27     Binary operators: + , - , * , / , %
    28     Minus sign (unary operator): -
    29 Boolean operations:(布尔运算)
    30     Binary operators: and , or
    31     Boolean negation (unary operator): ! , not
    32 Comparisons and equality:(比较运算)
    33     Comparators: > , < , >= , <= ( gt , lt , ge , le )
    34     Equality operators: == , != ( eq , ne )
    35 Conditional operators:条件运算(三元运算符)
    36     If-then: (if) ? (then)
    37     If-then-else: (if) ? (then) : (else)
    38     Default: (value) ?: (defaultvalue)
    39 Special tokens:
    40     No-Operation: _ 

     5、了解装配MVC以及扩展MVC

      官方建议:直接创建一个MVCconfig类,在类上加上 @Configuration 注解,并且实现WebMvcConfigurer接口,并且不能使用 @EnableWebMvc 注解

    为什么不能使用 @EnableWebMvc 注解

    • 这个注解导入了一个类:DelegatingWebMvcConfiguration,这个类从容器中获取所有的webmvcconfig

    并且在WebMvcAutoConfiguration类中有这样一个注解:

     @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) 
    • 这个注解的意思就是:容器中没有这个组件的时候,这个自动配置类才生效

    • 如果加了 @EnableWebMVC 容器中就有了组件,这个配置就不生效了

    如果需要全面接管SpringMVC可以使用该注解,当然在开发中,不推荐使用全面接管SpringMVC

      扩展:在springboot中,有非常多的xxxx Configuration帮助我们进行扩展配置、

    通常我们的添加功能扩展的类都是在config包下,而视图的跳转页面则放到templates包下:

      自定义一个视图解析器实现页面的跳转:

     1 /**
     2  * 扩展:自定义spring DispatcherServlet(视图解析器)
     3  *  如果你想diy一些定制化的功能, 只要写这个组件,然后将它交给springboot, springboot就会帮我们自动装配!
     4  */
     5 @Configuration
     6 public class MyMvcConfig implements WebMvcConfigurer {
     7 
     8     @Override
     9     /*添加视图控制器*/
    10     public void addViewControllers(ViewControllerRegistry registry) {
    11         // 如果视图控制器走/zhixi,就会跳转到view.html页面
    12         registry.addViewController("/zhixi").setViewName("view");
    13     }
    14 }

    6、前端基础

      

    如果你想定义你的404错误,就要将你的404.html页面放到templates/error/

    准备工作:

    1. 准备好模版(在网上找bootstrap或其他的模版,或者自己写)

    2. 页面直接放在templates下,css、img、js等放在static下

    3. 修改html页面,使其符合Thymeleaf模版规范

      • 在url路径属性前增加th:并修改url路径为@{}格式(js、css、img等)

       4. 准备数据

    在这里用Map模拟数据库中的数据,后期再进行数据库整合。

    pojo实体类:

      用户表:

     1 package com.zhixi.pojo;
     2 
     3 import lombok.AllArgsConstructor;
     4 import lombok.Data;
     5 import lombok.NoArgsConstructor;
     6 import org.springframework.stereotype.Repository;
     7 
     8 /**
     9  * @author zhangzhixi
    10  */
    11 @Data
    12 @AllArgsConstructor
    13 @NoArgsConstructor
    14 public class User {
    15     private Integer id;
    16     private String name;
    17     private int age;
    18     // 员工部门
    19     private Department department;
    20 }
    View Code

      部门表:

    package com.zhixi.pojo;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    /**
     * @author zhangzhixi
     * 部门表
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Department {
        private Integer id;
        private String departmentName;
    }
    View Code
    dao层业务:

      UserDao:

    package com.zhixi.dao;
    
    import com.zhixi.pojo.Department;
    import com.zhixi.pojo.User;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Repository;
    
    import java.util.Collection;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * @author zhangzhixi
     */
    @Repository
    public class UserDao {
        //模拟数据库中的数据
        private static Map<Integer, User> userMap = null;
    
        @Autowired
        // 员工所属的部门
        private static DepartmentDao departmentDao;
    
        static {
            //模拟数据库中的数据
            userMap = new HashMap<Integer, User>();
            userMap.put(101, new User(1001, "张三", 21, new Department(101, "教学部")));
            userMap.put(102, new User(1002, "李四", 22, new Department(102, "市场部")));
            userMap.put(103, new User(1003, "王五", 23, new Department(103, "后勤部")));
        }
    
        // 主键自增
        private static Integer initId = 1004;
    
        // 添加一个用户
        public void addUser(User user) {
            userMap.put(initId++, user);
        }
        // 查询全部员工
        public Collection<User> getUsers(){
            return userMap.values();
        }
        // 通过id查询员工
        public User getUserById(Integer id){
            return userMap.get(id);
        }
        // 删除一个员工
        public void delUser(Integer id){
            userMap.remove(id);
        }
    }
    View Code

      DepartmentDao:

     1 package com.zhixi.dao;
     2 
     3 import com.zhixi.pojo.Department;
     4 import org.springframework.stereotype.Repository;
     5 
     6 import java.util.Collection;
     7 import java.util.HashMap;
     8 import java.util.Map;
     9 
    10 /**
    11  * @author zhangzhixi
    12  * 部门dao
    13  */
    14 // 相当于Component注解
    15 @Repository
    16 public class DepartmentDao {
    17     private static Map<Integer, Department> Departments = null;
    18 
    19     static {
    20         //模拟数据库中的数据
    21         Departments = new HashMap<Integer, Department>();//创建一个部门表
    22         Departments.put(101, new Department(101, "教学部"));
    23         Departments.put(102, new Department(102, "市场部"));
    24         Departments.put(103, new Department(103, "后勤部"));
    25         Departments.put(104, new Department(104, "教研部"));
    26     }
    27 
    28     //获得所有部门信息
    29     public Collection<Department> getDepartments() {
    30         return Departments.values();
    31     }
    32 
    33     // 根据id查询部门
    34     public Department getDepartmentById(Integer id) {
    35         return Departments.get(id);
    36     }
    37 }
    View Code

    首页实现

    要求:默认访问首页

    方式一:写一个controller实现!

    1 //会解析到templates目录下的index.html页面
    2 @RequestMapping({"/","/index.html"})
    3  public String index(){
    4      return "index";
    5 }

    方式二:自己编写MVC的扩展配置

    1 @Configuration
    2 public class MyMVCConfig implements WebMvcConfigurer {
    3     @Override
    4     public void addViewControllers(ViewControllerRegistry registry) {
    5         //param1:路径,param2:名称
    6         registry.addViewController("/").setViewName("index");
    7         registry.addViewController("/index.html").setViewName("index");
    8     }
    9 }

    解决了这个问题,我们还需要解决一个资源导入的问题;

    为了保证资源导入稳定,我们建议在所有资源导入时候使用 th:去替换原有的资源路径!

    1 <!--“/”默认就是statics目录-->
    2 <link th:href="@{/css/style.css}" rel="stylesheet" />
    3 
    4 </head>
    5 <body>
    6 
    7 <script th:src="@{/js/anime.min.js}"></script>

     7、项目国际化

    1、在页面设置按钮发送请求,并修改页面文字元素为thymeleaf格式

    注意踩坑,这里的index不带后缀名

        <!--设置语言切换-->
        <a class="btn btn-sm" th:href="@{/index(l='zh_CN')}">中文</a>
        <a class="btn btn-sm" th:href="@{/index(l='en_US')}">English</a>

    2、在resources下创建i18n文件夹,并创建login.proterties文件login_zh_CN.proterties文件login_en_US.proterties文件并写入数据

    login.tip=请登录
    login.username=用户名
    login.password=密码
    login.remember=保存密码
    login.btn=登录
    
    login.tip=请登录
    login.username=用户名
    login.password=密码
    login.remember=保存密码
    login.btn=登录
    
    login.tip=please sign in
    login.username=username
    login.password=userpassword
    login.remember=save pwd
    login.btn=login
    

    3、在核心配置文件中配置一下属性

    # 国际化配置文件的真实位置
    spring.messages.basename=iI18n.login
    

    4、在config包内创建类,实现localereslover接口,重写方法,解析请求

     1 package com.zhixi.config;
     2 
     3 import org.springframework.util.StringUtils;
     4 import org.springframework.web.servlet.LocaleResolver;
     5 
     6 import javax.servlet.http.HttpServletRequest;
     7 import javax.servlet.http.HttpServletResponse;
     8 import java.util.Locale;
     9 
    10 /**
    11  * @author zhangzhixi
    12  * 编写语言解析器设置
    13  */
    14 public class MyLocalResolver implements LocaleResolver {
    15     @Override
    16     public Locale resolveLocale(HttpServletRequest request) {
    17         // 获取到首页传来的语言版本
    18         String language = request.getParameter("l");
    19         // 识别语言版本,没有就使用默认的
    20         Locale locale = Locale.getDefault();
    21         System.out.println("========>" + language);
    22         // 请求参数携带了国际化参数,将语言zh_CH进行分割
    23         if (!StringUtils.isEmpty(language)) {
    24             System.out.println("==============");
    25             String[] split = language.split("_");
    26             // 设置国家和地区
    27             System.out.println(split[0]);
    28             System.out.println(split[1]);
    29             locale = new Locale(split[0], split[1]);
    30         }
    31         return locale;
    32     }
    33     @Override
    34     public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
    35     }
    36 }

    5、在mvcconfig配置Bean

    注意踩坑,这里的方法名必须是localeResolver

        // 注册语言解析器
        @Bean
        public LocaleResolver localeResolver(){
            return new MyLocalResolver();
        }
    

    6、测试运行

    附:index首页代码

     1 <!DOCTYPE html>
     2 <html lang="en" xmlns:th="http://www.thymeleaf.org">
     3 <head>
     4     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
     5     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
     6     <meta name="description" content="">
     7     <meta name="author" content="">
     8     <title>Signin Template for Bootstrap</title>
     9     <link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
    10     <link th:href="@{/css/signin.css}" rel="stylesheet">
    11 </head>
    12 
    13 <body class="text-center">
    14 <form class="form-signin" action="dashboard.html">
    15     <img class="mb-4" th:src="@{/img/bootstrap-solid.svg}" alt="" width="72" height="72">
    16 
    17 
    18     <!--请登录-->
    19     <h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>
    20     <!--账号密码-->
    21     <input type="text" class="form-control" th:placeholder="#{login.username}" required="" autofocus="">
    22     <input type="password" class="form-control" th:placeholder="#{login.password}" required="">
    23 
    24     <div class="checkbox mb-3">
    25         <label>
    26             <!--记住密码-->
    27             <input type="checkbox" value="remember">[[#{login.remember}]]
    28         </label>
    29     </div>
    30     <!--登录-->
    31     <button class="btn btn-lg btn-primary btn-block" type="submit">[[#{login.btn}]]</button>
    32     <p class="mt-5 mb-3 text-muted">© 2017-2018</p>
    33     <!--设置语言切换-->
    34     <a class="btn btn-sm" th:href="@{/index(l='zh_CN')}">中文</a>
    35     <a class="btn btn-sm" th:href="@{/index(l='en_US')}">English</a>
    36 </form>
    37 
    38 </body>
    39 
    40 </html>
    View Code

     8、登录+拦截器功能实现


    登录:

      1、这里就先不连接数据库了,输入任意用户名都可以登录成功!

    声明一个之前没有提到的问题: templates下的页面只能通过Controller跳转实现,而static下的页面是能直接被外界访问的,就能正常访问了。 

    我们把登录页面的表单提交地址写一个controller!

    <form class="form" th:action="@{/user/login}" method="post">

      2、去编写对应的controller

    @Controller
    public class LoginController {
        @RequestMapping("/user/login")
        public String login(
                @RequestParam("username") String username,
                @RequestParam("password") String password,
                Model model,) {
    
            if (username != null && "123".equals(password)) {
                // 重定向到controller请求中
                return "redirect:/main.html";
            } else {
                // 告诉用户登录失败
                model.addAttribute("msg", "用户名或者密码错误");
                return "index";
            }
        }
    }
    

      3、关闭页面缓存

    页面存在缓存,所以我们需要禁用模板引擎的缓存

    #禁用模板缓存spring.thymeleaf.cache=false 

      4、给出用户登录失败提示

    <!--判断是否显示,使用if, ${}可以使用工具类,可以看thymeleaf的中文文档-->
    <p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>

      5、在MVCConfig中添加视图控制映射

    能够在第2步中的redirect中能够跳转到对应的页面

    // 接收请求,转到页面
    registry.addViewController("/main.html").setViewName("dashboard");

      6、登录测试

    成功:

    失败:

    模板引擎修改后,想要实时生效!页面修改完毕后,IDEA小技巧 : Ctrl + F9 重新编译!

    拦截器:HandlerInterceptor


      重定向成功之后!我们解决了之前资源没有加载进来的问题!后台主页正常显示!

    但是又发现新的问题,我们可以直接登录到后台主页,不用登录也可以实现!

    怎么处理这个问题呢?我们可以使用拦截器机制,实现登录检查!

      1、config包中自定义拦截器:

    public class LoginHandlerInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
            Object login = request.getSession().getAttribute("login");
    
            // 提示用户没有登录成功
            if (login == null) {
                request.setAttribute("msg", "没有权限,请先登录!");
                request.getRequestDispatcher("/index").forward(request, response);
                return false;
            }
            return true;
        }
    }

     2、将拦截器注册到我们的SpringMVC配置类当中!

        // 拦截器设置
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new LoginHandlerInterceptor())
                    // 拦截所有请求
                    .addPathPatterns("/**")
                    // 放行指定路径
                    .excludePathPatterns("/", "/index", "/user/login", "/css/*", "/js/*");
        }

      3、测试,直接访问主页

    9、展示用户页

     1、首页点击用户后进行跳转

    <li class="nav-item">
        <!--请求路径就到controller中-->
        <a class="nav-link" th:href="@{/emps}">
            员工
        </a>
    </li>
    

    2、定义一个controller类来实现处理请求数据的功能

    @Controller
    public class UserController {
        @Autowired
        private UserDao userDao;
    
        @RequestMapping("/emps")
        public String list(Model model) {
            // 调用dao层业务方法获取全部用户
            Collection<User> users = userDao.getUsers();
            // model携带用户数据
            model.addAttribute("emp", users);
            // 跳转到list页面展示
            return "emp/list";
        }
    }
    

    3、在list页面中定义表格,将获取到的数据通过thymeleaf显示出来

    <div class="table-responsive">
    	<table class="table table-striped table-sm">
    		<thead>
    			<tr>
    				<th>编号</th>
    				<th>姓名</th>
    				<th>年龄</th>
    				<th>部门编号</th>
    				<th>部门名称</th>
    				<th>操作</th>
    			</tr>
    		</thead>
    		<tbody>
    			<tr th:each="emps:${emp}">
    				<td th:text="${emps.getId()}"></td>
    				<td th:text="${emps.getName()}"></td>
    				<td th:text="${emps.getAge()}"></td>
    				<td th:text="${emps.getDepartment().getId()}"></td>
    				<td th:text="${emps.getDepartment().getDepartmentName()}"></td>
    				<td>
    					<button class="btn btn-sm btn-primary">编辑</button>
    					<button class="btn btn-sm btn-danger">删除</button>
    				</td>
    			</tr>
    		</tbody>
    	</table>
    </div>
    

     10、添加员工


    1、在用户展示的list页面添加跳转到添加员工页面

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

    2、编写controller跳转到添加用户页面

    // 添加用户界面
    @GetMapping("/emp")
    public String addUser(Model model) {
        // 查出所有部门的信息
        Collection<Department> departments = departmentDao.getDepartments();
        model.addAttribute("departments", departments);
        // 请求到add页面
        return "emp/add";
    }
    

    3、add页面添加表单数据:注意name属性要跟字段一致,否则表单不会将数据进行提交

    <form th:action="@{/emp}" method="post">
        <div class="form-group">
            <label>员工姓名</label>
            <input type="text" class="form-control" placeholder="xxx" name="name">
        </div>
        <div class="form-group">
            <label>员工年龄</label>
            <input type="text" class="form-control" placeholder="xxx" name="age">
        </div>
        <div class="form-group">
            <label>员工部门</label>
            <select class="form-control" name="department.id">
                <option th:each="dept:${departments}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"></option>
            </select>
        </div>
        <button type="submit" class="btn btn-primary">添加</button>
    </form>
    

    4、添加用户成功跳转到查询全部员工界面

    // 添加用户成功请求(跳转到首页)
    @PostMapping("/emp")
    public String addEmp(User user) {
        // 用户点击添加按钮,底层执行添加操作
        System.out.println("add==>" + user);
        userDao.addUser(user);
        // 重定向到查询全部用户界面
        return "redirect:/emps";
    }
    

      

      

  • 相关阅读:
    X lvm管理:扩展lv、删除pv、lv,删除物理卷PV
    X 如何在Linux中缩小LVM大小(逻辑卷调整)如何在Linux中缩小LVM大小(逻辑卷调整)
    元素和为目标值的子矩阵数量
    完美矩形问题
    桶排序算法
    组合数组合
    求两个有序数组的第k大的数(默认两有序数组都为从小到大)
    二叉树的遍历
    卡特兰数
    二叉排序树
  • 原文地址:https://www.cnblogs.com/zhangzhixi/p/14321709.html
Copyright © 2020-2023  润新知