员工管理系统文档【基础功能开发全细节】

1、首页实现

1.1、访问index

由于template包下的静态文件不能直接访问,所以需要间接访问到;需要进行视图跳转;

  • 在主程序统计目录下新建config包用来存放自己的配置类
  • 在其中建立自己的配置类MyMvcConfig用来增加自己的视图跳转
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("index");
        registry.addViewController("/index.html").setViewName("index");
    }
}

要先要导入thymeleaf依赖后,启动才有效!

启动主程序后访问测试,访问localhost:8080/或localhost:8080/index.html

在这里插入图片描述

显然,此时前端html代码有问题,一些静态资源没有成功引入。

1.2、给index.html引入thymeleaf

上述测试可以看到页面有图片没有加载出来,且没有css和js的样式,这就是因为我们html页面中静态资源引入的语法出了问题,在SpringBoot中,推荐使用Thymeleaf作为模板引擎,我们将其中的语法改为Thymeleaf,所有页面的静态资源都需要使用其接管

  • 注意所有html都需要引入Thymeleaf命名空间
xmlns:th="http://www.thymeleaf.org"
  • 然后修改所有的页面静态资源的引入,使用@{…}链接表达式

在这里插入图片描述

在此访问,正确显示页面:

在这里插入图片描述

2、页面国际化

2.1、统一properties编码

在IDEA中统一设置properties的编码为UTF-8

在这里插入图片描述

2.2、编写i18n国际化资源文件

  • 在resources目录下新建一个i18n包,其中放置国际化相关的配置

  • 其中新建三个配置文件,用来配置语言:

    • login.properties: 无语言配置时生效;

    • login_en_US.properties:英文生效;

    • login_zh_CN.properties:中文生效;

      命名方式是下划线的组合: 文件名_语言_国家.properties

以此命名方式,IDEA会帮助我们识别这是个国际化配置,自动绑定在一起转换如下的模式:

在这里插入图片描述

绑定在一起后,我们想要添加更多的语言配置,只需要在大的资源包右键添加到该绑定文件即可

在这里插入图片描述

此时只需要输入区域名即可创建成功,比如:en_US,就会自动识别为美国:

在这里插入图片描述

然后打开英文或是中文语言的properties文件,点击Resources Bundle进入可视化编辑页面

在这里插入图片描述

进入到可视化编辑页面后

  1. 点击+
  2. 添加属性:首先创建一个login.tip代表首页中的提示(自定义起名login.XXX)

在这里插入图片描述

  1. 然后对提示分别做三种情况的语言配置,三个对应的输入框输入即可

在这里插入图片描述

类似配置tip提示,我们在配置更多的信息

在这里插入图片描述

然后打开三个配置文件查看其中的文本内容,可以看到已经做好了全部的配置

login.properties(默认)

login.btn=登录
login.password=密码
login.remember=记住我
login.tip=请登录 
login.username=用户名

login_en_US.properties(英文)

login.btn=login
login.password=password
login.remember=remember me
login.tip=Please sign in
login.username=username

login_zh_CN.properties(中文)

login.btn=登录
login.password=密码
login.remember=记住我
login.tip=请登录
login.username=用户名

2.3、配置国际化资源文件名称

在Spring程序中,国际化主要是通过ResourceBundleMessageSource这个类来实现的

Springboot通过MessageSourceAutoConfiguration为我们自动配置好管理国际化资源文件的组件

先来看看这个类

@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(name = AbstractApplicationContext.MESSAGE_SOURCE_BEAN_NAME, search = SearchStrategy.CURRENT)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Conditional(ResourceBundleCondition.class)
@EnableConfigurationProperties
public class MessageSourceAutoConfiguration {

    private static final Resource[] NO_RESOURCES = {};

    @Bean
    @ConfigurationProperties(prefix = "spring.messages")
    public MessageSourceProperties messageSourceProperties() {
        return new MessageSourceProperties();
    }

    @Bean
    public MessageSource messageSource(MessageSourceProperties properties) {
        ...
    }
}

主要了解一下messageSource()这个方法

可以看到,此方法的参数为messageSourceProperties对象,来分析一下这个类:

public class MessageSourceProperties {

    /*逗号分隔的基名列表(本质上是完全限定的类路径)
      每个都遵循ResourcesBundle约定,并轻松支持基于斜杠的位置
      如果不包含全限定符(如:org.mypackage),他将从类路径根目录中解析*/
    private String basename = "messages";

    /**
	 * Message bundles encoding.
	 */
    private Charset encoding = StandardCharsets.UTF_8;

意思是:

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

因为我们自定义了国际化资源文件,因此我们需要在springboot配置文件application.propreties中加入以下配置指定我们配置文件的名称

spring.message

2.4、首页获取显示国际化

利用#{…}消息表达式,去首页index.html获取国际化的值

在这里插入图片描述

重启项目,访问首页,已经自动识别为中文

2.5、配置国际化组件实现中英文切换

2.5.1、添加中英文切换标签链接

index.html中底部可以看到两个标签

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

要通过这两个标签实现中英文切换,首先要在这两个标签上加跳转链接并带上响应参数

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

因此我们需要自定义地区解析器MyLocaleResolver中,需要处理这个带参数的链接请求

2.5.2、自定义地区解析器组件

LocaleResolver:地区解析器

WebMvcAutoConfiguration中,找到**localeResolver()**方法

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

  • 如果用户配置了则使用用户配置的地区解析器
  • 如用户没有配置,就用默认的
@Override
@Bean
@ConditionalOnMissingBean(name = DispatcherServlet.LOCALE_RESOLVER_BEAN_NAME)
public LocaleResolver localeResolver() {
    if (this.webProperties.getLocaleResolver() == WebProperties.LocaleResolver.FIXED) {
        return new FixedLocaleResolver(this.webProperties.getLocale());
    }
    AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
    localeResolver.setDefaultLocale(this.webProperties.getLocale());
    return localeResolver;
}

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


public class MyLocaleResolver implements LocaleResolver {
    //解析请求
    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        //获取请求中的国际化参数
        String language = request.getParameter("l");
        //默认的地址
        Locale locale = Locale.getDefault();
        //如果请求的链接参数不为空,携带了国际化参数
        if(!StringUtils.isEmpty(language)){
            String[] split = language.split("_");//zh_CN(语言_地区)
            locale = new Locale(split[0], split[1]);
        }
        return locale;
    }

    @Override
    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {

    }
}

为了我们的区域化信息能够生效,我们需要配置一下这个组件!在我们的MyMvcConfig配置类下添加bean

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    
    ...
        
    @Bean
    public LocaleResolver localeResolver(){
        return new MyLocaleResolver();
    }
}

我们重启项目,来访问一下,发现点击按钮可以实现切换!

4、登录功能实现

当我们点击登录按钮时,会进入一个界面(dashboard页面)

1、首先在index.html的表单中更改提交地址/user/login, 并给名称和密码输入框添加name属性为了后面传参

在这里插入图片描述

2、编写控制层的controller

@Controller
public class LoginController {

    @RequestMapping("/user/login")
    public String login(@RequestParam("username") String username, 
                        @RequestParam("passwrod") String password, 
                        Model model){
        if("admin".equals(username) && "123123".equals(password)){
            return "dashboard";
        }else{
            model.addAttribute("msg", "用户名或密码错误");
            return "index";
        }
    }
}

3、在index.html首页中,添加一个标签来显示从controller返回的登录错误信息

<p style="color: red" th:text="${msg}"></p>

重启,进行测试:

【注意: url泄露信息】

在这里插入图片描述

此时登录功能实现完毕,但是现在有一个大问题,浏览器的url暴露了用户的用户名和密码,泄露了用户信息,此时我们需要编写一个映射!

  • 我们在MyMvcConfig中加一句代码
registry.addViewController("/main.html").setViewName("dashboard");

​ 也就是访问main.html页面就跳转到dashboard页面

  • 然后修改LoginController,当登录成功后重定向到main.html页面,也就跳转到了dashboard页面
...
if("admin".equals(username) && "123123".equals(password)){
    return "redirect:/main.html";
}else{
...    

因为:

==原来是请求转发:==到dashboard,还是原来的请求,转发到dashboard页面

重定向后:是去请求mian.html,请求变了!

在这里插入图片描述

再次重新测试,输入正确的用户名和密码登录成功后,浏览器不在携带泄露信息。

【注意:拦截无权限访问】

出现了新的问题,不论登不登陆,我们访问localhost:8080/main.html都会跳转到dashhoard页面,此时就需要拦截器了。

5、登录拦截器

为了解决上述问题,我们需要自定义一个拦截器

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

登录成功后,后台会得到我们的用户信息;如果没有登录,则不会有任何用户信息。我们通过这一点来用拦截器进行拦截:

  • 将用户登录后的用户名信息放到session中,访问页面时首先判断session中有没有用户信息
  • 如果没有,拦截器进行拦截
  • 如果有,拦截器放行

1、存session信息

要先在LoginController中设计:用户登录成功后,存入用户信息到session中

@RequestMapping("/user/login")
public String login(@RequestParam("username") String username,
                    @RequestParam("password") String password,
                    Model model,
                    HttpSession session){
    if("admin".equals(username) && "123123".equals(password)){
        session.setAttribute("LoginUser", username);
        return "redirect:/main.html";
    }else{
        model.addAttribute("msg", "用户名或密码错误");
        return "index";
    }
}

2、自定义HandlerInterceptor接口的preHandle方法

2、再在config目录中新建一个自定义的LoginHanderInterceptor 类(继承HandlerInterceptor接口)

public class LoginHanderInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession();
        Object loginUser = session.getAttribute("LoginUser");

        //session中有LoginUser信息,放行
        if(loginUser != null){
            return true;
        }else{
        //session中没有LoginUser信息,就拒绝放行,并在请求上下文中放入msg信息,index的p标签提取
          ,请求转发到index.html页面
            request.setAttribute("msg", "权限不够,请先登录!");
            request.getRequestDispatcher("/index.html").forward(request,response);
            return false;
        }
    }
}

3、在配置类中注入bean

重写WebMvcConfigurer接口的addInterceptors方法

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new LoginHanderInterceptor())
        .addPathPatterns("/**")
        .excludePathPatterns("/index.html", "/", "/user/login", "/css/**", "/js/**", "/img/**");
}

与增加视觉控制器一样,通过addInterceptors方法添加你自定义的拦截器

  • 拦截器起作用路径:/**
  • 作用排除:"/index.html", "/", "/user/login", "/css/**", "/js/**", "/img/**"

6、展示员工信息

1、实现Customers视图跳转

需要在dashboard.html页面中的侧边栏,点击Customers链接跳转到用户信息列表页面

1、在templates目录下新建一个包:emp,用来放有关员工信息的页面,我们将list.html页面移入其中

2、编写controller,处理/emps请求,在controller包下,建立一个EmployeeController类

/***
     * 所有员工信息
     * @param model 视图解析器
     * @return 返回到 list 页面(list页面:显示所有员工信息)
     */
@RequestMapping("/emps")
public String list(Model model){
    Collection<Employee> allEmployee = employeeDao.getAllEmployee();
    model.addAttribute(allEmployee);

    return "emp/list";
}

3、修改list.html 和 dashboard.html中Customers链接请求路径

<a class="nav-link" th:href="@{/emps}">

重启主程序,登录到大神board页面中,再点击Customer,成功跳转到/emps

【问题】

  1. 点击Customer后,此处链接应该成高亮状态,但是这里点击后还是普通的样式,高亮点还在dashboard上
  2. list.html和dashboard.html页面的侧边栏和顶部栏是相同的,可以抽出来,共用!

2、提取页面公共部分

1、在templates目录下,新建common包(用来存放提取出来的公共部分)

在这里插入图片描述

2、dashboard.html和list.html中有公共部分代码(顶部栏、侧边栏部分)

  • 所以将其公共代码取出,放入common目录下的新建html文件:common.html中

  • 取出的标签中写上 : th:fragment="topbar" 、 th:fragment="sidepbar"

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">

<!--顶部导航栏,利用th:fragment提取出来,名为topbar-->
<nav th:fragment="topbar" class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0">
   ......
</nav>

<!--侧边栏,利用th:fragment提取出来,名为sidebar-->
<nav th:fragment="sidebar" class="col-md-2 d-none d-md-block bg-light sidebar">
   ......
</nav>

</html>

3、原代码中将提取部分删除掉,在原来你的地方插入common.html的代码

<body>
		<div th:insert="common/common::topbar"></div>

		<div class="container-fluid">
			<div class="row">
				<div th:insert="~{common/common::sidebar}"></div>
            </div>
            ....
</body>
  • 带不带~{}都可
  • th:insert 或 th:replace
  • 注意插入的文件与common.html的相对目录层级

3、点击高亮处理

在common.html中对链接进行判断

<a th:class="${active == 'dashboard.html'? 'nav-link active' : 'nav-link'}" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">

如果active是dashboard.html,class就等于nav-link active(高亮),否则定于nav-link

active的值从何而来?

在每次进入某个html页面后,插入的公共部分代码标签上传递对应的值,例如:

<!--侧边栏-->
<div th:replace="~{common/common::sidebar(active='list.html')}"></div>

进入list页面后,list.html的侧边栏代码在引入公共代码时向其传入参数,公共代码部分识别此参数,做出判断后,显示高亮或不高亮。

4、显示员工信息

1、EmployeeController中将查找出来的所有员工信息,放入model中

Collection<Employee> allEmployee = employeeDao.getAllEmployee();
model.addAttribute("emps", allEmployee);

2、前段将emps取出,在table中each遍历取出

<table class="table table-striped table-sm">
    <thead>
        <tr>
            <th>id</th>
            <th>lastName</th>
            <th>email</th>
            <th>gender</th>
            <th>department</th>
            <th>date</th>
        </tr>
    </thead>
    <tbody>
        <tr th:each="emp:${emps}">
            <td th:text="${emp.getId()}">
            <td th:text="${emp.getLastName()}">
            <td th:text="${emp.getEmail()}">
            <td th:text="${emp.getGender() == 1 ? '' : ''}">
            <td th:text="${emp.getDepartment().getDepartmentName()}">
            <td th:text="${#dates.format(emp.getDate(),'yyyy-MM-dd HH:mm:ss')}">
            </td>
        </tr>
    </tbody>
</table>

【注意】

日期格式转换:thymeleaf语法专门的转换格式#dates.format(emp.getDate(),'yyyy-MM-dd HH:mm:ss')

3、在员工列表每行中再加上两个按钮操作:编辑 、 删除

在此重启主程序测试,成功:

在这里插入图片描述

7、增加员工

【整体流程图】

在这里插入图片描述

1、list页面增加 添加员工 按钮

1、首先在list.html页面中,添加一个 增加员工的按钮,点击按钮后发起一个请求: /add

在这里插入图片描述

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

2、编写/emp对应的controller,在EmployeeController中添加一个toAdd方法用来处理list页面中的按钮提交动作,返回到add.html页面

/***
     * 获取所有departments信息
     * @param model 视图解析器
     * @return 跳转到add.html页面
     */
@GetMapping("/emp")
public String toAdd(Model model){
    Collection<Department> allDepartments = departmentDao.getAllDepartments();
    model.addAttribute("departments", allDepartments);

    return "emp/add";
}

【注意】

add.html中,有一个部分选项:需要前端获取到所有的departments信息,所以在toAdd方法中有两个作用:

  1. 将departments信息放入model中;
  2. 跳转到add.html界面

2、创建添加员工页面add

1、在templates/emp目录下新建add.html

2、我们复制list.html中的内容,修改掉中心内容信息,更改为我们的表格

<form th:action="@{/emp}" method="post">
    <div class="form-group">
        <label>LastName</label>
        <input type="text" name="lastName" class="form-control" placeholder="lastname:zsr">
    </div>
    <div class="form-group">
        <label>Email</label>
        <input type="email" name="email" class="form-control" placeholder="email:xxxxx@qq.com">
    </div>
    <div class="form-group">
        <label>Gender</label><br/>
        <div class="form-check form-check-inline">
            <input class="form-check-input" type="radio" name="gender" value="1">
            <label class="form-check-label"></label>
        </div>
        <div class="form-check form-check-inline">
            <input class="form-check-input" type="radio" name="gender" value="0">
            <label class="form-check-label"></label>
        </div>
    </div>
    <div class="form-group">
        <label>department</label>
        <!--注意这里的name是department.id,因为传入的参数为id-->
        <select class="form-control" name="department.id">
            <option th:each="department:${departments}" th:text="${department.getDepartmentName()}" th:value="${department.getId()}"></option>
        </select>
    </div>
    <div class="form-group">
        <label>Birth</label>
        <!--springboot默认的日期格式为yy/MM/dd-->
        <input type="text" name="date" class="form-control" placeholder="birth:yyyy/MM/dd">
    </div>
    <button type="submit" class="btn btn-primary">添加</button>
</form>

重启后看看

点击添加员工—>成功跳转到add.html页面

在这里插入图片描述

【注意】

department下拉框应该是所有的部分,是我们前端获取到departments后遍历显示得到

  • 注意后台接收的是employee对象,其中department属性是对象,所以前端不能name是department但是值是department.id,后端参数解析器会配置错误!
  • 直接让前端传入的是department.id,后端后自行实例化对象,只不过departmentName属性可能是NULL
<!--注意这里的name是department.id,因为传入的参数为id-->
<select class="form-control" name="department.id">
    <option th:each="department:${departments}" th:text="${department.getDepartmentName()}" th:value="${department.getId()}"></option>
</select>

3、add页面添加员工请求

在add.html页面,我们填写完信息,点击添加按钮后,应该完成添加返回到list页面,展示新的员工信息;

因此在add.html点击按钮的一瞬间,我们同样发起post请求/emp(restF风格)

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

然后编写对应的controller: EmployeeController下的add方法

/****
     * 增加新用户
     * @param employee 前端传入的用户信息,用employee接收
     * @return 跳转到list.html页面
     */
@PostMapping("/emp")
public String add(Employee employee){
    employeeDao.insert(employee);

    return "redirect:/emps";
}

注意增加后,重定向至emps,获取数据库中所用员工信息,后到list.html页面展示.

重启后测试:

在这里插入图片描述

点击添加按钮,成功实现添加员工

在这里插入图片描述

8、修改员工信息

1、list页面编辑按钮,添加请求

点击编辑后,应该跳转到edit.html进行编辑

  1. 首先就是要将list.html的标签添加href属性,实现点击请求/edit/id号 (restFul风格)
<a th:href="@{/edit/${emp.getId()}}" style="color: white ; border-radius: 50px" class="btn btn-sm btn-primary">编辑</a>
  1. 然后编写对应的controller,在EmployeeController类下添加新的方法叫edit来处理list页面点击编辑后的操作,返回到edit.html编辑员工页面
 /***
     * restful风格接收参数
     * @param id list编辑按键的请求中带有的参数
     * @param model 视图解析器
     * @return 跳转到编辑界面
     */
    @RequestMapping("/edit/{id}")
    public String edit(@PathVariable("id") Integer id, Model model){
        //查询指定id的员工,添加到employee中,用于前端接收
        Employee employee = employeeDao.getEmployeeByID(id);
        model.addAttribute("employee", employee);

        //查出所有部分的信息,添加到departments中,用于前端接收(和add一样)
        Collection<Department> allDepartments = departmentDao.getAllDepartments();
        model.addAttribute("departments", allDepartments);

        return "/emp/edit";
    }

2、创建编辑员工页面edit

edit.html

修改处:

  • th:value="${employee.getLastName()}"提前放值,不同类型的标签,属性不同
  • th:checked="${employee.getGender() == 1}"
  • th:selected="${department.getId() == employee.getDepartment().getId()}"
<form th:action="@{/edit}" method="post">
    <div class="form-group">
        <label>LastName</label>
        <input th:value="${employee.getLastName()}" type="text" name="lastName" class="form-control" placeholder="lastname:zsr">
    </div>
    <div class="form-group">
        <label>Email</label>
        <input th:value="${employee.getEmail()}" type="email" name="email" class="form-control" placeholder="email:xxxxx@qq.com">
    </div>
    <div class="form-group">
        <label>Gender</label><br/>
        <div class="form-check form-check-inline">
            <input th:checked="${employee.getGender() == 1}"  value="1" class="form-check-input" type="radio" name="gender" value="1">
            <label class="form-check-label"></label>
        </div>
        <div class="form-check form-check-inline">
            <input th:checked="${employee.getGender()==0}" value="0" class="form-check-input" type="radio" name="gender" value="0">
            <label class="form-check-label"></label>
        </div>
    </div>
    <div class="form-group">
        <label>department</label>
        <!--注意这里的name是department.id,因为传入的参数为id-->
        <select class="form-control" name="department.id">
            <option th:each="department:${departments}"
                    th:selected="${department.getId() == employee.getDepartment().getId()}"
                    th:text="${department.getDepartmentName()}" 
                    th:value="${department.getId()}">
            </option>
        </select>
    </div>
    <div class="form-group">
        <label>Birth</label>
        <!--springboot默认的日期格式为yy/MM/dd-->
        <input th:value="${employee.getDate()}" type="text" name="date" class="form-control" placeholder="birth:yyyy/MM/dd">
    </div>
    <button type="submit" class="btn btn-primary">修改</button>
</form>

启动主程序测试:

在这里插入图片描述

【注意】

要将日期格式提前修改

 <input th:value="${#dates.format(employee.getDate(), 'yyyy-MM-dd')}" type="text" name="date" class="form-control" placeholder="birth:yyyy/MM/dd">

【注意:修改employee的date属性格式】

@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date date;

使其能够兼容得到前端传回的时间格式参数。

3、edit页面编辑完成提交请求

在edit.html点击修改按钮后,我们需要返回到list页面,更新员工信息,因此我们需要添加href属性,实现点击按钮后的请求:/editEmp

<form th:action="@{/editEmp}" method="post">

编写对应的controller,处理修改按钮的请求, editEmp方法

/***
     * 处理edit按键的请求
     * @param employee 前端传递来的参数
     * @return 重定向到/emps,刷新列表
     */
    @RequestMapping("/editEmp")
    public String editEmp(Employee employee){
        employeeDao.insert(employee);

        return "redirect:/emps";
    }
【注意:修改时隐藏提交id】

如果按照add.html样式提交修改后的信息,向后端传入的参数中id=null,后端接收到的employee对象因此没有id值,就会触发自增id条件,生成了新的用户。

在这里插入图片描述

所以,需要在edit.html的from表单中添加隐藏提交值

<input type="hidden" name="id" th:value="${employee.getId()}">

然后点击修改后,正常完成修改,并返回到list.html页面。

4、删除员工信息

给list中的删除标签写请求(注意写法)

<a th:href="@{/delete/{id}(id=${emp.getId()})}" style="color: white; border-radius: 50px" class="btn  btn-sm btn-danger">删除</a>
【注意:restFul风格的thymeleaf请求风格】

{id}(id=${…})—参数给值

然后编写controller,处理删除标签的请求,删除指定id的员工

 /***
     * 处理delete请求
     * @param id 指定员工id
     * @return 重定向到emps,刷新列表
     */
    @RequestMapping("/delete/{id}")
    public String deleteEmp(@PathVariable("id") Integer id){
        employeeDao.deleteEmployeeByID(id);

        return "redirect:/emps";
    }

重新启动后测试,成功删除,刷新页面。

9、 404页面定制

只需要在templates目录下新建一个error包,然后将404.html放入其中,报错Springboot就会自动找到这个页面

测试:随便访问一个不存在的页面

在这里插入图片描述

出现的404页面即是我们自己的404.html

10、注销操作

在common页面中,修改顶部导航栏标签的href属性,实现点击发起请求/logout

<li class="nav-item text-nowrap">
            <a class="nav-link" th:href="@{/logout}">Sign out</a>
</li>

然后编写对应的controller,处理点击注销的请求,在LoginController中编写方法,清除session,重定向到首页

/***
     * 注销用户session
     * @param session HttpSession
     * @return 重定向到:index.html
     */
    @RequestMapping("/logout")
    public String signout(HttpSession session){
        session.invalidate();

        return "redirect:index.html";
    }

重新测试,登录成功后,点击sign out退出首页。

员工id
* @return 重定向到emps,刷新列表
*/
@RequestMapping("/delete/{id}")
public String deleteEmp(@PathVariable(“id”) Integer id){
employeeDao.deleteEmployeeByID(id);

    return "redirect:/emps";
}

重新启动后测试,成功删除,刷新页面。



# 9、 404页面定制

只需要在templates目录下新建一个error包,然后将404.html放入其中,报错Springboot就会自动找到这个页面



测试:随便访问一个不存在的页面

[外链图片转存中...(img-VdUALG20-1642820791754)]

出现的404页面即是我们自己的404.html



# 10、注销操作

在common页面中,修改顶部导航栏标签的href属性,实现点击发起请求/logout

```html
<li class="nav-item text-nowrap">
            <a class="nav-link" th:href="@{/logout}">Sign out</a>
</li>

然后编写对应的controller,处理点击注销的请求,在LoginController中编写方法,清除session,重定向到首页

/***
     * 注销用户session
     * @param session HttpSession
     * @return 重定向到:index.html
     */
    @RequestMapping("/logout")
    public String signout(HttpSession session){
        session.invalidate();

        return "redirect:index.html";
    }

重新测试,登录成功后,点击sign out退出首页。

doc文档,5号字体,共48页。 贴出目录部分: 第一部分 MS-系统维护 5 一、 公司注册资料(MSCompanyUser) 5 二、 组织机构(MSDepartmemt, MSPostionClass, MSPostion,MSEmployee) 6 三、 权限登记 (MSPermissions) 8 四、 权限分类(MSPermissionsClass) 8 五、 用户定义(MSUser) 9 七、 登陆管理(MSLogin) 10 八、 管理期间(MSPeriod) 10 九、 单据表名称(MSBillTable ) 11 十、 凭单引用(主要进行查询) 11 第二部分 DA-基本资料 11 十一、 币种资料(MSCurrency) 11 十二、 资金帐户(FNAccounts) 12 十三、 会计科目(DAAccountCode) 12 十四、 属性字典(DAAttribute) 13 十五、 仓库货位(STWarehouse) ) 13 十六、 货品资料(DAGoodsClass, DAGoods) 14 十七、 使用单位(MSUnits ,MSGoodsUnits) 14 十八、 单据类型表(DABillType ) 15 十九、 费用资料(DAExpense ) 16 二十、 客户资料(DAArea, DAClient) 16 二十一、 厂商资料(DAArea, DAClient) 17 二十二、 工程资料( DAProject) 18 二十三、 结算方式(POClear) 18 二十四、 联系人(DALinkMen) 18 第三部分 SL-销售管理 22 二十五、 销售合同(SLContract) 22 二十六、 销售订单(SLOrderMaster, SLOrderDetail) 23 二十七、 销售开单(SLSaleMaster, SLSaleDetail) 24 二十八、 销售结算(FNClearSLMaster, FNClearSLDetail) 26 二十九、 销售出库(SLGoodsOutMaster,SLGoodsOutDetail) 28 三十、 销售退货(用销售开单表) 29 三十一、 客户信用(SLCredit) 29 三十二、 商品售价(SLSalePrice) 29 三十三、 合同售价(SLContractPriceMaster, SLContractPriceDetail) 30 三十四、 销售折扣(SLDiscount) 31 三十五、 商品赠送(SLSaleGift) 31 三十六、 送货登记(SLDeliverMaster, SLDeliverDetail) 32 三十七、 连锁加盟销售(SLSaleClientMaster,SLSaleClientDetail) 33 三十八、 销售排行榜(SLSaleFruitList模块,PCPurchaseFruitList模块) 33 三十九、 连锁加盟排行(SLSaleChainList模块) 33 第四部分 PC-采购管理(部表与销售模块对应的表结构一致) 33 四十、 采购合同(PCContract) 33 四十一、 采购订单(PCOrderMaster, PCOrderDetail) 33 四十二、 采购进货(PCPurchaseMaster, PCPurchaseDetail) 33 四十三、 采购结算(FNClearMaster, FNClearDetail) 34 四十四、 采购入库(PCGoodsInMaster,PCGoodsInDetail) 34 四十五、 采购退货(PCPurchaseMaster, PCPurchaseDetail) 34 四十六、 提货登记(PCDeliverMaster, PCDeliverDetail) 34 四十七、 采购信用(PCCredit) 34 四十八、 商品进价(PCPurchasePrice) 34 四十九、 合同进价(PCContractPriceMaster, PCContractpriceDetail) 34 第五部分 ST-库存管理 34 五十、 存货计价方式(STStockCostMode--) 34 五十一、 销售出库( , ) 35 五十二、 采购入库( , ) 35 五十三、 生产出库(YDGoodsOutMaster, YDGoodsOutDetail) 35 五十四、 生产入库(YDGoodsInMaster, YDGoodsInDetail) 35 五十五、 货品调拨(STGoodsOutInMaster, STGoodsOutInDetail) 35 五十六、 盘盈盘亏(STGoodsCountOffMaster, STGoodsCountOffDetail) 35 五十七、 库存结帐(存货成本结算)(STGoodsOutCostMaster, STGoodsOutCostDetail) 35 五十八、 采购成本核算 (STPCGoodsInCostMaster, STPCGoodsInCostDetail) 35 五十九、 领料成本核算 (STPCGoodsInCostMaster, STPCGoodsInCostDetail) 37 六十、 外发成本核算 (STPCGoodsInCostMaster, STPCGoodsInCostDetail) 37 六十一、 生产成本核算 (STPCGoodsInCostMaster, STPCGoodsInCostDetail) 37 六十二、 销售成本核算 (STPCGoodsInCostMaster, STPCGoodsInCostDetail) 37 六十三、 库存变动( 查询库存变动资料 ) 38 第六部分 FN-财务管理 38 六十四、 收款申请 (FNCashInMaster,FNCashInDetail) 38 六十五、 付款申请(FNCashOutMaster,FNCashOutDetail) 38 六十六、 报销申请(FNExpenseMaster, FNExpenseDetail) 38 六十七、 资金调动(FNCashOutInMaster, FNCashOutInDetail) 38 六十八、 外币兑换(FNCashExchangeMaster, FNCashExchangeDetail) 38 六十九、 收款结算(销售结算) 38 七十、 付款结算(采购结算) 38 七十一、 会计凭证(FNVoucherMaster, FNVoucherDetail) 38 七十二、 应收应付( 查询 ) 39 七十三、 其它应收款( 查询 ) 39 七十四、 资金帐本( 查询 ) 39 七十五、 外币台帐(查询) 39 七十六、 现金流量( 查询 ) 40 七十七、 待摊预提(FNAmortizeExpect) 40 七十八、 帐龄报表( ) 40 七十九、 经营费用( ) 40 八十、 营业利润( ) 40 八十一、 资产负债( ) 40 第七部分 OA-办公管理 40 八十二、 公司新闻(OACompanyNews) 40 八十三、 工作安排(OAJobArrange) 41 八十四、 邮件收发(OAEmail) 41 八十五、 工作日志(OAJobRecords ) 41 八十六、 客户关系(???) 42 八十七、 厂商关系(???) 42 第八部分 YD-生产管理 42 八十八、 物料清单(生产配方/产品配方)( YDFormulaMaster, YDFormulaDetail) 42 八十九、 生产能力(YDProductPower) 43 九十、 生产计划(YDProductPlanMaster, YDProductPlanDetail) 43 九十一、 生产通知(YDProductNoteMaster, YDProductNoteDetail) 43 九十二、 采购计划 (YDPurchasePlanMaster, YDPurchasePlanDetail) 43 九十三、 生产领料(与销售出库表一致) 44 九十四、 生产入库(与采购入库表一致) 44 九十五、 生产日报( 查询 ) 44 九十六、 生产统计( 查询 ) 44 九十七、 车间库存(主要查询结果) 44 九十八、 物料还原(根据物料清单和入库凭单还原物料) 44 第九部分 RP-报表管理 44 九十九、 报表管理器( ) 44 百、 自定义报表( ) 44 第十部分 PS-人事管理 44 第十一部分 SR-工资管理 44 百一、 工作时段(SRWorkTimeMaster, SRWorkTimeDetail) 44 百二、 作息时间(SRWorkScheduleMaster, SRWorkScheduleDetail) 44 百三、 生产排班(SRWorkRestMaster, SRWorkRestDetail) 44 百四、 计件项目(SRJobs) 44 百五、 计件工价(SRJobsPriceMaster, SRJobsPriceDetail) 45 百六、 计件统计(SRWorkQuantityMaster, SRWorkQuantityDetail) 45 百七、 计时统计(SRWorkTimeCntMaster, SRWorkTimeCntDetail) 45 百八、 请假调班(SRLeaveReptMaster, SRSRLeaveReptDetail) 45 百九、 工资核算表(SRBaseSalaryMaster, SRBaseSalaryDetail) 45 百十、 工资分析(对SRBaseSalaryMaster, SRBaseSalaryDetail的查询统计) 46 第十二部分 EG-工程管理 46 百十一、 工程合同(EGContractMaster, EGContractDetail) 46 百十二、 工程结算(FNClearEGMaster, FNClearEGDetail) 46 百十三、 工程计划(EGContractPlanMaster, EGContractPlanDetail) 46 百十四、 工程进度(EGProjectProgressMaster, EGProjectProgressDetail) 47 百十五、 工程监管(EGProjectCtrlMaster, EGProjectCtrlDetail) 47 百十六、 来料加工( , ) 47 百十七、 来料加工核销( , ) 47 百十八、 外委加工( , ) 47 百十九、 外委加工核销( , ) 47 第十三部分 FA-资产管理 47 百二十、 资产增加(FAAssetAddMaster, FAAssetAddDetail) 47 百二十一、 资产折旧(FADepreciationMaster, FADepreciationDetail) 47 百二十二、 资产处置(FAAssetReduceMaster, FAAssetReduceDetail) 47 百二十三、 资产维修(FAAssetRepairMaster, FAAssetRepairDetail) 47 百二十四、 维修计划(FAAssetRePlanMaster, FAAssetRePlanDetail) 48 百二十五、 资产总表(主要查询,窗体FAAssetRept) 48 百二十六、 资产变动(主要查询,窗体FAAssetChange) 48 百二十七、 计划管理(主要查询,窗体FAAssetPlanRept) 48 第十四部分 DS-决策支持 48
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值