经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Spring » 查看文章
Springboot-Management的项目实践
来源:jb51  时间:2022/5/30 9:33:43  对本文有异议

准备工作

1.新建一个项目

next之后选择SpringWebThymeleaf,然后直接next,Finish即可。

之后我们进行测试,看是否搭建成功

ok,我们已经项目创建好了。

2.导入静态资源

根据下方的图片展示将资源导入

3.创建实体类

首先我们先导入lombok

  1. <dependency>
  2. <groupId>org.projectlombok</groupId>
  3. <artifactId>lombok</artifactId>
  4. <version>1.18.20</version>
  5. </dependency>

创建pojo的包,在其下创建两个实体类Department和Employee

  1. import lombok.AllArgsConstructor;
  2. import lombok.Data;
  3. import lombok.NoArgsConstructor;
  4.  
  5. //部门表
  6. @Data
  7. @AllArgsConstructor
  8. @NoArgsConstructor
  9. public class Department {
  10. private Integer id;
  11. private String departmentName;
  12. }
  1. import lombok.AllArgsConstructor;
  2. import lombok.Data;
  3. import lombok.NoArgsConstructor;
  4.  
  5. import java.util.Date;
  6.  
  7. //员工表
  8. @Data
  9. @AllArgsConstructor
  10. @NoArgsConstructor
  11. public class Employee {
  12. private Integer id;
  13. private String employeeName;
  14. private String email;
  15. private Integer gender; //0:女 1:男
  16.  
  17. private Department department;
  18. private Date birth;
  19. }

遇到的问题:有些人会遇到这个问题,为什么我的lombok导入了,也用将其方法生成了,但是最后不能用,就像下面的情况

其实不要你以为写了那三行就是有了,我们打开structure看一下,发现虽然写了,但是还是没有方法。这又是为什么呢?

其实是因为你的IDEA里面没有Lombok的插件,只需要在Setting->Plugins->搜索lombok->Install->重新启动idea

最后看下成果

4.编写dao层

同样建包dao,并在其下创建DepartmentDaoEmployeeDao

  1. import com.hxl.pojo.Department;
  2. import org.springframework.stereotype.Repository;
  3.  
  4. import java.util.Collection;
  5. import java.util.HashMap;
  6. import java.util.Map;
  7.  
  8. //部门dao
  9. //注册到IOC容器中
  10. @Repository
  11. public class DepartmentDao {
  12. //模拟数据库中的数据
  13. private static Map<Integer, Department> departments = null;
  14.  
  15. static {
  16. departments = new HashMap<Integer, Department>();
  17.  
  18. departments.put(1, new Department(1, "教学部"));
  19. departments.put(2, new Department(2, "市场部"));
  20. departments.put(3, new Department(3, "调研部"));
  21. departments.put(4, new Department(4, "后勤部"));
  22. departments.put(5, new Department(5, "运营部"));
  23. }
  24.  
  25. //获得所有部门信息
  26. public Collection<Department> getDepartments(){
  27. return departments.values();
  28. }
  29.  
  30. //通过id得到部门
  31. public Department getDepartmentById(Integer id){
  32. return departments.get(id);
  33. }
  34. }
  1. import com.hxl.pojo.Department;
  2. import com.hxl.pojo.Employee;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.stereotype.Repository;
  5.  
  6. import java.util.Collection;
  7. import java.util.Date;
  8. import java.util.HashMap;
  9. import java.util.Map;
  10.  
  11. //员工dao
  12. //注册到IOC容器中
  13. @Repository
  14. public class EmployeeDao {
  15. //模拟数据库中的数据
  16. static private Map<Integer, Employee> employees = null;
  17.  
  18. //员工所属的部门
  19. @Autowired
  20. private DepartmentDao departmentDao;
  21.  
  22. static {
  23. employees = new HashMap<Integer, Employee>();//创建一个员工表
  24. employees.put(1, new Employee(1, "hxl", "1234@qq.com", 1, new Department(1, "教学部"), new Date()));
  25. employees.put(2, new Employee(2, "zmc", "5678@qq.com", 1, new Department(2, "市场部"), new Date()));
  26. employees.put(3, new Employee(3, "kwb", "9012@qq.com", 0, new Department(3, "调研部"), new Date()));
  27. employees.put(4, new Employee(4, "lqs", "3456@qq.com", 1, new Department(4, "后勤部"), new Date()));
  28. employees.put(5, new Employee(5, "wjr", "7890@qq.com", 1, new Department(5, "运营部"), new Date()));
  29. }
  30.  
  31. //主键自增
  32. private static Integer initialId = 6;
  33.  
  34. //增加一个员工
  35. public void addEmployee(Employee employee) {
  36. if (employee.getId() == null) {
  37. employee.setId(initialId++);
  38. }
  39. employee.setDepartment(departmentDao.getDepartmentById(employee.getDepartment().getId()));
  40. employees.put(employee.getId(), employee);
  41. }
  42.  
  43. //查询全部员工信息
  44. public Collection<Employee> getAllEmployees() {
  45. return employees.values();
  46. }
  47.  
  48. //通过id查询员工
  49. public Employee getEmployeeById(Integer id) {
  50. return employees.get(id);
  51. }
  52.  
  53. //通过id删除员工
  54. public void deleteEmployeeById(int id) {
  55. employees.remove(id);
  56. }
  57. }

至此我们的准备工作就完成了。

首页实现

首先我们像之前创建一个config的包用来存放自定义的配置

创建一个MyMvcConfig的配置类,进行首页的视图跳转

  1. import org.springframework.context.annotation.Configuration;
  2. import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
  3. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  4.  
  5. @Configuration
  6. public class MyMvcConfig implements WebMvcConfigurer {
  7. @Override
  8. public void addViewControllers(ViewControllerRegistry registry) {
  9. //添加一个,打了"/",然后让他去index
  10. registry.addViewController("/").setViewName("index");
  11. registry.addViewController("index.html").setViewName("index");
  12. }
  13. }

启动程序,进行测试访问localhost:8080/或者locahost:8080/index.html出现下面的界面就ok了

在这块中,我们发现仅有一些文字,样式图片等都没有加载出来,这是因为我们之前导入的静态资源的html,没有使用Thymeleaf的的语法。我们的模板引擎为Thymeleaf

我们将之前导入的html里面的都改为thymeleaf语法。

注意所有html都需要引入Thymeleaf命名空间

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

然后修改所有页面静态资源的引入,使用@{...} 链接表达式(只要是自己本地的链接资源,都需要根据这个语法来修改)

在标签前增加th:

index.html为例

注意:第一个/代表项目的classpath,也就是这里的resources目录

修改之后我们再次运行

中英文切换

首先我们要保证我们的编码是UTF-8

Properties编写

接下来我们进行配置编写,在resources目录下创建一个文件夹i18n,然后在其下创建一个login.propertieslogin_zh_CN.properties创建完成后发现他们两个合并了。

这样我们就有了默认配置和中文的配置,接下来再创建一个英语的,来看步骤:

这样我们就有了三个文件。展示操作的时候到了

首先点击这里,可以让我们拥有可视化操作。没有可视化选项的兄弟下载插件Flagiarism然后重启就可以了

接下来将我们的内容一次创建

直接点击+号,创建文件名和输入内容即可。

之后我们就会发现这里也会增加内容。

接下来按照图片一次进行创建

这里展示一个内容

login.properties

  1. login.btn=登录
  2. login.password=密码
  3. login.remember=记住我
  4. login.tip=请登录
  5. login.username=用户名

login_en_US.properties

  1. login.btn=Sign in
  2. login.password=Password
  3. login.remember=Remember me
  4. login.tip=Please sign in
  5. login.username=Username

我们设置完之后,该怎么让我们的项目识别呢。需要在我们的application.properties下进行绑定

  1. # 我们的配置文件的真实位置
  2. spring.messages.basename=i18n.login

源码分析:

我们去MessageSourceAutoConfiguration这个类下,查看messageSource该方法

  1. public MessageSource messageSource(MessageSourceProperties properties);

可以看到,他的参数是一个MessageSourceProperties对象,我们继续查看,它首先是一个属性basename,默认值为message

  • 如果你不在springboot配置文件中指定以.分隔开的国际化资源文件名称的话
  • 它默认会去类路径下找messages.properties作为国际化资源文件

这也就是我们为什么要在配置文件中进行配置。

后面好了,那么我们的html页面该怎么进行呢。查阅资料发现Thymeleaf中取值需要进行使用到#{}例如

  1. <th:text="#{login.tip}">

根据上述步骤将其他的几处也进行修改

最后的效果

接下来就是可以中英文进行切换,此时需要加一个组件

在我们的首页界面中可以看到我们的两个中英文标签

  1. <a class="btn btn-sm">中文</a>
  2. <a class="btn btn-sm">English</a>

此时我们需要对其加上跳转链接同时加上参数,原来我们的参数是现在不需要,用的是()

  1. <a class="btn btn-sm" th:href="@{/index.html(l='zh_CN')}" rel="external nofollow" >中文</a>
  2. <a class="btn btn-sm" th:href="@{/index.html(l='en_US')}" rel="external nofollow" >English</a>

自定义地区的解析器组件

在spring中,有两个关于国际化的类,一个是代表地区的Locale,每一个对象都代表了特定的区域,还有一个关于地区解析器LocaleResolver

首先搜索WebMvcAutoConfiguration,可以在其中找到关于一个方法localeResolver()

  1. @Bean
  2. @ConditionalOnMissingBean
  3. @ConditionalOnProperty(prefix = "spring.mvc", name = "locale")
  4. public LocaleResolver localeResolver() {
  5. //如果用户配置了,则使用用户配置好的,容器中没有就自己配,有就用用户的
  6. if (this.mvcProperties.getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) {
  7. return new FixedLocaleResolver(this.mvcProperties.getLocale());
  8. }
  9. //用户没有配置,则使用默认的,接收头 国际化分解
  10. AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
  11. localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
  12. return localeResolver;
  13. }

该方法就是获取LocaleResolver地区对象解析器:

  1. 如果用户配置了则使用用户配置的地区解析器;
  2. 如果用户没有配置,则使用默认的地区解析器

可以发现它继承了LocaleResolver接口,实现了地区解析

因此我们想要实现上述自定义的国际化资源生效,只需要编写一个自己的地区解析器,继承LocaleResolver接口,重写其方法即可

在config包下新建一个MyLocaleResolver

  1. package com.hxl.config;
  2.  
  3. import org.springframework.util.StringUtils;
  4. import org.springframework.web.servlet.LocaleResolver;
  5.  
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. import java.util.Locale;
  9.  
  10. public class MyLocaleResolver implements LocaleResolver {
  11. @Override
  12. public Locale resolveLocale(HttpServletRequest httpServletRequest) {
  13. //获取请求中的国际化参数
  14. String language = httpServletRequest.getParameter("l");
  15. //默认的地区
  16. Locale locale = Locale.getDefault();
  17. //如果请求的链接参数不为空,携带了国际化参数
  18. if (!StringUtils.isEmpty(language)) {
  19. String[] split = language.split("_");//zh_CN(语言_地区)
  20. locale = new Locale(split[0], split[1]);
  21. }
  22. return locale;
  23. }
  24.  
  25. @Override
  26. public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
  27.  
  28. }
  29. }

完成组件后,需要在MvcConfig配置类下添加上我们的Bean

  1. //自定义的国际化组件生效
  2. @Bean
  3. public LocaleResolver localeResolver() {
  4. return new MyLocaleResolver();
  5. }

重新启动项目,我们就可以通过点击下方的中英文来进行切换。

总结

  • 我们需要配置i18n文件
  • 需要自定义一个组件MyLocaleResolver,以便在项目中进行按钮的自动切换。
  • 将自己的组件配置到spring容器中@Bean
  • 取值用的是#{}

登录功能

1.页面调整

我们需要将这里进行修改。

查看页面之后发现,我们点击登录按钮的时候会进入dashboard页面。

所以我们需要将这里的提交地址进行修改,以及将用户名和密码框加上属性以便传参。

2.编写LoginController

  1. import org.springframework.stereotype.Controller;
  2. import org.springframework.ui.Model;
  3. import org.springframework.web.bind.annotation.RequestMapping;
  4. import org.springframework.web.bind.annotation.RequestParam;
  5.  
  6. @Controller
  7. public class LoginController {
  8. @RequestMapping("/user/login")
  9. public String login(@RequestParam("username") String username,@RequestParam("password") String password, Model model){
  10. //如果用户名和密码都正确
  11. if("wangmm".equals(username) && "123456".equals(password)){
  12. return "dashboard";
  13. }else{
  14. //如果用户名或者密码不正确
  15. model.addAttribute("msg","用户名或者密码不正确");
  16. return "index";
  17. }
  18. }
  19. }

我们需要在登录页面增加一个返回错误信息的标签。

此时启动程序并访问localhost:8080。输入正确的账号密码访问我们可以看到这个页面

输入错误的账号密码会呈现

好了,我们这里已经成功了。但是当我们成功登录后我们的页面显示不全,这是因为之前提到的静态页面展示的问题,需要把我们dashboard页面下的本地静态资源都用Thymeleaf语法进行修改。修改成功后即可。

同时我们可以到浏览器页面的url暴露了我们的信息。所以我们需要进行修改。

在自定义的配置类MyMvcConfig中增加。这样我们访问main.html也就是访问了dashboard页面。

  1. registry.addViewController("/main.html").setViewName("dashboard");

同时我们也要去将LoginController下的登录页面也重定向到main.html中。

  1. @Controller
  2. public class LoginController {
  3. @RequestMapping("/user/login")
  4. public String login(@RequestParam("username") String username,@RequestParam("password") String password, Model model){
  5. //如果用户名和密码都正确
  6. if("wangmm".equals(username) && "123456".equals(password)){
  7. return "redirect:/main.html";
  8. }else{
  9. //如果用户名或者密码不正确
  10. model.addAttribute("msg","用户名或者密码不正确");
  11. return "index";
  12. }
  13. }
  14. }

之后我们运行查看,浏览器上的url不再携带用户的信息。

此时出现了新的问题,就是我们不管登录不登录,通过localhost:8080/main.html都可以访问到我们的dashboard的页面。

3.登录拦截器

config目录下,新建一个登录拦截器类LoginHandlerInterceptor

目的:用户登录成功后得到用户的信息。防止未登录用户查看页面

得到用户信息,我们需要先保存用户的信息,所以我们需要在LoginController中当用户登录成功后,存入用户信息到session

  1. @Controller
  2. public class LoginController {
  3. @RequestMapping("/user/login")
  4. public String login(@RequestParam("username") String username,@RequestParam("password") String password, Model model, HttpSession session){
  5. //如果用户名和密码都正确
  6. if("wangmm".equals(username) && "123456".equals(password)){
  7. session.setAttribute("LoginUser", username);
  8. return "redirect:/main.html";
  9. }else{
  10. //如果用户名或者密码不正确
  11. model.addAttribute("msg","用户名或者密码不正确");
  12. return "index";
  13. }
  14. }
  15. }

实现拦截器。需要继承HandlerInterceptor接口

  1. import org.springframework.web.servlet.HandlerInterceptor;
  2. import org.springframework.web.servlet.ModelAndView;
  3.  
  4. import javax.servlet.http.HttpServletRequest;
  5. import javax.servlet.http.HttpServletResponse;
  6.  
  7. public class LoginHandlerInterceptor implements HandlerInterceptor {
  8. @Override
  9. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  10. //用户登录成功拥有session
  11. Object loginUser = request.getSession().getAttribute("LoginUser");
  12. if(loginUser == null){
  13. request.setAttribute("msg","用户权限不够,请登录");
  14. //权限不够就重定向到首页
  15. request.getRequestDispatcher("/index.html").forward(request,response);
  16. return false;
  17. }else{
  18. return true;
  19. }
  20. }
  21. }

有了拦截器就需要注册到bean中,在MyMvcConfig配置类中,添加我们自定义的拦截器,注意屏蔽主页、登录相关请求、静态资源的拦截

  1. @Override
  2. public void addInterceptors(InterceptorRegistry registry) {
  3. registry.addInterceptor(new LoginHandlerInterceptor())
  4. .addPathPatterns("/**")
  5. .excludePathPatterns("/index.html", "/", "/user/login", "/asserts/**");
  6. }

注意这个地方,有些人不是在整一个文件夹中,所以需要分开写"/css/**", "/js/**", "/img/**"

测试:启动程序直接访问http://localhost:8080/main.html

之后我们登录,成功之后再重新进入之前的链接http://localhost:8080/main.html发现也是可以访问得到的。

这是因为登录之后用户的信息已经保存在了session中。拦截器自然不会拦截。

员工信息——查

实现界面中的Customers中的员工查询。

  • th:fragment="sidebar"
  • th:replace="~{commons/commons::topbar}"
  • 如果要传递参数,可以直接使用()传参,接收判断即可
  • 列表循环展示

首先我们先将模板中的跳转链接进行跳转

同时将list.html中的代码进行修改

templates目录下新建一个包emp用来存放员工的相关页面

之后我们编写对应的Controller

  1. package com.hxl.controller;
  2.  
  3. import com.hxl.dao.EmployeeDao;
  4. import com.hxl.pojo.Employee;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.stereotype.Controller;
  7. import org.springframework.ui.Model;
  8. import org.springframework.web.bind.annotation.RequestMapping;
  9.  
  10. import java.util.Collection;
  11.  
  12. @Controller
  13. public class EmployeeController {
  14. @Autowired
  15. private EmployeeDao employeeDao;
  16.  
  17. @RequestMapping("/emps")
  18. public String list(Model model){
  19. Collection<Employee> employees = employeeDao.getAllEmployees();
  20. model.addAttribute("emps",employees);
  21. return "emp/list";
  22. }
  23. }

启动测试,发现是这个页面,这是由于咱们的语法有问题,和之前的一样将本地静态资源进行修改。

之后进行修改可以得到新的界面。

优化

点击员工管理之后应该是高亮的状态,但是我们发现点击之后高亮不在Customers而在Dashboard

同时我们可以将侧边栏以及顶部栏公共的部分进行提炼

  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3.  
  4. <!--顶部导航栏,利用th:fragment提取出来,命名为topbar-->
  5. <nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="topbar">
  6. <a class="navbar-brand col-sm-3 col-md-2 mr-0" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >Company
  7. name</a>
  8. <input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search">
  9. <ul class="navbar-nav px-3">
  10. <li class="nav-item text-nowrap">
  11. <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >Sign out</a>
  12. </li>
  13. </ul>
  14. </nav>
  15.  
  16. <!--侧边栏,利用th:fragment提取出来,命名为sidebar-->
  17. <nav class="col-md-2 d-none d-md-block bg-light sidebar" th:fragment="siderbar">
  18. <div class="sidebar-sticky">
  19. <ul class="nav flex-column">
  20. <li class="nav-item">
  21. <a class="nav-link active" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >
  22. <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
  23. fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
  24. stroke-linejoin="round" class="feather feather-home">
  25. <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
  26. <polyline points="9 22 9 12 15 12 15 22"></polyline>
  27. </svg>
  28. Dashboard <span class="sr-only">(current)</span>
  29. </a>
  30. </li>
  31. <li class="nav-item">
  32. <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >
  33. <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
  34. fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
  35. stroke-linejoin="round" class="feather feather-file">
  36. <path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path>
  37. <polyline points="13 2 13 9 20 9"></polyline>
  38. </svg>
  39. Orders
  40. </a>
  41. </li>
  42. <li class="nav-item">
  43. <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >
  44. <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
  45. fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
  46. stroke-linejoin="round" class="feather feather-shopping-cart">
  47. <circle cx="9" cy="21" r="1"></circle>
  48. <circle cx="20" cy="21" r="1"></circle>
  49. <path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path>
  50. </svg>
  51. Products
  52. </a>
  53. </li>
  54. <li class="nav-item">
  55. <a class="nav-link" th:href="@{/emps}" rel="external nofollow" >
  56. <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
  57. fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
  58. stroke-linejoin="round" class="feather feather-users">
  59. <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
  60. <circle cx="9" cy="7" r="4"></circle>
  61. <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
  62. <path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
  63. </svg>
  64. Customers
  65. </a>
  66. </li>
  67. <li class="nav-item">
  68. <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >
  69. <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
  70. fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
  71. stroke-linejoin="round" class="feather feather-bar-chart-2">
  72. <line x1="18" y1="20" x2="18" y2="10"></line>
  73. <line x1="12" y1="20" x2="12" y2="4"></line>
  74. <line x1="6" y1="20" x2="6" y2="14"></line>
  75. </svg>
  76. Reports
  77. </a>
  78. </li>
  79. <li class="nav-item">
  80. <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >
  81. <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
  82. fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
  83. stroke-linejoin="round" class="feather feather-layers">
  84. <polygon points="12 2 2 7 12 12 22 7 12 2"></polygon>
  85. <polyline points="2 17 12 22 22 17"></polyline>
  86. <polyline points="2 12 12 17 22 12"></polyline>
  87. </svg>
  88. Integrations
  89. </a>
  90. </li>
  91. </ul>
  92.  
  93. <h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
  94. <span>Saved reports</span>
  95. <a class="d-flex align-items-center text-muted"
  96. href="http://getbootstrap.com/docs/4.0/examples/dashboard/#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >
  97. <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
  98. stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
  99. class="feather feather-plus-circle">
  100. <circle cx="12" cy="12" r="10"></circle>
  101. <line x1="12" y1="8" x2="12" y2="16"></line>
  102. <line x1="8" y1="12" x2="16" y2="12"></line>
  103. </svg>
  104. </a>
  105. </h6>
  106. <ul class="nav flex-column mb-2">
  107. <li class="nav-item">
  108. <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >
  109. <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
  110. fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
  111. stroke-linejoin="round" class="feather feather-file-text">
  112. <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
  113. <polyline points="14 2 14 8 20 8"></polyline>
  114. <line x1="16" y1="13" x2="8" y2="13"></line>
  115. <line x1="16" y1="17" x2="8" y2="17"></line>
  116. <polyline points="10 9 9 9 8 9"></polyline>
  117. </svg>
  118. Current month
  119. </a>
  120. </li>
  121. <li class="nav-item">
  122. <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >
  123. <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
  124. fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
  125. stroke-linejoin="round" class="feather feather-file-text">
  126. <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
  127. <polyline points="14 2 14 8 20 8"></polyline>
  128. <line x1="16" y1="13" x2="8" y2="13"></line>
  129. <line x1="16" y1="17" x2="8" y2="17"></line>
  130. <polyline points="10 9 9 9 8 9"></polyline>
  131. </svg>
  132. Last quarter
  133. </a>
  134. </li>
  135. <li class="nav-item">
  136. <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >
  137. <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
  138. fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
  139. stroke-linejoin="round" class="feather feather-file-text">
  140. <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
  141. <polyline points="14 2 14 8 20 8"></polyline>
  142. <line x1="16" y1="13" x2="8" y2="13"></line>
  143. <line x1="16" y1="17" x2="8" y2="17"></line>
  144. <polyline points="10 9 9 9 8 9"></polyline>
  145. </svg>
  146. Social engagement
  147. </a>
  148. </li>
  149. <li class="nav-item">
  150. <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >
  151. <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
  152. fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
  153. stroke-linejoin="round" class="feather feather-file-text">
  154. <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
  155. <polyline points="14 2 14 8 20 8"></polyline>
  156. <line x1="16" y1="13" x2="8" y2="13"></line>
  157. <line x1="16" y1="17" x2="8" y2="17"></line>
  158. <polyline points="10 9 9 9 8 9"></polyline>
  159. </svg>
  160. Year-end sale
  161. </a>
  162. </li>
  163. </ul>
  164. </div>
  165. </nav>
  166. </html>

提取页面的公共部分

我们可以将两个页面dashboard.htmllist.html`中顶部导航栏和侧边栏的代码删除

启动测试查看:所有顶部和侧边都没有了

将公共的部分引入

dashboard.htmllist.html删除的部分插入提取出来的公共部分topbarsidebar

  1. <!--顶部导航栏-->
  2. <div th:replace="~{commons/commons::topbar}" }></div>
  3. <!--侧边栏-->
  4. <div th:replace="~{commons/commons::siderbar}"></div>

解决高亮

通过观察,在页面中高亮的部分是由于class="nav-link active"属性

我们可以通过传递参数来进行判断说明自己的页面应该哪里高亮

dashboard.html的侧边栏标签传递参数activedashboard.html

  1. <!--侧边栏-->
  2. <div th:replace="~{commons/commons::siderbar(active='dashboard.html')}"></div>

list.html的侧边栏标签传递参数activelist.html

  1. <!--顶部导航栏-->
  2. <div th:replace="~{commons/commons::siderbar(active='list.html')}" }></div>

我们将页面参数修改后需要在公共页面部分接收参数active

  1. th:class="${active=='dashboard.html'?'nav-link active':'nav-link'}"
  2.  
  3. th:class="${active=='list.html'?'nav-link active':'nav-link'}"

测试:

点击CustomersCustomers高亮,成功

显示员工信息

list.html中数据进行修改,显示员工的信息,并添加编辑和删除的标签

  1. <table class="table table-striped table-sm">
  2. <thead>
  3. <tr>
  4. <th>id</th>
  5. <th>employeeName</th>
  6. <th>email</th>
  7. <th>gender</th>
  8. <th>department</th>
  9. <th>birth</th>
  10. <th>操作</th>
  11. </tr>
  12. </thead>
  13. <tbody>
  14. <tr th:each="emp:${emps}">
  15. <td th:text="${emp.getId()}"></td>
  16. <td th:text="${emp.getEmployeeName()}"></td>
  17. <td th:text="${emp.getEmail()}"></td>
  18. <td th:text="${emp.getGender()==0?'女':'男'}"></td>
  19. <td th:text="${emp.getDepartment().getDepartmentName()}"></td>
  20. <td th:text="${#dates.format(emp.getBirth(),'yyyy-MM-dd HH:mm:ss')}"></td>
  21. <td>
  22. <a class="btn btn-sm btn-primary">编辑</a>
  23. <a class="btn btn-sm btn-danger">删除</a>
  24. </td>
  25. </tr>
  26. </tbody>
  27. </table>

修改成功后,测试

员工信息——增

  • 按钮提交
  • 跳转到添加页面
  • 添加员工成功
  • 返回首页

表单提交尽量用重定向:redirect,否则容易出现表单重复提交

首先增加提交按钮

list.html中增加一个添加员工的按钮,点击按钮时发起有一个/addEmps的请求

  1. <a class="btn btn-sm btn-success" th:href="@{/addEmps}" rel="external nofollow" >添加员工</a>

这里去编写对应的controller,处理请求。

通过get的方式进行请求提交,所以在EmployeeController中添加一个方法addEmps用来处理list页面点击提交按钮的操作,返回到add.html添加员工页面(页面需要增加,原先没有)

注意在最开始的地方将departmentDao进行装配

  1. @Autowired
  2. private DepartmentDao departmentDao;
  1. @GetMapping("/addEmps")
  2. public String add(Model model) {
  3. //查出所有的部门信息,添加到departments中,用于前端接收
  4. Collection<Department> departments = departmentDao.getDepartments();
  5. model.addAttribute("departments", departments);
  6. return "emp/add";//返回到添加员工页面
  7. }

创建员工界面add.html

在我们的templates/emp下新建一个add.html,只需要将list.html界面进行复制,然后修改表单即可。修改内容如下:

  1. <main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
  2. <form>
  3. <div class="form-group">
  4. <label>EmployeeName</label>
  5. <input type="text" name="employeeName" class="form-control" placeholder="employeeName:hxl">
  6. </div>
  7. <div class="form-group">
  8. <label>Email</label>
  9. <input type="email" name="email" class="form-control" placeholder="email:xxxxx@qq.com">
  10. </div>
  11. <div class="form-group">
  12. <label>Gender</label><br/>
  13. <div class="form-check form-check-inline">
  14. <input class="form-check-input" type="radio" name="gender" value="1">
  15. <label class="form-check-label"></label>
  16. </div>
  17. <div class="form-check form-check-inline">
  18. <input class="form-check-input" type="radio" name="gender" value="0">
  19. <label class="form-check-label"></label>
  20. </div>
  21. </div>
  22. <div class="form-group">
  23. <label>department</label>
  24. <!--注意这里的name是department.id,因为传入的参数为id-->
  25. <!--我们在controller中接收的是一个Employee,所以我们需要提交的是其中的一个属性-->
  26. <select class="form-control" name="department.id">
  27. <option th:each="department:${departments}" th:text="${department.getDepartmentName()}" th:value="${department.getId()}"></option>
  28. </select>
  29. </div>
  30. <div class="form-group">
  31. <label>Birth</label>
  32. <!--springboot默认的日期格式为yy/MM/dd-->
  33. <input type="text" name="date" class="form-control" placeholder="birth:yyyy/MM/dd">
  34. </div>
  35. <button type="submit" class="btn btn-primary">添加</button>
  36. </form>
  37.  
  38. </main>

注意下拉框中的内容应该是我们自己部门名。通过遍历得到

  1. <!--通过遍历得到部门的信息,显示是部门的名字,传入的是部门的id-->
  2. <option th:each="department:${departments}" th:text="${department.getDepartmentName()}" th:value="${department.getId()}"></option>

测试:

员工请求addEmps

add.html页面,当我们填写完信息,点击添加按钮,应该完成添加返回到list页面,展示新的员工信息;因此在add.html点击添加按钮的一瞬间,我们同样发起一个请求/addEmps,与上述提交按钮发出的请求路径一样,但这里发出的是post请求

编写对应的controller

  1. @PostMapping("/addEmps")
  2. public String addEmp(Employee employee) {
  3. employeeDao.addEmployee(employee);//添加一个员工
  4. return "redirect:/emps";//重定向到/emps,刷新列表,返回到list页面
  5. }

测试:

提交之后我们可以跳转到员工页面查看我们的新增加的员工

差一个添加成功的图片

同时这里需要注意:日期格式必须是yyyy/MM/dd才能正确跳转,否则就会出错。因为这是spring默认的,如果要修改日期格式,需要在application.properties中进行修改

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

这样日期格式就变了,此时原来的格式就不能用了

链接形式处理是getMapping

员工信息——改

首页编辑按钮

当我们点击编辑时,应该跳转到更新员工的页面update.html,在list.html中修改

  1. <a class="btn btn-sm btn-primary" th:href="@{/update/{id}(id=${emp.getId()})}" rel="external nofollow" >编辑</a>

这里进行跳转就需要GetMapping

编写对应controller,在EmployeeController中添加一个方法update用来处理list页面点击编辑按钮的操作,返回到update.html

  1. //restful风格接收参数
  2. @GetMapping("/update/{id}")
  3. public String update(@PathVariable("id") int id, Model model) {
  4. //查询指定id的员工,添加到empByID中,用于前端接收
  5. Employee employeeByID = employeeDao.getEmployeeById(id);
  6. model.addAttribute("empByID", employeeByID);
  7. //查出所有的部门信息,添加到departments中,用于前端接收
  8. Collection<Department> departments = departmentDao.getDepartments();
  9. model.addAttribute("departments", departments);
  10. return "emp/update";//返回到编辑员工页面
  11. }

更新员工的页面

复制add.html并修改

  1. <main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
  2. <form th:action="@{/update}" method="post">
  3. <input type="hidden" name="id" th:value="${empByID.getId()}">
  4. <div class="form-group">
  5. <label>employeeName</label>
  6. <input th:value="${empByID.getEmployeeName()}" type="text" name="employeeName" class="form-control"
  7. placeholder="employeeName:hxl">
  8. </div>
  9. <div class="form-group">
  10. <label>Email</label>
  11. <input th:value="${empByID.getEmail()}" type="email" name="email" class="form-control"
  12. placeholder="email:xxxxx@qq.com">
  13. </div>
  14. <div class="form-group">
  15. <label>Gender</label><br/>
  16. <div class="form-check form-check-inline">
  17. <input th:checked="${empByID.getGender()==1}" class="form-check-input" type="radio"
  18. name="gender" value="1">
  19. <label class="form-check-label"></label>
  20. </div>
  21. <div class="form-check form-check-inline">
  22. <input th:checked="${empByID.getGender()==0}" class="form-check-input" type="radio"
  23. name="gender" value="0">
  24. <label class="form-check-label"></label>
  25. </div>
  26. </div>
  27. <div class="form-group">
  28. <label>department</label>
  29. <!--注意这里的name是department.id,因为传入的参数为id-->
  30. <select class="form-control" name="department.id">
  31. <option th:selected="${department.getId()==empByID.department.getId()}"
  32. th:each="department:${departments}" th:text="${department.getDepartmentName()}"
  33. th:value="${department.getId()}">
  34. </option>
  35. </select>
  36. </div>
  37. <div class="form-group">
  38. <label>Birth</label>
  39. <!--springboot默认的日期格式为yyyy/MM/dd-->
  40. <input th:value="${#dates.format(empByID.getBirth(),'yyyy/MM/dd')}" type="text" name="date" class="form-control"
  41. placeholder="birth:yyyy/MM/dd">
  42. </div>
  43. <button type="submit" class="btn btn-primary">修改</button>
  44. </form>
  45. </main>

这里已经将日期格式进行了修改,没有修改之前的日期是不太正确的。

同时页面跳转的时候需要将Id携带过去。但是不能显示出来,所以需要hidden在上方已经有标注。

页面提交请求

页面编辑完成后会发起一个请求

  1. <form th:action="@{/update}" method="post">

这需要我们去controller中处理请求

  1. @PostMapping("/update")
  2. public String updateEmp(Employee employee) {
  3. employeeDao.addEmployee(employee);//添加一个员工
  4. return "redirect:/emps";//添加完成重定向到/emps,刷新列表
  5. }

测试:

原来的信息:

点击编辑之后:

修改之后:

成功将员工进行了修改。

员工信息——删

点击删除进行请求跳转:修改我们的删除标签

  1. <a class="btn btn-sm btn-success" th:href="@{/delete/{id}(id=${emp.getId()})}" rel="external nofollow" >删除</a>

然后编写对应的controller,处理点击删除按钮的请求,删除指定员工,重定向到/emps请求,更新员工信息

  1. @GetMapping("/delete/{id}")
  2. public String delete(@PathVariable("id") Integer id) {
  3. employeeDao.deleteEmployeeById(id);
  4. return "redirect:/emps";
  5. }

测试:

删除成功

错误页面定制

404页面定制

springboot中错误页面定制比较简单,比如说404。直接在thmplates下新建一个error文件夹,然后将404页面直接丢进去即可。

登录测试一下

注销

在我们提取出来的公共commons页面,顶部导航栏处中的标签添加href属性,实现点击发起请求/user/logout

  1. <a class="nav-link" th:href="@{/user/logout}" rel="external nofollow" >Sign out</a>

LoginController中编写对应的方法,清除session,并重定向到首页

  1. @RequestMapping("/user/logout")
  2. public String logout(HttpSession session) {
  3. session.invalidate();
  4. return "redirect:/index.html";
  5. }

测试:点击右上角的Sign out就可以退出界面,访问main.html是没有权限的。

到此这篇关于Springboot-Management的项目实践的文章就介绍到这了,更多相关Springboot Management内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号