1.创建项目
Bootstrap下载模板:https://getbootstrap.com/docs/4.5/examples/
以下(不选-选填)
2.hello初建
package com.cevent.springboot.web.controller;/**
* Created by Cevent on 2020/7/8.
*/
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @author cevent
* @description
* @date 2020/7/8 0:01
*/
@Controller
public class HelloController {
@ResponseBody
@RequestMapping("/hello")
public String hello(){
return "hello cevent!";
}
}
导入静态资源
Springboot对静态资源的映射规则,所在位置
3.、所有 /webjars/** ,都去 classpath:/META-INF/resources/webjars/ 找资源
依赖链接地址:https://www.webjars.org/
引入jQuery链接:localhost:8080/webjars/jquery/3.3.1/jquery.js
引入jQuery链接:localhost:8080/webjars/jquery/3.3.1/jquery.js
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.3.1</version>
</dependency>
4.SpringBoot对静态资源的映射规则
localhost:8080/abc === 去静态资源文件夹里面找abc
访问路径:http://localhost:8080/asserts/js/Chart.min.js
欢迎页; 静态资源文件夹下的所有index.html页面;被"/**"映射;
访问:http://localhost:8080/
所有的 **/favicon.ico 都是在静态资源文件下找
5.模板引擎thymeleaf
访问success页面配置
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>success</title>
</head>
<body>
<h1>request mapping 成功!</h1>
</body>
</html>
6.HelloController
package com.cevent.springboot.web.controller;/**
* Created by Cevent on 2020/7/8.
*/
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @author cevent
* @description
* @date 2020/7/8 0:01
*/
@Controller
public class HelloController {
@ResponseBody
@RequestMapping("/hello")
public String hello(){
return "hello cevent!";
}
@RequestMapping("/success")
public String success(){
//默认跳转路径:classpath://templates/success.html
return "success";
}
}
7.引用thymeleaf获取属性
//查数据,页面显示,map的key对应页面的th:text=""key值,可索引到页面
@RequestMapping("/successdata")
public String thymeLeanData(Map<String , Object> map){
map.put("hello","你好:cevent!");
return "success";
}
【thymeleaf】
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>success</title>
</head>
<body>
<h1>request mapping 成功!</h1>
<!--th:text=""将div中的文本内容,谁知为controller的预设map值,th:id="${hello}"可替换为动态值 -->
<div id="div01" class="class01" th:id="${hello}" th:class="${hello}" th:text="${hello}">显示欢迎信息...</div>
</body>
</html>
【controller更改】
package com.cevent.springboot.web.controller;/**
* Created by Cevent on 2020/7/8.
*/
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Arrays;
import java.util.Map;
/**
* @author cevent
* @description
* @date 2020/7/8 0:01
*/
@Controller
public class HelloController {
@ResponseBody
@RequestMapping("/hello")
public String hello(){
return "hello cevent!";
}
@RequestMapping("/success")
public String success(){
//默认跳转路径:classpath://templates/success.html
return "success";
}
//查数据,页面显示,map的key对应页面的th:text=""key值,可索引到页面
@RequestMapping("/successdata")
public String thymeLeanData(Map<String , Object> map){
map.put("hello","<h1>你好:cevent!</h1>");
map.put("users", Arrays.asList("kk","MR","wz"));
return "success";
}
}
【thymeleaf属性】
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>success</title>
</head>
<body>
<h1>request mapping 成功!</h1>
<!--th:text=""将div中的文本内容,谁知为controller的预设map值,th:id="${hello}"可替换为动态值 -->
<div id="div01" class="class01" th:id="${hello}" th:class="${hello}" th:text="${hello}">显示欢迎信息...</div>
<hr />
<div th:text="${hello}">转译-字符串</div>
<div th:utext="${hello}">不转译字符-h1</div>
<hr />
<!--th:each每次遍历都会生成当前标签:3个h4-->
<!--/*@thymesVar id="users" type="ch"*/-->
<h4 th:text="${user}" th:each="user:${users}"></h4>
<hr/>
<h5>
<span th:each="user:${users}" >
[[${user}]]
</span>
</h5>
</body>
</html>
8.开始项目-引入资源
8.1.entity-employee
package com.cevent.springboot.web.entity;/**
* Created by Cevent on 2020/7/8.
*/
import java.util.Date;
/**
* @author cevent
* @description
* @date 2020/7/8 15:24
*/
public class Employee {
private Integer id;
private String lastName;
private String email;
//male:1 female:0
private Integer gender;
private Department department;
private Date birth;
public Employee() {
}
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.birth = birth;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", lastName='" + lastName + '\'' +
", email='" + email + '\'' +
", gender=" + gender +
", department=" + department +
", birth=" + birth +
'}';
}
}
8.2entity-department
package com.cevent.springboot.web.entity;/**
* Created by Cevent on 2020/7/8.
*/
/**
* @author cevent
* @description
* @date 2020/7/8 15:23
*/
public class Department {
private Integer id;
private String deptNmme;
public Department() {
}
public Department(Integer id, String deptNmme) {
this.id = id;
this.deptNmme = deptNmme;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDeptNmme() {
return deptNmme;
}
public void setDeptNmme(String deptNmme) {
this.deptNmme = deptNmme;
}
@Override
public String toString() {
return "Department{" +
"id=" + id +
", deptNmme='" + deptNmme + '\'' +
'}';
}
}
8.3dao-employeeDao
package com.cevent.springboot.web.dao;/**
* Created by Cevent on 2020/7/8.
*/
import com.cevent.springboot.web.entity.Department;
import com.cevent.springboot.web.entity.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;
/**
* @author cevent
* @description
* @date 2020/7/8 15:20
*/
@Repository
public class EmployeeDao {
private static Map<Integer, Employee> employees=null;
@Autowired
private DepartmentDao departmentDao;
static {
employees=new HashMap<Integer, Employee>();
employees.put(2001, new Employee(2001, "E-AA", "aa@163.com", 1, new Department(101, "D-AA")));
employees.put(2002, new Employee(2002, "E-BB", "bb@163.com", 1, new Department(102, "D-BB")));
employees.put(2003, new Employee(2003, "E-CC", "cc@163.com", 0, new Department(103, "D-CC")));
employees.put(2004, new Employee(2004, "E-DD", "dd@163.com", 0, new Department(104, "D-DD")));
employees.put(2005, new Employee(2005, "E-EE", "ee@163.com", 1, new Department(105, "D-EE")));
}
private static Integer initId=2020;
public void save(Employee employee){
if(employee.getId()==null){
employee.setId(initId++);
}
employee.setDepartment(departmentDao.getDepartment(employee.getDepartment().getId()));
employees.put(employee.getId(),employee);
}
public Collection<Employee> getAll(){
return employees.values();
}
public Employee get(Integer id){
return employees.get(id);
}
public void delete(Integer id){
employees.remove(id);
}
}
8.4dao-departmentDao
package com.cevent.springboot.web.dao;/**
* Created by Cevent on 2020/7/8.
*/
import com.cevent.springboot.web.entity.Department;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* @author cevent
* @description
* @date 2020/7/8 15:20
*/
@Repository
public class DepartmentDao {
private static Map<Integer, Department> departments=null;
static {
departments=new HashMap<Integer, Department>();
departments.put(101, new Department(101, "D-AA"));
departments.put(102, new Department(102, "D-BB"));
departments.put(103, new Department(103, "D-CC"));
departments.put(104, new Department(104, "D-DD"));
departments.put(105, new Department(105, "D-EE"));
}
public Collection<Department> getDepartments(){
return departments.values();
}
public Department getDepartment(Integer id){
return departments.get(id);
}
}
8.5hello@Controller
package com.cevent.springboot.web.controller;/**
* Created by Cevent on 2020/7/8.
*/
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Arrays;
import java.util.Map;
/**
* @author cevent
* @description
* @date 2020/7/8 0:01
*/
@Controller
public class HelloController {
@ResponseBody
@RequestMapping("/hello")
public String hello(){
return "hello cevent!";
}
@RequestMapping("/success")
public String success(){
//默认跳转路径:classpath://templates/success.html
return "success";
}
//查数据,页面显示,map的key对应页面的th:text=""key值,可索引到页面
@RequestMapping("/successdata")
public String thymeLeanData(Map<String , Object> map){
map.put("hello","<h1>你好:cevent!</h1>");
map.put("users", Arrays.asList("kk","MR","wz"));
return "success";
}
//配置thymelead模板引擎自动加载的路径 {"/","/index.html"} 访问当前项目,或者访问路径都进入指定页面
/* @RequestMapping({"/","/index.html"})
public String index(){
return "index";
}*/
}
8.6@configuration
package com.cevent.springboot.web.config;/**
* Created by Cevent on 2020/7/8.
*/
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.config.annotation.*;
/** 全局配置类:继承WebMvcConfigurationSupport,可以扩展springMVC的方法
* @author cevent
* @description
* @date 2020/7/8 14:53
* @EnableWebMvc 启动后,springboot的springmvc自动配置全部失效
* @Configuration 必须关闭才能不阻塞自动配置的index寻找路径,这里配置的跳转不能使用
*/
//@EnableWebMvc
@Configuration
public class MyMVCConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//super.addViewControllers(registry);
//浏览器发送cevent请求,响应转发success页面
registry.addViewController("/cevent").setViewName("success");
}
//全部组件跳转作用,@Bean
@Bean
public WebMvcConfigurerAdapter webMvcConfigurerAdapter(){
WebMvcConfigurerAdapter adapter=new WebMvcConfigurerAdapter(){
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
registry.addViewController("/login.html").setViewName("login");
}
};
return adapter;
}
}
8.7 main-class解析器
package com.cevent.springboot.web;
import ch.qos.logback.core.net.SyslogOutputStream;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import java.util.Locale;
@SpringBootApplication
public class SpringBoot09WebRestfulCrudApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBoot09WebRestfulCrudApplication.class, args);
}
//自动解析器
@Bean
public ViewResolver myNegotiateViewResolve(){
System.out.println( "创建了视图解析器My Negotiation View Resolver!");
return new MyNegotiateViewResolver();
}
private static class MyNegotiateViewResolver implements ViewResolver{
@Override
public View resolveViewName(String viewName, Locale locale) throws Exception {
return null;
}
}
}
8.8 login.html
<!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="@{/webjars/bootstrap/4.5.0/css/bootstrap.css}" rel="stylesheet">
<!-- Custom styles for this template -->
<link th:href="@{/asserts/css/signin.css}" rel="stylesheet">
</head>
<body class="text-center">
<form class="form-signin" action="dashboard.html">
<img class="mb-4" th:src="@{/asserts/img/yameng-logo.png}" alt="" width="150" height="150">
<h1 class="h3 mb-3 font-weight-normal">亚盟后台管理系统</h1>
<label class="sr-only">用户名</label>
<input type="text" class="form-control" placeholder="用户名" required="" autofocus="">
<label class="sr-only">密码</label>
<input type="password" class="form-control" placeholder="密码" required="">
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me"> 保存账户/密码
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">登陆</button>
<p class="mt-5 mb-3 text-muted">© 2020</p>
<a class="btn btn-sm">中文</a>
<a class="btn btn-sm">English</a>
</form>
</body>
</html>
8.9 application.yml配置
application.yml配置
##配置了访问路径后,原自动访问路径取消
#spring:
# resources:
# static-locations: classpath://hello,classpath://cevent/
##修改项目名,th语法(thymeleaf)设置路径可以保证绝对路径正确
server:
servlet:
context-path: /ceventcrud
8.10 pom.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.cevent</groupId>
<artifactId>spring-boot-09-web-restful-crud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-09-web-restful-crud</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--引入web模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--1.已进入jquery-webjars-->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.3.1</version>
</dependency>
<!--2.引入模板引擎-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--3.引入bootstap-->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>4.5.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
9.启动报错注意,调整controller和configuration
2020-07-08 16:36:46.199 INFO 20296 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2020-07-08 16:36:46.207 INFO 20296 --- [ main] .w.SpringBoot09WebRestfulCrudApplication : Started SpringBoot09WebRestfulCrudApplication in 1.129 seconds (JVM running for 2.267)
2020-07-08 16:36:48.596 INFO 20296 --- [nio-8080-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-07-08 16:36:48.596 INFO 20296 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2020-07-08 16:36:48.599 INFO 20296 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Completed initialization in 3 ms
2020-07-08 16:36:48.606 WARN 20296 --- [nio-8080-exec-2] o.s.web.servlet.PageNotFound : No mapping for GET /
2020-07-08 16:36:49.390 WARN 20296 --- [nio-8080-exec-3] o.s.web.servlet.PageNotFound : No mapping for GET /
2020-07-08 16:36:50.275 WARN 20296 --- [nio-8080-exec-4] o.s.web.servlet.PageNotFound : No mapping for GET /
2020-07-08 16:37:42.231 WARN 20296 --- [nio-8080-exec-5] o.s.web.servlet.PageNotFound : No mapping for GET /index
2020-07-08 16:37:47.185 WARN 20296 --- [nio-8080-exec-1] o.s.web.servlet.PageNotFound : No mapping for GET /index.html
WebMvcConfigurerAdapter 与WebMvcConfigurationSupport区别(待补充)
实现:http://localhost:8080/ceventcrud/ 或者 http://localhost:8080/ceventcrud/login.html
10.idea自动识别国际化properties文件
yml配置
##配置了访问路径后,原自动访问路径取消
#spring:
# resources:
# static-locations: classpath://hello,classpath://cevent/
##修改项目名,th语法(thymeleaf)设置路径可以保证绝对路径正确
server:
servlet:
context-path: /ceventcrud
##配置国际化
spring:
messages:
basename: i18n.login
去页面获取国际化的值
<!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="@{/webjars/bootstrap/4.5.0/css/bootstrap.css}" rel="stylesheet">
<!-- Custom styles for this template -->
<link th:href="@{/asserts/css/signin.css}" rel="stylesheet">
</head>
<body class="text-center">
<form class="form-signin" action="dashboard.html">
<img class="mb-4" th:src="@{/asserts/img/yameng-logo.png}" alt="" width="150" height="150">
<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in YaMeng E-Commerce Manager</h1>
<label class="sr-only" th:text="#{login.username}">Username</label>
<input type="text" class="form-control" placeholder="用户名" required="" autofocus="">
<label class="sr-only" th:text="#{login.password}">Password</label>
<input type="password" class="form-control" placeholder="密码" required="">
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me" /> [[#{login.rememberme}]]
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.submit}">Sign in</button>
<p class="mt-5 mb-3 text-muted">© 2020</p>
<a class="btn btn-sm">中文</a>
<a class="btn btn-sm">English</a>
</form>
</body>
</html>
11.排除浏览器乱码
11.1file-settings
11.2全局默认配置file-other srttings,idea2020取消了other,这里可以这样设置
11.3浏览器更改语言
11.4修改页面
<!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="@{/webjars/bootstrap/4.5.0/css/bootstrap.css}" rel="stylesheet">
<!-- Custom styles for this template -->
<link th:href="@{/asserts/css/signin.css}" rel="stylesheet">
</head>
<body class="text-center">
<form class="form-signin" action="dashboard.html">
<img class="mb-4" th:src="@{/asserts/img/yameng-logo.png}" alt="" width="150" height="150">
<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in YaMeng E-Commerce Manager</h1>
<label class="sr-only" th:text="#{login.username}">Username</label>
<input type="text" class="form-control" placeholder="用户名" required="" autofocus="">
<label class="sr-only" th:text="#{login.password}">Password</label>
<input type="password" class="form-control" placeholder="密码" required="">
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me" /> [[#{login.rememberme}]]
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.submit}">Sign in</button>
<p class="mt-5 mb-3 text-muted">© 2020</p>
<a class="btn btn-sm" th:href="@{/login.html(l='zh_CH')}">中文</a>
<a class="btn btn-sm" th:href="@{/login.html(l='en_US')}">English</a>
</form>
</body>
</html>
12.MyLocaleResolver
package com.cevent.springboot.web.component;
/*
* Created by Cevent on 2020/7/8.
*/
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;
/** 链接上携带国家信息
* @author cevent
* @description
* @date 2020/7/8 22:05
*/
public class MyLocaleResolver implements LocaleResolver {
//解析国家信息
@Override
public Locale resolveLocale(HttpServletRequest request) {
String lang=request.getParameter("l");
Locale locale=null;
if(!StringUtils.isEmpty(lang)){
String[] split=lang.split("_");
locale=new Locale(split[0],split[1]);
}
return locale;
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
}
}
13.MyMVCConfig
package com.cevent.springboot.web.config;/**
* Created by Cevent on 2020/7/8.
*/
import com.cevent.springboot.web.component.MyLocaleResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.*;
/** 全局配置类:继承WebMvcConfigurationSupport,可以扩展springMVC的方法
* @author cevent
* @description
* @date 2020/7/8 14:53
* @EnableWebMvc 启动后,springboot的springmvc自动配置全部失效
* @Configuration 必须关闭才能不阻塞自动配置的index寻找路径,这里配置的跳转不能使用
*/
//@EnableWebMvc
@Configuration
public class MyMVCConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//super.addViewControllers(registry);
//浏览器发送cevent请求,响应转发success页面
registry.addViewController("/cevent").setViewName("success");
}
//全部组件跳转作用,@Bean
@Bean
public WebMvcConfigurerAdapter webMvcConfigurerAdapter(){
WebMvcConfigurerAdapter adapter=new WebMvcConfigurerAdapter(){
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
registry.addViewController("/login.html").setViewName("login");
}
};
return adapter;
}
//语言配置
@Bean
public LocaleResolver localResolver(){
return new MyLocaleResolver();
}
}
14.运行报错Error:(1, 1) java: 非法字符: ‘\ufeff’
Error:(1, 10) java: 需要class, interface或enum
编辑器里右键remobe BOM
15.登录拦截器
15.1设置页面post-action
<form class="form-signin" action="dashboard.html" th:action="@{user/login}" method="post">
15.2loginController
package com.cevent.springboot.web.controller;/**
* Created by Cevent on 2020/7/8.
*/
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpSession;
import java.util.Map;
/**
* @author cevent
* @description
* @date 2020/7/8 22:45
*/
@Controller
public class LoginController {
//为简化SpringMVC写法
//@RequestMapping(value="/user/login",method = RequestMethod.POST)
@PostMapping(value = "/user/login")
public String login(
@RequestParam("username") String username,
@RequestParam("password") String password,
Map<String,Object> errorMap,
HttpSession session //记录登录用户session
){
if(!StringUtils.isEmpty(username) && "cevent".equals(password)){
//记录数据传给LoginHandler
session.setAttribute("loginUser",username);
//防止重复提交,重定向
//登录成功
return "redirect:/main.html";
}else{
errorMap.put("msg","用户名/密码错误");
return "login";
}
}
}
15.3loginHandlerInterceptor
loginHandlerInterceptor
package com.cevent.springboot.web.component;/**
* Created by Cevent on 2020/7/8.
*/
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author cevent
* @description
* @date 2020/7/8 23:16
*/
/**
* 登录检查拦截
*/
public class LoginHandlerIntecepter 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","您没有权限进入后台,请先登录");
request.getRequestDispatcher("/login.html").forward(request,response);
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 {
}
}
15.4mvcConfig
package com.cevent.springboot.web.config;/**
* Created by Cevent on 2020/7/8.
*/
import com.cevent.springboot.web.component.LoginHandlerIntecepter;
import com.cevent.springboot.web.component.MyLocaleResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.*;
/** 全局配置类:继承WebMvcConfigurationSupport,可以扩展springMVC的方法
* @author cevent
* @description
* @date 2020/7/8 14:53
* @EnableWebMvc 启动后,springboot的springmvc自动配置全部失效
* @Configuration 必须关闭才能不阻塞自动配置的index寻找路径,这里配置的跳转不能使用
*/
//@EnableWebMvc
@Configuration
public class MyMVCConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//super.addViewControllers(registry);
//浏览器发送cevent请求,响应转发success页面
registry.addViewController("/cevent").setViewName("success");
}
//全部组件跳转作用,@Bean
@Bean
public WebMvcConfigurerAdapter webMvcConfigurerAdapter() {
WebMvcConfigurerAdapter adapter = new WebMvcConfigurerAdapter() {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
registry.addViewController("/login.html").setViewName("login");
//模板引擎解析:添加视图重定向
registry.addViewController("/main.html").setViewName("dashboard");
}
//注册拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
//拦截任意路径下的请求/**
registry.addInterceptor(new LoginHandlerIntecepter()).addPathPatterns("/**")
.excludePathPatterns("/login.html","/","/user/login");
}
//springboot已经做了静态资源映射,css、js自动拦截
};
return adapter;
}
//语言配置
@Bean
public LocaleResolver localResolver(){
return new MyLocaleResolver();
}
}
15.5login.html
login.html
<!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="@{/webjars/bootstrap/4.5.0/css/bootstrap.css}" rel="stylesheet">
<!-- Custom styles for this template -->
<link th:href="@{/asserts/css/signin.css}" rel="stylesheet">
</head>
<body class="text-center">
<form class="form-signin" action="dashboard.html" th:action="@{/user/login}" method="post">
<img class="mb-4" th:src="@{/asserts/img/yameng-logo.png}" alt="" width="150" height="150">
<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in YaMeng E-Commerce Manager</h1>
<!--重新编译页面代码:ctrl+f9 判断,msg不为空的时候才出现-->
<label class="sr-only" th:text="#{login.username}">Username</label>
<p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
<input type="text" class="form-control" name="username" placeholder="用户名" required="" autofocus="">
<label class="sr-only" th:text="#{login.password}">Password</label>
<input type="password" class="form-control" name="password" placeholder="密码" required="">
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="rememberme" /> [[#{login.rememberme}]]
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.submit}">Sign in</button>
<p class="mt-5 mb-3 text-muted">© 2020</p>
<a class="btn btn-sm" th:href="@{/login.html(l='zh_CH')}">中文</a>
<a class="btn btn-sm" th:href="@{/login.html(l='en_US')}">English</a>
</form>
</body>
</html>
15.6 dashboard.html
<!DOCTYPE html>
<!-- saved from url=(0052)http://getbootstrap.com/docs/4.0/examples/dashboard/ -->
<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>Dashboard Template for Bootstrap</title>
<!-- Bootstrap core CSS -->
<link href="./asserts/css/bootstrap.min.css" th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="./asserts/css/dashboard.css" th:href="@{/asserts/css/dashboard.css}" rel="stylesheet">
<style type="text/css">
/* Chart.js */
@-webkit-keyframes chartjs-render-animation {
from {
opacity: 0.99
}
to {
opacity: 1
}
}
@keyframes chartjs-render-animation {
from {
opacity: 0.99
}
to {
opacity: 1
}
}
.chartjs-render-monitor {
-webkit-animation: chartjs-render-animation 0.001s;
animation: chartjs-render-animation 0.001s;
}
</style>
</head>
<body>
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0">
<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>
<div class="container-fluid">
<div class="row">
<nav class="col-md-2 d-none d-md-block bg-light sidebar">
<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>
</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="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-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="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-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>
</ul>
</div>
</nav>
<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>
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
<h1 class="h2">Dashboard</h1>
<div class="btn-toolbar mb-2 mb-md-0">
<div class="btn-group mr-2">
<button class="btn btn-sm btn-outline-secondary">Share</button>
<button class="btn btn-sm btn-outline-secondary">Export</button>
</div>
<button class="btn btn-sm btn-outline-secondary dropdown-toggle">
<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-calendar"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line></svg>
This week
</button>
</div>
</div>
<canvas class="my-4 chartjs-render-monitor" id="myChart" width="1076" height="454" style="display: block; width: 1076px; height: 454px;"></canvas>
</main>
</div>
</div>
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script type="text/javascript" src="asserts/js/jquery-3.2.1.slim.min.js" ></script>
<script type="text/javascript" src="asserts/js/popper.min.js" ></script>
<script type="text/javascript" src="asserts/js/bootstrap.min.js" ></script>
<!-- Icons -->
<script type="text/javascript" src="asserts/js/feather.min.js" ></script>
<script>
feather.replace()
</script>
<!-- Graphs -->
<script type="text/javascript" src="asserts/js/Chart.min.js" ></script>
<script>
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
datasets: [{
data: [15339, 21345, 18483, 24003, 23489, 24092, 12034],
lineTension: 0,
backgroundColor: 'transparent',
borderColor: '#007bff',
borderWidth: 4,
pointBackgroundColor: '#007bff'
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: false
}
}]
},
legend: {
display: false,
}
}
});
</script>
</body>
</html>
16 员工列表
16.1 员工列表抽取顶部栏(dashboard)
<body>
<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)
<body>
<!--引用topbar
模板名:使用thymeleaf的前后缀配置规则进行解析
-->
<div th:insert="~{dashboard::topbar}"></div>
真正抽取
<body>
<!--引用topbar
模板名:使用thymeleaf的前后缀配置规则进行解析
-->
<!-- <div th:insert="~{dashboard::topbar}"></div>-->
<div th:replace="dashboard::topbar"></div>
侧边栏(dashboard)
<div class="container-fluid">
<div class="row">
<!--抽取侧边栏,除了fragment,也可以用选择器,添加id即可-->
<nav class="col-md-2 d-none d-md-block bg-light sidebar" th:fragment="" id="sideBar">
<div class="sidebar-sticky">
引入侧边栏
<body>
<!--引用topbar
模板名:使用thymeleaf的前后缀配置规则进行解析
-->
<!-- <div th:insert="~{dashboard::topbar}"></div>-->
<div th:replace="dashboard::topbar"></div>
<div class="container-fluid">
<div class="row">
<!--引入侧边栏-->
<div th:replace="~{dashboard::#sideBar}"></div>
16.2 引入片段的时候传入active点亮参数
(bar页面配置引入标签时的active)
<!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>
<!--sidebar-->
<!--抽取侧边栏,除了fragment,也可以用选择器,添加id即可-->
<nav class="col-md-2 d-none d-md-block bg-light sidebar" th:fragment="" id="sideBar">
<div class="sidebar-sticky">
<ul class="nav flex-column">
<li class="nav-item">
<!--实现动态高亮-->
<a class="nav-link active"
th:class="${activeURI=='main.html'?'nav-link active':'nav-link'}"
href="#" th:href="@{/main.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>
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 active" th:href="@{/emps}" th:class="${activeURI=='emps'?'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-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-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="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>
<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="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-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="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-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="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-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="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-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="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-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>
</body>
</html>
16.3Dashboard页面
<body>
<!--1.引入commons-topbar-->
<div th:replace="commons/bar::topbar"></div>
<div class="container-fluid">
<div class="row">
<!--2.引入commons-sidebar-->
<div th:replace="commons/bar::#sideBar(activeURI='main.html')"></div>
List页面
<body>
<!--引用topbar
模板名:使用thymeleaf的前后缀配置规则进行解析
-->
<!-- <div th:insert="~{dashboard::topbar}"></div>-->
<div th:replace="commons/bar::topbar"></div>
<div class="container-fluid">
<div class="row">
<!--引入侧边栏-->
<div th:replace="~{commons/bar::#sideBar(activeURI='emps')}"></div>
16.4引入员工列表
(1)employeeDao
//获取所有员工
public Employee get(Integer id){
return employees.get(id);
}
(2)empController
package com.cevent.springboot.web.controller;/**
* Created by Cevent on 2020/7/9.
*/
import com.cevent.springboot.web.dao.EmployeeDao;
import com.cevent.springboot.web.entity.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.Collection;
/**
* @author cevent
* @description
* @date 2020/7/9 21:15
*/
@Controller
public class EmployeeController {
@Autowired
EmployeeDao employeeDao;
//1.查询所有员工,返回列表页面
@GetMapping("/emps")
public String empList(Model model){
Collection<Employee> empsCollection= employeeDao.getAll();
//将获取的员工信息,放在请求域中
model.addAttribute("emps",empsCollection);
//根据thymeleaf框架默认拼串: classpath:/templates/ "xxx" .html
return "emps/list";
}
}
(3)list
<!DOCTYPE html>
<!-- 引入th命名空间 -->
<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>Dashboard Template for Bootstrap</title>
<!-- Bootstrap core CSS -->
<link href="../../static/asserts/css/bootstrap.min.css" th:href="@{/webjars/bootstrap/4.5.0/css/bootstrap.css}" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="../../static/asserts/css/dashboard.css" th:href="@{/asserts/css/dashboard.css}" rel="stylesheet">
<style type="text/css">
/* Chart.js */
@-webkit-keyframes chartjs-render-animation {
from {
opacity: 0.99
}
to {
opacity: 1
}
}
@keyframes chartjs-render-animation {
from {
opacity: 0.99
}
to {
opacity: 1
}
}
.chartjs-render-monitor {
-webkit-animation: chartjs-render-animation 0.001s;
animation: chartjs-render-animation 0.001s;
}
</style>
</head>
<body>
<!--引用topbar
模板名:使用thymeleaf的前后缀配置规则进行解析
-->
<!-- <div th:insert="~{dashboard::topbar}"></div>-->
<div th:replace="commons/bar::topbar"></div>
<div class="container-fluid">
<div class="row">
<!--引入侧边栏-->
<div th:replace="~{commons/bar::#sideBar(activeURI='emps')}"></div>
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
<h2>
<button class="btn btn-sm btn-success">员工添加</button>
</h2>
<div class="table-responsive">
<table class="table table-striped table-sm">
<thead>
<tr>
<th>员工ID</th>
<th>姓名</th>
<th>邮箱</th>
<th>性别</th>
<th>部门</th>
<th>生日</th>
<th>操作</th>
</tr>
</thead>
<!--更换tbody-->
<tbody>
<tr th:each="emp:${emps}">
<td th:text="${emp.id}"></td>
<td>[[${emp.lastName}]]</td>
<td th:text="${emp.email}"></td>
<!--判断显示,不推荐将REX写在大括号内-->
<!--<td th:text="${emp.gender==0?'女':'男'}"></td>-->
<td th:text="${emp.gender}==0?'女':'男'"></td>
<td th:text="${emp.department.deptNmme}"></td>
<!--格式化date-->
<td th:text="${#dates.format(emp.birth,'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>
</div>
</main>
</div>
</div>
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script type="text/javascript" src="../../static/asserts/js/jquery-3.2.1.slim.min.js"></script>
<script type="text/javascript" src="../../static/asserts/js/popper.min.js"></script>
<script type="text/javascript" src="../../static/asserts/js/bootstrap.min.js"></script>
<!-- Icons -->
<script type="text/javascript" src="../../static/asserts/js/feather.min.js"></script>
<script>
feather.replace()
</script>
<!-- Graphs -->
<script type="text/javascript" src="../../static/asserts/js/Chart.min.js"></script>
<script>
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
datasets: [{
data: [15339, 21345, 18483, 24003, 23489, 24092, 12034],
lineTension: 0,
backgroundColor: 'transparent',
borderColor: '#007bff',
borderWidth: 4,
pointBackgroundColor: '#007bff'
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: false
}
}]
},
legend: {
display: false,
}
}
});
</script>
</body>
</html>
17.添加员工
17.1bootstrap获取静态表单
https://getbootstrap.com/docs/4.5/components/forms/
<form>
<div class="form-group">
<label for="exampleFormControlInput1">Email address</label>
<input type="email" class="form-control" id="exampleFormControlInput1" placeholder="name@example.com">
</div>
<div class="form-group">
<label for="exampleFormControlSelect1">Example select</label>
<select class="form-control" id="exampleFormControlSelect1">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
</div>
<div class="form-group">
<label for="exampleFormControlSelect2">Example multiple select</label>
<select multiple class="form-control" id="exampleFormControlSelect2">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
</div>
<div class="form-group">
<label for="exampleFormControlTextarea1">Example textarea</label>
<textarea class="form-control" id="exampleFormControlTextarea1" rows="3"></textarea>
</div>
</form>
17.2添加页面add
添加页面add
<!DOCTYPE html>
<!-- 引入th命名空间 -->
<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>Dashboard Template for Bootstrap</title>
<!-- Bootstrap core CSS -->
<link href="../../static/asserts/css/bootstrap.min.css" th:href="@{/webjars/bootstrap/4.5.0/css/bootstrap.css}" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="../../static/asserts/css/dashboard.css" th:href="@{/asserts/css/dashboard.css}" rel="stylesheet">
<style type="text/css">
/* Chart.js */
@-webkit-keyframes chartjs-render-animation {
from {
opacity: 0.99
}
to {
opacity: 1
}
}
@keyframes chartjs-render-animation {
from {
opacity: 0.99
}
to {
opacity: 1
}
}
.chartjs-render-monitor {
-webkit-animation: chartjs-render-animation 0.001s;
animation: chartjs-render-animation 0.001s;
}
</style>
</head>
<body>
<!--引用topbar
模板名:使用thymeleaf的前后缀配置规则进行解析
-->
<!-- <div th:insert="~{dashboard::topbar}"></div>-->
<div th:replace="commons/bar::topbar"></div>
<div class="container-fluid">
<div class="row">
<!--引入侧边栏-->
<div th:replace="~{commons/bar::#sideBar(activeURI='emps')}"></div>
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
<h2 class="btn btn-sm btn-success" >添加员工信息
</h2>
<form th:action="@{/emp}" method="post">
<div class="form-group">
<label >员工-姓名</label>
<!--name=jave bean de 定义name-->
<input name="lastName" type="text" class="form-control" id="exampleFormControlInput1" placeholder="cevent">
</div>
<div class="form-group">
<label >员工-邮箱</label>
<input name="email" type="email" class="form-control" id="exampleFormControlInput2" placeholder="1540001771@qq.com">
</div>
<div class="form-group">
<label >员工-性别</label>
<div class="form-check form-check-inline">
<input name="gender" value="1" class="form-check-input" type="radio"/>
<label class="form-check-label">男</label>
</div>
<div class="form-check form-check-inline">
<input name="gender" value="0" class="form-check-input" type="radio"/>
<label class="form-check-label">女</label>
</div>
</div>
<div class="form-group">
<label >所属-部门</label>
<!-- multiple全显示options <select multiple class="form-control" id="exampleFormControlSelect2"> -->
<select class="form-control" name="department.id">
<!--提交为部门id-->
<option th:each="dept:${dept}" th:text="${dept.deptName}" th:value="${dept.id}"></option>
</select>
</div>
<div class="form-group">
<label >员工-生日</label>
<input name="birth" type="text" class="form-control" id="exampleFormControlInput3" placeholder="cevent">
</div>
<button type="submit" class="btn btn-primary">添加</button>
</form>
</main>
</div>
</div>
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script type="text/javascript" src="../../static/asserts/js/jquery-3.2.1.slim.min.js" th:src="@{/webjars/jquery/3.3.1/jquery.js}"></script>
<script type="text/javascript" src="../../static/asserts/js/popper.min.js" th:src="@{/webjars/popper.js/1.11.1/dist/popper.js}"></script>
<script type="text/javascript" src="../../static/asserts/js/bootstrap.min.js" th:src="@{/webjars/bootstrap/4.0.0/js/bootstrap.js}"></script>
<!-- Icons -->
<script type="text/javascript" src="../../static/asserts/js/feather.min.js" th:src="@{/asserts/js/feather.min.js}"></script>
<script>
feather.replace()
</script>
</body>
</html>
17.3empController
package com.cevent.springboot.web.controller;/**
* Created by Cevent on 2020/7/9.
*/
import com.cevent.springboot.web.dao.DepartmentDao;
import com.cevent.springboot.web.dao.EmployeeDao;
import com.cevent.springboot.web.entity.Department;
import com.cevent.springboot.web.entity.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.Collection;
/**
* @author cevent
* @description
* @date 2020/7/9 21:15
*/
@Controller
public class EmployeeController {
@Autowired
EmployeeDao employeeDao;
@Autowired
DepartmentDao departmentDao;
//1.查询所有员工,返回列表页面
@GetMapping("/emps")
public String empList(Model model){
Collection<Employee> empsCollection= employeeDao.getAll();
//将获取的员工信息,放在请求域中
model.addAttribute("emps",empsCollection);
//根据thymeleaf框架默认拼串: classpath:/templates/ "xxx" .html
return "emps/list";
}
//2.到添加员工页面
@GetMapping("/emp")
public String toAddEMPPage(Model model){
//2.1先查出所有部门,页面显示再选择
Collection<Department> depts=departmentDao.getDepartments();
model.addAttribute("dept",depts);
return "emps/add";
}
//3.员工添加,SpringMVC自动将请求参数(name)和入参对象的属性名(javaBean)进行一一绑定
@PostMapping("/emp")
public String addEMP(Employee employee){
//打印add员工信息
System.out.println("新建的员工信息:"+employee);
//1.添加保存员工
employeeDao.save(employee);
//返回员工列表页面,redirect:重定向到地址,forward:转发到地址
return "redirect:/emps";
}
}
17.4日期格式yml配置
日期格式yml配置
##配置了访问路径后,原自动访问路径取消
#spring:
# resources:
# static-locations: classpath://hello,classpath://cevent/
##修改项目名,th语法(thymeleaf)设置路径可以保证绝对路径正确
server:
servlet:
context-path: /ceventcrud
##配置国际化,禁用模板引擎缓存thymeleaf.cache,指定日期格式mvc.format.date
#date-time: yyyy-MM-dd HH:mm:ss
spring:
messages:
basename: i18n.login
thymeleaf:
cache: false
mvc:
format:
date: yyyy-MM-dd
18. 员工修改
18.1修改list页面
<!--更换tbody-->
<tbody>
<tr th:each="emp:${emps}">
<td th:text="${emp.id}"></td>
<td>[[${emp.lastName}]]</td>
<td th:text="${emp.email}"></td>
<!--判断显示,不推荐将REX写在大括号内-->
<!--<td th:text="${emp.gender==0?'女':'男'}"></td>-->
<td th:text="${emp.gender}==0?'女':'男'"></td>
<td th:text="${emp.department.deptName}"></td>
<!--格式化date-->
<td th:text="${#dates.format(emp.birth,'yyyy-MM-dd HH:mm:ss')}"></td>
<td>
<a class="btn btn-sm btn-primary" th:href="@{/emp/}+${emp.id}">编辑</a>
<button class="btn btn-sm btn-danger">删除</button>
</td>
带入员工id
18.2修改add页面
修改add页面
<!DOCTYPE html>
<!-- 引入th命名空间 -->
<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>Dashboard Template for Bootstrap</title>
<!-- Bootstrap core CSS -->
<link href="../../static/asserts/css/bootstrap.min.css" th:href="@{/webjars/bootstrap/4.5.0/css/bootstrap.css}" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="../../static/asserts/css/dashboard.css" th:href="@{/asserts/css/dashboard.css}" rel="stylesheet">
<style type="text/css">
/* Chart.js */
@-webkit-keyframes chartjs-render-animation {
from {
opacity: 0.99
}
to {
opacity: 1
}
}
@keyframes chartjs-render-animation {
from {
opacity: 0.99
}
to {
opacity: 1
}
}
.chartjs-render-monitor {
-webkit-animation: chartjs-render-animation 0.001s;
animation: chartjs-render-animation 0.001s;
}
</style>
</head>
<body>
<!--引用topbar
模板名:使用thymeleaf的前后缀配置规则进行解析
-->
<!-- <div th:insert="~{dashboard::topbar}"></div>-->
<div th:replace="commons/bar::topbar"></div>
<div class="container-fluid">
<div class="row">
<!--引入侧边栏-->
<div th:replace="~{commons/bar::#sideBar(activeURI='emps')}"></div>
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
<!--区分员工修改/添加-->
<h2 class="btn btn-sm btn-success" th:text="${emp!=null?'修改员工信息':'新建员工'}">添加员工信息
</h2>
<form th:action="@{/emp}" method="post">
<!--发送put请求,修改员工数据-->
<!--
1.SpringMVC中配置HiddenHttpMethodFilter
2.页面创建post表单
3.页面创建input,name="_method"(代表新的请求方式),需要if判断员工!=null
4.不为空,获取emp的ID
-->
<input name="_method" value="put" type="hidden" th:if="${emp!=null}"/>
<input name="id" type="hidden" th:if="${emp!=null}" th:value="${emp.id}">
<div class="form-group">
<label >员工-姓名</label>
<!--name=jave bean de 定义name-->
<input name="lastName" type="text" class="form-control" id="exampleFormControlInput1" th:value="${emp!=null}?${emp.lastName}">
</div>
<div class="form-group">
<label >员工-邮箱</label>
<input name="email" type="email" class="form-control" id="exampleFormControlInput2" th:value="${emp!=null}?${emp.email}">
</div>
<div class="form-group">
<label >员工-性别</label>
<div class="form-check form-check-inline">
<input name="gender" value="1" class="form-check-input" type="radio" th:checked="${emp!=null}?${emp.gender==1}"/>
<label class="form-check-label">男</label>
</div>
<div class="form-check form-check-inline">
<input name="gender" value="0" class="form-check-input" type="radio" th:checked="${emp!=null}?${emp.gender==0}"/>
<label class="form-check-label">女</label>
</div>
</div>
<div class="form-group">
<label >所属-部门</label>
<!-- multiple全显示options <select multiple class="form-control" id="exampleFormControlSelect2"> -->
<select class="form-control" name="department.id">
<!--提交为部门id-->
<option th:each="dept:${dept}" th:text="${dept.deptName}" th:value="${dept.id}" th:selected="${emp!=null}?${dept.id==emp.department.id}"></option>
</select>
</div>
<div class="form-group">
<!--使用dates工具-->
<label >员工-生日</label>
<input name="birth" type="text" class="form-control" th:value="${emp!=null}?${#dates.format(emp.birth,'yyyy-MM-dd HH:mm:ss')}" />
</div>
<button type="submit" class="btn btn-primary" th:text="${emp!=null?'修改':'添加'}">添加</button>
</form>
</main>
</div>
</div>
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script type="text/javascript" src="../../static/asserts/js/jquery-3.2.1.slim.min.js" th:src="@{/webjars/jquery/3.3.1/jquery.js}"></script>
<script type="text/javascript" src="../../static/asserts/js/popper.min.js" th:src="@{/webjars/popper.js/1.11.1/dist/popper.js}"></script>
<script type="text/javascript" src="../../static/asserts/js/bootstrap.min.js" th:src="@{/webjars/bootstrap/4.0.0/js/bootstrap.js}"></script>
<!-- Icons -->
<script type="text/javascript" src="../../static/asserts/js/feather.min.js" th:src="@{/asserts/js/feather.min.js}"></script>
<script>
feather.replace()
</script>
</body>
</html>
18.3empController
empController
package com.cevent.springboot.web.controller;/**
* Created by Cevent on 2020/7/9.
*/
import com.cevent.springboot.web.dao.DepartmentDao;
import com.cevent.springboot.web.dao.EmployeeDao;
import com.cevent.springboot.web.entity.Department;
import com.cevent.springboot.web.entity.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import java.util.Collection;
/**
* @author cevent
* @description
* @date 2020/7/9 21:15
*/
@Controller
public class EmployeeController {
@Autowired
EmployeeDao employeeDao;
@Autowired
DepartmentDao departmentDao;
//1.查询所有员工,返回列表页面
@GetMapping("/emps")
public String empList(Model model){
Collection<Employee> empsCollection= employeeDao.getAll();
//将获取的员工信息,放在请求域中
model.addAttribute("emps",empsCollection);
//根据thymeleaf框架默认拼串: classpath:/templates/ "xxx" .html
return "emps/list";
}
//2.到添加员工页面
@GetMapping("/emp")
public String toAddEMPPage(Model model){
//2.1先查出所有部门,页面显示再选择
Collection<Department> depts=departmentDao.getDepartments();
model.addAttribute("dept",depts);
return "emps/add";
}
//3.员工添加,SpringMVC自动将请求参数(name)和入参对象的属性名(javaBean)进行一一绑定
@PostMapping("/emp")
public String addEMP(Employee employee){
//打印add员工信息
System.out.println("新建的员工信息:"+employee);
//1.添加保存员工
employeeDao.save(employee);
//返回员工列表页面,redirect:重定向到地址,forward:转发到地址
return "redirect:/emps";
}
//4.修改员工页面
@GetMapping("/emp/{id}")
public String toEditPage(@PathVariable("id") Integer id,Model model){
Employee employee=employeeDao.get(id);
model.addAttribute("emp",employee);
//页面显示部门列表
Collection<Department> depts=departmentDao.getDepartments();
model.addAttribute("dept",depts);
//修改/添加通用add页面
return "emps/add";
}
//5.更新员工数据
@PutMapping("/emp")
public String updateEMP(Employee employee){
System.out.println("修改的员工数据");
employeeDao.save(employee);
return "redirect:/emps";
}
}