spring boot 尚桂谷学习笔记05 ---Web

------web 开发登录功能------

  修改login.html文件:注意加粗部分为 msg 字符串不为空时候 才进行显示

<!DOCTYPE html>
<!-- saved from url=(0050)http://getbootstrap.com/docs/4.0/examples/sign-in/ -->
<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="">
    <link rel="icon" href="http://getbootstrap.com/favicon.ico">

    <title>Signin Template for Bootstrap</title>

    <!-- Bootstrap core CSS -->
    <link href="/asserts/css/bootstrap.min.css" th:href="@{/webjars/bootstrap/4.0.0/css/bootstrap.css}" rel="stylesheet">

    <!-- Custom styles for this template -->
    <link href="/asserts/css/signin.css" th:href="@{/asserts/css/signin.css}" rel="stylesheet">
  </head>

  <body class="text-center">
    <form class="form-signin" th:action="@{/user/login}" method="post">
      <img class="mb-4" src="/asserts/img/bootstrap-solid.svg" th:src="@{/asserts/img/bootstrap-solid.svg}" alt="" width="72" height="72">
      <h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>
      <p style="color: red;" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
      <label for="username" class="sr-only" th:text="#{login.username}">Email address</label>
      <input name="username" type="email" id="username" th:placeholder="#{login.username}" class="form-control" placeholder="Email address" required="" autofocus="">
      <label for="inputPassword" th:text="#{login.password}" class="sr-only">Password</label>
      <input name="password" type="password" th:placeholder="#{login.password}" id="inputPassword" class="form-control" placeholder="Password" required="">
      <div class="checkbox mb-3">
        <label>
          <input type="checkbox" value="remember-me"/> [[#{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.html(l='zh_CN')}">中文</a>
        <a class="btn btn-sm" th:href="@{/index.html(l='en_US')}">English</a>
    </form>
</body></html>

  添加一个controller 对应页面跳转

package com.lixuchun.springboot.controller;

import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.Map;

@Controller
public class LoginController {

    // @RequestMapping(value = "/user/login", method = RequestMethod.POST)
    @PostMapping(value = "/user/login")
    public String login(@RequestParam String username, @RequestParam String password
            ,Map<String, Object> map) {
        if (!StringUtils.isEmpty(username) && "123456".equals(password)) {
            // 登录成功
            return "dashboard";
        } else {
            map.put("msg", "用户登录失败!");
            // 登录失败
            return "login";
        }
    }
}

  实现效果:填写正确情况下跳转到 dashboard.html页面中,错误情况下 返回login页面 并且显示 用户登录失败!

  登录 开发期间模板引擎页面修改以后要实时生效

    禁用模板引擎缓存:spring.thymeleaf.cache=false

    修改页面完成以后 ctrl + f9 重新编译

  当页面位于 dashboard 页面 按 F5 会有是否表单再次提交提示 (表单重复提交)

    可以进行重定向防止重复提交

     if (!StringUtils.isEmpty(username) && "123456".equals(password)) {
            // 登录成功
            // 防止表单从夫提交 可以从定向导主页
            return "redirect:/main.html";
        } else {
            map.put("msg", "用户登录失败!");
            // 登录失败
            return "login";
        }

    修改Mvc View视图解析器

    @Bean
    public WebMvcConfigurerAdapter webMvcConfigurerAdapter() {
        WebMvcConfigurerAdapter adapter = new WebMvcConfigurerAdapter() {
            @Override
            public void addViewControllers(ViewControllerRegistry registry) {
                registry.addViewController("/").setViewName("login");
                registry.addViewController("/index.html").setViewName("login");
                registry.addViewController("/main.html").setViewName("dashboard");
            }
        };
        return adapter;
    }

  如果这样修改了 直接访问 localhost:8080/main.html 就可以直接访问 登录功能没起到作用 那么引入拦截器

  拦截器 编写拦截器controller 必须实现 HandlerInterceptor

  pre 在登录之前进行检查:

package com.lixuchun.springboot.component;

import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

/**
 * 进行登录检查
 */
public class LoginHandlerIntercepter implements HandlerInterceptor{

    // 目标方法预检查
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        Object user = request.getSession().getAttribute("loginUser");
        if (user == null) {
            // 未登录 返回登录页面
            request.setAttribute("msg", "没有用户权限 请先登录");
       // 没有登录跳转到 /index.html 页面 request.getRequestDispatcher(
"/index.html").forward(request, response); return false; } else { // 已经登录 放行请求 return true; } } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { } }

  Mvc 配置文件添加 Interceptor 组件 进行注册:

    @Bean
    public WebMvcConfigurerAdapter webMvcConfigurerAdapter() {
        WebMvcConfigurerAdapter adapter = new WebMvcConfigurerAdapter() {
            @Override
            public void addViewControllers(ViewControllerRegistry registry) {
                registry.addViewController("/").setViewName("login");
                registry.addViewController("/index.html").setViewName("login");
                registry.addViewController("/main.html").setViewName("dashboard");
            }

            // 注册拦截器
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                // 拦截任意请求
                // 已经做好了静态资源的映射 *.css *.js 访问等 不需要做处理
                registry.addInterceptor(new LoginHandlerIntercepter()).addPathPatterns("/**")
                    .excludePathPatterns("/index.html", "/", "/user/login");
            }
        };
        return adapter;
    }

  访问效果:在没有登录的情况下 访问 localhost:8080/main.html

  登录后再次访问:左侧上面 [email protected] 为登录名称 dashboard 页面 [[${session.loginUser}]] 行内表达式取值

  CRUD-员工列表 

  实验要求: 

    1) RestfulCRUD: CRUD 满足Rest风格

    URI : /资源名称/资源标识  HTTP请求方式区分对资源的CRUD操作

       /emp/{id}

    

    2). 实验的请求架构

    

    

    3).员工列表

      抽取公共元素片段

        <div th:fragment="copy">&COPY 2011 thymes Virtual Grocery</div>

      引入公共元素片段

        <div th:insert="~{footer::copy}"></div>

        ~{templatename::selector} :模板名 :: 选择器

        ~{templatename::fragmentname}:模板名::片段名

      三种引入公共片段th属性:

        th:insert :将公共的片段整个插入到声明引用的div中

        th:replace: 将声明引入的元素替换为公共片段

        th:include:被引入的片段内容包含近这个标签中

        如果使用th:insert 等属性进行引入 可以不用写 ~{} 

        行内写法加上 [[~{}]] , [(~{})] (转义不转义)

      dashboard 页面定义公共片段头 th:fragment="topbar"

<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="http://getbootstrap.com/docs/4.0/examples/dashboard/#">[[${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" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">Sign out</a>
        </li>
      </ul>
    </nav>

      list 页面头取法 

<!-- 引入抽取的topbar -->
<!-- 模板名称:使用thymeleaf的配置规则进行解析 -->
<div th:replace="~{dashboard::topbar}"></div>

      dashboard 页面定义公共片段侧边栏 id="sideBar"

    <nav id="sideBar" class="col-md-2 d-none d-md-block bg-light sidebar" style="margin-top: 50px;">
          <div class="sidebar-sticky">
            <ul class="nav flex-column">
              <li class="nav-item">
                <a class="nav-link active" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                  <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>
                  Dashboard <span class="sr-only">(current)</span>
                </a>
              </li>
              <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                  <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="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                  <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 class="nav-link" href="#" th:href="@{/emps}">
                  <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>
            </ul>
          </div>
        </nav>

      list 页面侧边栏取法

<!-- 引入侧边栏 -->
<div th:replace="~{dashboard::#sideBar}"></div>

    也可以单独提出一个bar文件 然后在各个页面进行调用

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <!-- top bar -->
    <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="http://getbootstrap.com/docs/4.0/examples/dashboard/#">[[${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" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">Sign out</a>
            </li>
        </ul>
    </nav>

    <!-- side bar -->
    <nav id="sideBar" class="col-md-2 d-none d-md-block bg-light sidebar" style="margin-top: 50px;">
        <div class="sidebar-sticky">
            <ul class="nav flex-column">
                <li class="nav-item">
                    <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                        <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 class="nav-link" href="#" th:href="@{/emps}">
                        <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="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                        <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>
        </div>
    </nav>
</body>
</html>

    页面进行调用 list 页面 效果和之前的效果一样

<!-- 引入抽取的topbar -->
<!-- 模板名称:使用thymeleaf的配置规则进行解析 -->
<div th:replace="commons/bar::topbar"></div>
<!-- 引入侧边栏 -->
<div th:replace="commons/bar::#sideBar"></div>

    

  引入片段也可以传入参数:

    在 dashboard.html 页面引入左侧栏时候 传入参数

<div th:replace="commons/bar::#sideBar(activeUri='main.html')"></div>

    在 bar.html 页面设置左侧栏时候 通过传过来的参数设置 是否高亮

<li class="nav-item">
  <a class="nav-link active" href="#"
      th:href="@{/main.html}" th:class="${activeUri=='main.html'?'nav-link active':'nav-link'}">
        <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>
          Dashboard <span class="sr-only">(current)</span>
    </a>
</li>        

   

  员工列表做数据展示:

  list.html 页面编写

    <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; left: 0px; top: 0px; right: 0px; bottom: 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><button class="btn btn-sm btn-success">员工添加</button></h2> <h2>Section title</h2> <div class="table-responsive"> <table class="table table-striped table-sm"> <thead> <tr> <th>#</th> <th>lastName</th> <th>email</th> <th>gender</th> <th>department</th> <th>birth</th> <th>options</th> </tr> </thead> <tbody> <tr th:each="emp:${emps}"> <td th:text="${emp.id}"></td> <td>[[${emp.lastName}]]</td> <td th:text="${emp.email}"></td> <td th:text="${emp.gender}==0?'girl':'boy'"></td> <td th:text="${emp.department.departmentName}"></td> <td th:text="${#dates.format(emp.birth, 'yyyy-MM-dd HH:mm')}"></td> <td> <button class="btn btn-sm btn-primary">编辑员工</button> <button class="btn btn-sm btn-danger">删除员工</button> </td> </tr> </tbody> </table> </div> </main>

  做一个伪处理 employeeDao 

package com.lixuchun.springboot.dao;

import com.lixuchun.springboot.entities.Department;
import com.lixuchun.springboot.entities.Employee;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Repository
public class EmployeeDao {
    public Employee selectEmpById(Integer id) {
        return new Employee();
    }

    public List<Employee> selectEmps() {
        List<Employee> empList = new ArrayList<Employee>();
        for (int i = 0; i < 6; i++) {
            Employee emp = new Employee(i, "emp" + i,
                    i + "[email protected]", 0,
                    new Department(i, "dep"+ i), new Date());
            empList.add(emp);
        }
        return empList;
    }
}

  employee / department

department
    private Integer id;
    private String departmentName;

employee
    id
    lastName
    email
    gender
    department
    birth

  EmpController 编写

    @Autowired
    EmployeeDao employeeDao;

    // 查询所有员工返回列表页面
    @GetMapping("/emps")
    public String list(Model model) {
        List<Employee> employees = employeeDao.selectEmps();
        model.addAttribute("emps", employees);
        // classpath:/templates/xxx.html
        return "emp/list";
    }

  最后页面效果:

  员工添加功能:

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

    emp get 请求到员工添加页面

    emp post 添加员工

  

  其中部门为后台查出来的,前后台处理

 

<select class="form-control">
    <option th:value="${dept.id}" th:each="dept:${depts}" th:text="dept.departmentName"></option>
</select>

  点击添加按钮 post 到 emp为添加功能

<form ah:action="@{/emp}" method="post">

  员工添加controller

  修改日期格式:spring.mvc.date-format=yyyy-MM-dd

  员工修改:emp/id ------->get 方式

<a class="btn btn-sm btn-primary" th:href="@{/emp/} + ${emp.id}">编辑员工</a>

  页面需要回显:

    th:value="${emp!=null}?${emp.lastName}">

    th:checked="${emp!=null}?${emp.gender==1}" / gender==0

    th:selected="${emp!=null}?${dept.id==emp.department.id}"

  如何发送put请求,到员工修改controller

  删除:delete请求

   出现了按钮换行 因为 form的添加 所以进行修改

   设置按钮del_uri

    button 设置 :th:attr="del_uri=@{emp/} + ${emp.id}"

    form 设置:id="deleteEmpForm"

 

  最后效果:

猜你喜欢

转载自www.cnblogs.com/lixuchun/p/8976656.html