zoukankan      html  css  js  c++  java
  • SpringBoot-Web开发

    SpringBoot Web开发

    1. 自动装配

    SpringBoot到底帮我们配置了什么? 我们能不能进行修改? 能修改哪些东西? 能不能扩展?

    • XXXAutoConfiguration: 向容器中自动装配的组件
    • XXXProperties: 自动装配类, 装配配置文件中自定义的一些内容!

    2. 要解决的问题

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

    3. 静态资源

    静态资源目录

    默认

    • resources下的 (优先级由高到低)
      • resources
      • static(默认)
      • public
    • /** (根目录:localhost:8080/)

    自定义静态资源后, 以上的目录失效

    spring.mvc.static-path-pattern=/hello
    

    4. 首页如何定制

    位置: 静态资源目录下的index.html

    定制标签的图标: 在static目录下新建favicon.ico即可

    5. 模板引擎

    image-20200917154838115

    1. 导入依赖

    <!--导入thymeleaf模板引擎依赖, 我们都是基于3.X开发的-->
    <dependency>
        <groupId>org.thymeleaf</groupId>
        <artifactId>thymeleaf-spring5</artifactId>
    </dependency>
    <dependency>
        <groupId>org.thymeleaf.extras</groupId>
        <artifactId>thymeleaf-extras-java8time</artifactId>
    </dependency>
    

    2. 使用

    在resources下的template目录下放html页面即可

    @ConfigurationProperties(prefix = "spring.thymeleaf")
    public class ThymeleafProperties {
    
       private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;
    
       public static final String DEFAULT_PREFIX = "classpath:/templates/";
    
       public static final String DEFAULT_SUFFIX = ".html";
    

    controller控制视图跳转

    package com.wang.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import java.util.Arrays;
    
    //在template目录下的所有页面, 只能通过controller来跳转
    //这个需要模板引擎的支持
    @Controller
    public class IndexController {
    
        @RequestMapping("/test")
        public String index (Model model) {
            model.addAttribute("msg", "Hello, ThymeLeaf!");
            model.addAttribute("htmlMsg", "<h1>Hello, ThymeLeaf!</h1>");
            model.addAttribute("users", Arrays.asList("王", "赵", "李"));
            return "test";
        }
    }
    

    3. thymeleaf使用

    在html中添加约束

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

    Simple expressions:

    • Variable Expressions: ${...}
    • Selection Variable Expressions: *{...}
    • Message Expressions: #{...}
    • Link URL Expressions: @{...}
    • Fragment Expressions: ~{...}
    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org" lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
    <!--所有的HTML元素, 都可以被 thymeleaf接管:    th: 元素名-->
    
    <div th:text="${msg}"></div>
    
    <!--转义html标签-->
    <div th:utext="${htmlMsg}"></div>
    <hr>
    
    <!--遍历 th:each-->
    <div th:each="user : ${users}" th:text="${user}"></div>
    
    </body>
    </html>
    

    6. 扩展装配MVC

    如果我们要扩展SpringMVC, 官方建议我们做以下两步:

    • @Configuration. Java配置类
    • 实现WebMvcConfigurer接口

    自己定义一个视图解析器

    package com.wang.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.View;
    import org.springframework.web.servlet.ViewResolver;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    import java.util.Locale;
    
    //全面扩展SpringMvc
    @Configuration
    public class MyMvcConfig implements WebMvcConfigurer {
    
        /*
        public interface ViewResolver
        实现了视图解析器接口的类, 我们就可以把它看做视图解析器
         */
        //注册一个bean, 就相当于我们之前在xml中写的一bean标签
        //这个方法的名字就相当于bean标签中的id属性
        //这个方法的返回值就相当于bean标签中的class属性
        @Bean
        public ViewResolver myViewResolver() {
            //返回值就是要注入到bean中的对象
            return new MyViewResolver();
        }
    
    
        //自定义了一个自己的视图解析器
        public static class MyViewResolver implements ViewResolver{
            @Override
            public View resolveViewName(String s, Locale locale) throws Exception {
                return null;
            }
        }
    
    
    }
    

    在doDispatch方法打断点, 访问localhost:8080

    image-20200917171006087

    发现自己的视图解析器被加载了

    结论:

    如果想要定制化一些功能, 只需要写这个组件, 然后将它交给SpringBoot(利用注解注册Bean), 然后他就会被自动装配!

    7. 员工管理

    1. 创建实体类

    package com.wang.pojo;
    
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    import java.util.Date;
    //员工表
    @Data
    @NoArgsConstructor
    public class Employee {
        private Integer id;
        private String lastName;
        private String email;
        private Integer gender; //0: 女, 1:  男
    
        private Department department;
        private Date date;
    
        public Employee(Integer id, String lastName, String email, Integer gender, Department department) {
            this.id = id;
            this.lastName = lastName;
            this.email = email;
            this.gender = gender;
            this.department = department;
            //默认的创建日期
            this.date = new Date();
        }
    }
    
    package com.wang.pojo;
    //部门表
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Department {
        private Integer id;
        private String departmentName;
    }
    

    2. 模拟数据库, 创建Dao

    package com.wang.dao;
    
    import com.wang.pojo.Department;
    import org.springframework.stereotype.Repository;
    
    import java.util.Collection;
    import java.util.HashMap;
    import java.util.Map;
    
    //部门Dao
    @Repository
    public class DepartmentDao {
        //模拟数据库中的数据
        private static Map<Integer, Department> departments = null;
        static {
            departments = new HashMap<>();      //创建一个部门表
    
            departments.put(101, new Department(101, "教学部"));
            departments.put(101, new Department(102, "市场部"));
            departments.put(101, new Department(103, "教研部"));
            departments.put(101, new Department(104, "运营部"));
            departments.put(101, new Department(105, "后勤部"));
        }
    
        //获得所有部门的信息
        public Collection<Department> getDepartments() {
            return departments.values();
        }
    
        //通过id获得部门
        public Department getDepartmentById(Integer id) {
            return departments.get(id);
        }
    
    }
    
    package com.wang.dao;
    
    import com.wang.pojo.Department;
    import com.wang.pojo.Employee;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Repository;
    
    import java.util.Collection;
    import java.util.HashMap;
    import java.util.Map;
    
    //员工Dao
    @Repository
    public class EmployeeDao {
        //模拟数据库中的数据
        private static Map<Integer, Employee> employees = null;
        //员工所属部门
        @Autowired
        private DepartmentDao departmentDao;
        static {
            employees = new HashMap<>();    //创建一个部门表
    
            employees.put(1001, new Employee(1001, "AA", "A12345678@qq.com", 0, new Department(101, "教学部")));
            employees.put(1002, new Employee(1002, "BB", "B12345678@qq.com", 1, new Department(102, "市场部")));
            employees.put(1003, new Employee(1003, "CC", "C12345678@qq.com", 0, new Department(103, "教研部")));
            employees.put(1004, new Employee(1004, "DD", "D12345678@qq.com", 1, new Department(104, "运营部")));
            employees.put(1005, new Employee(1005, "EE", "E12345678@qq.com", 0, new Department(105, "后勤部")));
        }
    
        //主键自增!
        private static Integer initId = 1006;
        //增加 一个员工
        public void save(Employee employee) {
            //如果没有id, 主键自增
            if (employee.getId() == null) {
                employee.setId(initId++);
            }
    
            //如果部门name错误, 通过部门ID可以取到正确的值
            employee.setDepartment(departmentDao.getDepartmentById(employee.getDepartment().getId()));
    
            employees.put(employee.getId(), employee);
        }
    
        //查询全部员工的信息
        public Collection<Employee> getAll() {
            return employees.values();
        }
    
        //通过ID查询员工
        public Employee getEmployeeByID (Integer id) {
            return employees.get(id);
        }
    
        //通过ID删除员工
        public void deleteEmployeeById (Integer id) {
            employees.remove(id);
        }
    
    
    }
    

    3. 可以在controller中控制视图跳转

    package com.wang.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    public class IndexController {
    
        //访问首页和/index都会跳转
        @RequestMapping({"/", "/index"})
        public String index() {
            return "index";
        }
    }
    

    注意:

    • 跳转多个路径, 用{ , }

    4. 也可以在自定义config中设置视图跳转

    package com.wang.config;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    //全面扩展SpringMvc
    @Configuration
    public class MyMvcConfig implements WebMvcConfigurer {
    
        @Override
        public void addViewControllers(ViewControllerRegistry registry) {
            registry.addViewController("/").setViewName("index");
            registry.addViewController("/index").setViewName("index");
        }
    }
    

    重写addViewController方法, 同样可以跳转多个路径

    在SpringBoot中, 视图跳转的返回值自动被设置了前缀(templates)和后缀(.html), 直接写页面文件名即可

    5. 修改模板为thymeleaf

    修改页面后不生效, 在配置文件中关闭模板引擎的缓存

    #关闭模板引擎的缓存
    spring.thymeleaf.cache=false
    

    修改url, 在标签前加th:表示被模板引擎接管了

    • Link URL Expressions: @{...}

    注意, 路径直接从静态资源目录找, 即直接写静态资源下的路径就可以了

    修改的时候, 只修改位于本地的资源即可

    所有页面的静态资源都要用thymeleaf接管!

    6. 页面的国际化

    1. 配置i18n

    在resource目录下建立i18n, 分别建立login.properties, login_en_US.properties, login_zn_CN.properties, 可以使用Resource Bundle方便写对应的配置文件

    image-20200918142141133

    2. 需要在项目中进行按钮切换, 需要自定义组件

    package com.wang.config;
    
    import org.springframework.util.StringUtils;
    import org.springframework.web.servlet.LocaleResolver;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.util.Locale;
    
    //实现了LocaleResolver就是一个国际化解析器
    public class MyLocaleResolver implements LocaleResolver {
    
        //解析请求
        @Override
        public Locale resolveLocale(HttpServletRequest request) {
            //获取请求中的参数 l
            String language = request.getParameter("l");
    
            //如果没有, 就使用默认的
            Locale locale = Locale.getDefault();
    
            //如果请求的链接携带了国际化的参数
            if (!StringUtils.isEmpty(language)) {
                String[] split = language.split("_");
                //国家, 地区
                locale = new Locale(split[0], split[1]);
            }
    
            return locale;
        }
    
        @Override
        public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
    
        }
    }
    

    3. 记得将自己写的组件配置到Spring容器中

    用@Bean注册为bean, 注意方法的名字必须写对, 因为这是bean的id!, 返回值为bean的value

    package com.wang.config;
    
    import org.apache.tomcat.util.descriptor.LocalResolver;
    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.ViewControllerRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    //全面扩展SpringMvc
    @Configuration
    public class MyMvcConfig implements WebMvcConfigurer {
    
        @Override
        public void addViewControllers(ViewControllerRegistry registry) {
            registry.addViewController("/").setViewName("index");
            registry.addViewController("/index").setViewName("index");
        }
    
        //在这里注册自己写的配置文件, 这样自定义国际化组件就生效了!
        @Bean
        public LocaleResolver localeResolver() {
            return new MyLocaleResolver();
        }
    }
    

    4. 前端页面用#{}配置消息, @{}配置url, ()直接传参

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <meta name="description" content="">
        <meta name="author" content="">
        <title>Signin Template for Bootstrap</title>
        <!-- Bootstrap core CSS -->
        <link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
        <!-- Custom styles for this template -->
        <link th:href="@{css/signin.css}" rel="stylesheet">
    </head>
    
    <body class="text-center">
    <form class="form-signin" action="dashboard.html">
        <img class="mb-4" th:src="@{/img/bootstrap-solid.svg}" alt="" width="72" height="72">
        <h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}"></h1>
        <label class="sr-only" th:text="#{login.username}">Username</label>
        <input type="text" class="form-control" th:placeholder="#{login.username}" required="" autofocus="">
        <label class="sr-only" th:text="#{login.password}">Password</label>
        <input type="password" class="form-control" th:placeholder="#{login.password}" required="">
        <div class="checkbox mb-3">
            <label>
                <input type="checkbox" value="remember-me" th:text=" #{login.remember}">
            </label>
        </div>
        <button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.btn}">Sign in</button>
        <p class="mt-5 mb-3 text-muted">© 2017-2018</p>
        <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>
    </form>
    
    </body>
    
    </html>
    

    7. 登陆功能实现

    1. controller

    package com.wang.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.util.StringUtils;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    
    @Controller
    public class LoginController {
    
        @RequestMapping("/user/login")
        public String login(@RequestParam("username") String username, @RequestParam("password") String password, Model model) {
            //具体的业务
            if (!StringUtils.isEmpty(username) && "123456".equals(password)) {
                //重定向
                return "redirect:/main";
            } else {
                //提示用户,登录失败
                model.addAttribute("msg", "用户名或密码错误!");
                //返回登录页
                return "index";
            }
        }
    }
    

    注意

    • 可以直接取到前端中name属性对应的值, 但推荐使用@RequestParam注释进行绑定
    • 如果要返回前端一些信息, 使用Model并用addAttribute(name, value)

    2. 修改前端显示信息

    可以使用模板引擎提供的一些工具类进行判断是否显示信息

    <!--如果msg的结果为空, 则不显示消息-->
    <p th:text="${msg}" style="color: red" th:if="${not #strings.isEmpty(msg)}"></p>
    

    3. 在自定义配置类中添加视图控制

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("index");
        registry.addViewController("/index").setViewName("index");
        registry.addViewController("/main").setViewName("dashboard");
    }
    

    8. 登录拦截器

    1. 编写拦截器

    package com.wang.config;
    
    import org.springframework.web.servlet.HandlerInterceptor;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    //实现了HandlerInterceptor接口就是一个拦截器
    public class LoginHandlerIntercepter implements HandlerInterceptor {
        //return true就是放行
        @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").forward(request, response);
                //不放行
                return false;
            } else {
                return true;
            }
        }
    }
    

    2. 在配置类中配置拦截器

    //配置拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginHandlerIntercepter())
                .addPathPatterns("/**")
                .excludePathPatterns("/index", "/", "/user/login", "/static/**");
    }
    

    注意

    • 重写addInterceptors方法
    • addPathPatterns写要拦截的url
    • excludePathPatterns写要放行的资源, 注意要将静态资源放行!
    • / 和 /* 的区别**
      • / 是拦截所有的文件夹,不包含子文件夹*
      • / 是拦截所有的文件夹及里面的子文件夹**

    3. 在前端页面从session中取出结果

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

    使用[[${}]]即可取出, session用session.字段 即可取出对应字段在session中存放的值!

    9. 展示员工列表

    1. 利用thymeleaf抽取模板

    <nav class="col-md-2 d-none d-md-block bg-light sidebar" th:fragment="sidebar">
    

    th:fragment="" 抽取模板

    <div th:insert="~{dashboard::sidebar}"></div>
    

    th:insert="~{}"使用模板

    花括号中的内容为 文件名::模板名

    可以将公用的模板放在一个html中

    通过 () 可以传递一些值, 接收判断即可

    <div th:insert="~{commons/commons::sidebar(active='list')}"></div>
    

    这样可以实现对一些标签的两种状态的切换

    <a th:class="${active=='list'?'nav-link active':'nav-link'}" th:href="@{/employees}">
    

    2. 列表循环展示

    <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="employee:${employees}">
                <td th:text="${employee.getId()}"></td>
                <td th:text="${employee.getLastName()}"></td>
                <td th:text="${employee.getEmail()}"></td>
                <td th:text="${employee.getGender() == 0 ? '女' : '男'}"></td>
                <td th:text="${employee.getDepartment().getDepartmentName()}"></td>
                <td th:text="${#dates.format(employee.getDate(), 'yyyy-MM-dd HH:mm:ss')}"></td>
                <td>
                    <button class="btn btn-sm btn-primary">编辑</button>
                    <button class="btn btn-sm btn-danger">删除</button>
                </td>
            </tr>
        </tbody>
    </table>
    

    用 th:each="" 遍历, 用 th:text="${}" 展示其中的元素

    10. 添加员工

    SpringBoot默认的date格式为 / 分隔

    image-20200921104854168

    我们为了实现输入日期用 - 分隔, 在配置文件中设置日期格式

    spring.mvc.format.date=yyyy-MM-dd
    

    1. 按钮提交

    main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
        <h2>
            <a class="btn btn-sm btn-success" th:href="@{/addEmployee}">添加员工</a>
        </h2>
    

    a标签默认的提交方式为get请求

    2. 跳转到添加页面

    //只能用get方式获得请求, 前端请求添加员工, 这里进行页面的跳转
    @GetMapping("/addEmployee")
    public String toAddPage(Model model) {
        //查出所有部门的信息
        Collection<Department> departments = departmentDao.getDepartments();
        model.addAttribute("departments", departments);
    
        return "employees/add";
    }
    
    <main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
    
        <form th:action="@{/addEmployee}" method="post">
            <div class="form-group">
                <label>LastName</label>
                <input type="text" name="lastName" class="form-control" placeholder="请输入姓氏">
            </div>
            <div class="form-group">
                <label>Email</label>
                <input type="email" name="email" class="form-control" placeholder="请输入邮箱">
            </div>
            <div class="form-group">
                <label>Gender</label><br>
                <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>
            <div class="form-group">
                <label>department</label>
                <!--由于我们在controller中接收的是一个department对象, 而我们提交的是其中的一个属性, 因此要写成name="department.id"-->
                <select class="form-control" name="department.id">
                    <!--这里提交的是value-->
                    <option th:each="department:${departments}" th:text="${department.getDepartmentName()}"
                            th:value="${department.getId()}"></option>
                </select>
            </div>
            <div class="form-group">
                <label>Birth</label>
                <input type="text" name="date" class="form-control" placeholder="请输入出生日期">
            </div>
            <button type="submit" class="btn btn-primary">添加</button>
        </form>
    
    
    </main>
    

    这里使用post请求提交

    表单的name属性要与pojo中的属性一一对应, 这样才能取到自动装配后对应的值

    3. 添加员工成功

    //只能用post方式获得请求, 与上面的get方式的url一致, 是RestFul风格
    @PostMapping("/addEmployee")
    public String addEmployee(Employee employee) {
        //添加的操作
        //调用底层业务方法, 保存员工信息
        employeeDao.save(employee);
        return "redirect:/employees";
    }
    

    添加成功后跳转到员工展示页面, 从map中遍历并展示

    11. 修改员工

    1. 添加修改按钮

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

    利用url传递参数, 将当前选中的对象的id传到后端

    2. 跳转到修改页面

    //去员工的修改页面
    @GetMapping("/employee/{id}")
    public String toUpdateEmployee(@PathVariable("id")Integer id, Model model) {
        //查出原来的数据
        Employee employee = employeeDao.getEmployeeByID(id);
        model.addAttribute("employee", employee);
        Collection<Department> departments = departmentDao.getDepartments();
        model.addAttribute("departments", departments);
        return "employees/update";
    }
    

    @PathVariable 注解,让方法参数的值对应绑定到一个URI模板变量上 ( RestFul风格, 路径格式为 /XXX/{XX} )

    这里由于我们要显示departmentId对应的名字, 要把department对象也传递到前端

    3. 设计修改页面

    注意前端的name要与属性一致!

    由于我们设计了主键自增, 而修改页面无需让用户看到自己的id, 因此利用隐藏域传递id, 防止创建新的用户

    要显示选中用户的属性值, 用value

    date格式很重要, 我们可以指定显示的日期格式: th:value="${#dates.format(employee.getDate(), 'yyyy-MM-dd')}"

    <main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
    
        <form th:action="@{/updateEmployee}" method="post">
            <!--利用隐藏域传递id, 从而实现修改当前用户的功能-->
            <input type="hidden" name="id" th:value="${employee.getId()}">
            <div class="form-group">
                <label>LastName</label>
                <input type="text" name="lastName" class="form-control" placeholder="请输入姓氏"
                       th:value="${employee.getLastName()}">
            </div>
            <div class="form-group">
                <label>Email</label>
                <input type="email" name="email" class="form-control" placeholder="请输入邮箱"
                       th:value="${employee.getEmail()}">
            </div>
            <div class="form-group">
                <label>Gender</label><br>
                <div class="form-check form-check-inline">
                    <input class="form-check-input" type="radio" name="gender" value="1"
                           th:checked="${employee.getGender()==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"
                           th:checked="${employee.getGender()==0}">
                    <label class="form-check-label">女</label>
                </div>
            </div>
            <div class="form-group">
                <label>department</label>
                <!--由于我们在controller中接收的是一个department对象, 而我们提交的是其中的一个属性, 因此要写成name="department.id"-->
                <select class="form-control" name="department.id">
                    <!--这里提交的是value, 所以要得到id-->
                    <!--选择与修改员工的部门一致的id, 遍历, 一致则为true, 选中-->
                    <option th:each="department:${departments}" th:text="${department.getDepartmentName()}"
                            th:selected="${department.getId()==employee.getDepartment().getId()}"
                            th:value="${department.getId()}"></option>
                </select>
            </div>
            <div class="form-group">
                <label>Birth</label>
                <input type="text" name="date" class="form-control" placeholder="请输入出生日期"
                       th:value="${#dates.format(employee.getDate(), 'yyyy-MM-dd')}">
            </div>
            <button type="submit" class="btn btn-primary">修改</button>
        </form>
    
    
    </main>
    

    4. 保存修改结果

    将修改页面的值读到employee对象中, 保存

    @PostMapping("/updateEmployee")
    public String updateEmployee(Employee employee) {
        employeeDao.save(employee);
        return "redirect:/employees";
    }
    

    12. 删除员工

    1. 添加删除按钮

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

    此处为a标签, 使用了btn的样子

    如果为button, 要绑定onclick

    2. 在controller中删除

    将前端传递的id在后端删除对应的employee

    由于删除不需要额外的信息提供, 因此不用跳转到专门的删除页面

    //删除员工
    @GetMapping("/deleteEmployee/{id}")
    public String deleteEmployee(@PathVariable("id")Integer id) {
        employeeDao.deleteEmployeeById(id);
        return "redirect:/employees";
    }
    

    13. 404处理

    在template下新建error文件夹, 在其中新建404.html即可

    其他错误与404类似, 修改名字即可

    14. 注销

    1. 设置注销按钮

    <a class="nav-link" th:href="@{/user/logout}">注销</a>
    

    2. 根据url设计controller

    package com.wang.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import javax.servlet.http.HttpSession;
    
    @Controller
    public class LogoutController {
    
        //移除loginUser字段
        @RequestMapping("/user/logout")
        public String logout(HttpSession session) {
            session.removeAttribute("loginUser");
            return "redirect:/index";
        }
    }
    
  • 相关阅读:
    修改服务器时间及时区
    风情万种awk
    追忆似水流年sed
    lvm笔记
    正则不怎么会用
    在CentOS7.5的虚拟环境下新建你的django项目
    Django学习过程中的排错总结
    我一直记不住的vim用法
    关于自建yum源拾遗
    Djangp2.x版本报错找不到模版目录下的文件
  • 原文地址:https://www.cnblogs.com/wang-sky/p/13706698.html
Copyright © 2011-2022 走看看