1. 导入静态资源
- 页面直接放在tempaltes里
- 其他静态资源放在static里面(如css,js,img等)
2. 模拟数据库
用java写数据库数据以及数据库操作(不外连数据库时的操作)
- pojo
department.java
package com.example.employeesystem.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
//部门表
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Department {
private Integer id;
private String departmentName;
}
employee.java
package com.example.employeesystem.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
//员工表
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee {
private Integer id;
private String lastName;
private String email;
private Integer gender; // 0:女 1:男
private Department department;
private Date birth;
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 = new Date();
}
}
- Dao
DepartmentDao.java
package com.example.employeesystem.dao;
import com.example.employeesystem.pojo.Department;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
//部门dao
@Repository
public class DepartmentDao {
//模拟数据库中的数据
private static Map<Integer, Department>deparments = null;
static{
deparments = new HashMap<Integer,Department>(); // 创建一个部门表
deparments.put(101,new Department(101,"教学部"));
deparments.put(102,new Department(102,"市场部"));
deparments.put(103,new Department(103,"教研部"));
deparments.put(104,new Department(104,"运营部"));
deparments.put(105,new Department(105,"后勤部"));
}
//数据库操作
//获得所有部门信息
public Collection<Department>getDepartments(){
return deparments.values();
}
//通过id得到部门
public Department getDepartmentById(Integer id){
return deparments.get(id);
}
}
EmployeeDao.java
package com.example.employeesystem.dao;
import com.example.employeesystem.pojo.Department;
import com.example.employeesystem.pojo.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Repository
public class EmployeeDao {
//模拟数据库中的数据
private static Map<Integer, Employee> employees = null;
//员工有所属的部门
@Autowired
private DepartmentDao departmentDao;
static{
employees = new HashMap<Integer,Employee>(); // 创建一个部门表
employees.put(1001,new Employee(1001,"小明","123456@qq.com",1,new Department(101,"教学部")));
employees.put(1002,new Employee(1002,"小王","123556@qq.com",1,new Department(102,"市场部")));
employees.put(1003,new Employee(1003,"小美","123656@qq.com",0,new Department(101,"教学部")));
employees.put(1004,new Employee(1004,"小张","123756@qq.com",1,new Department(102,"市场部")));
employees.put(1005,new Employee(1005,"小李","123856@qq.com",0,new Department(105,"后勤部")));
}
//主键自增
private static Integer initId =1006;
//增加一个员工
public void save(Employee employee){
if (employee.getId()==null){
employee.setId(initId++);
}
employee.setDepartment(departmentDao.getDepartmentById(employee.getDepartment().getId()));
employees.put(employee.getId(),employee);
}
//查询全部员工信息
public Collection<Employee>getAll(){
return employees.values();
}
//通过id查询员工
public Employee getEmployeeById(Integer id){
return employees.get(id);
}
//删除员工通过id
public void delete(Integer id){
employees.remove(id);
}
}
3.跳转页面,设置主页
在config中自定义一个自己的mvcconfig
MyMvcConfig.java
package com.example.employeesystem.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//直接/和/index.html都会走到index页面去
registry.addViewController("/").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
}
这样直接进入localhost:8080/就是首页了
4.国际化
-
编码所有的都改成utf-8
-
写中英文配置(login.properties,login_en_US.properties, login_zh_CN.properties)
-
在index.html里设置 th:text"#{message}"
-
自定义一个国际化配置,并且注入到容器才能生效
MyLocaleResolver.java
package com.example.employeesystem.config;
import org.springframework.web.servlet.LocaleResolver;
import org.thymeleaf.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
public class MyLocaleResolver implements LocaleResolver {
//解析请求
@Override
public Locale resolveLocale(HttpServletRequest httpServletRequest) {
//获取请求中的语言参数
String language = httpServletRequest.getParameter("l");
Locale locale = Locale.getDefault(); //如果没有就使用默认
//如果请求的链接携带了国际化参数
if (!StringUtils.isEmpty(language)){
//zh_CN
String[] split = language.split("_");
//国家、地区
locale = new Locale(split[0], split[1]);
}
return locale;
}
@Override
public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
}
}
注入进容器
MyMvcConfig.java
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
5. 登录功能实现和登录拦截器
- 登录功能实现
从前端开始,index.html
<form class="form-signin" th:action="@{/user/login}">
根据要跳转的去写接口,loginController
package com.example.employeesystem.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.thymeleaf.util.StringUtils;
import javax.servlet.http.HttpSession;
@Controller
public class LoginController {
@RequestMapping("/user/login")
public String login(@RequestParam("username") String username, @RequestParam("password") String password
, Model model, HttpSession session){
//具体业务
if (!StringUtils.isEmpty(username)&&"123456".equals(password)){
session.setAttribute("loginUser",username);
return "redirect:/main.html";
}else {
//告诉用户,你登录失败
model.addAttribute("msg","用户名或者密码错误!");
return "index";
}
}
}
- 要判断一下用户名和密码
- 登录失败的时候,返回到主页,还要弹出来一个告诉你用户名和密码错误的信息,这是在页面显示的
<!-- 如果msg为空则不显示这个红色消息,如果不为空(登录失败),则会显示出红色msg-->
<p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
- 直接输入账号密码登录进主页,但是用户名和密码会暴露出来,所以可以映射一下,通过自己设置的视图转发器,让登录进去转发到main.html,然后设置/main.html同样进入
registry.addViewController("/main.html").setViewName("dashboard");
- 登录拦截功能
通过session,获取到session就说明输入了用户名和密码,如果没有获取,就拦截
做一个拦截器
package com.example.employeesystem.config;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//登录成功后,应该有用户的session
Object loginUser = request.getSession().getAttribute("loginUser");
if (loginUser==null){
request.setAttribute("msg","没有权限,请先登录");
request.getRequestDispatcher("/index.html").forward(request,response);
return false;
}else {
return true;
}
}
}
然后在自己的自定义mvc配置中重写
@Override
public void addInterceptors(InterceptorRegistry registry) {
//要拦截的页面,除了哪些不拦截
registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**").excludePathPatterns("/index.html","/","/user/login"
,"/css/*","/js/**","/img/**");
}
这样就可以实现登录拦截功能了。
6.员工管理系统
1、展示员工列表
- 使点击到员工管理或者点击到首页时,会分别有高亮,而不是高亮一直在首页
<!-- 传递参数给组件-->
<div th:replace="~{common::sidebar(active='main.html')}"></div>
<div th:replace="~{common::sidebar(active='list.html')}"></div>
<a th:class="${active=='main.html'?'nav-link active':'nav-link'}" th:href="@{/index.html}">
<a th:class="${active=='list.html'?'nav-link active':'nav-link'}"th:href="@{/emps}">
- 在前端获取到后端的数据,并且遍历出来
<thead>
<tr>
<th>id</th>
<th>lastName</th>
<th>email</th>
<th>gender</th>
<th>department</th>
<th>birth</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr th:each="emp:${emps}">
<td th:text="${emp.getId()}"></td>
<td th:text="${emp.getLastName()}"></td>
<td th:text="${emp.getEmail()}"></td>
<td th:text="${emp.getGender()==0?'女':'男'}"></td>
<td th:text="${emp.department.getDepartmentName()}"></td>
<td th:text="${#dates.format(emp.getBirth(),'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>
2、增加员工实现
- 从列表页面中,点击按钮去添加页面
<a class="btn btn-sm btn-success" th:href="@{/emp}">添加</a>
- 写去到添加页面的请求
@GetMapping("/emp")
public String toAddpage(Model model){
//查出所有部门信息
Collection<Department> departments = departmentDao.getDepartments();
model.addAttribute("departments",departments);
return"add";
}
- 写add页面,其他内容和list页面一样,只是中间需要一个添加的表单,post请求提交添加按钮
<form th:action="@{/emp}" method="post">
<div class="form-group">
<label >LastName</label>
<div class="col-sm-10">
<input type="text" name="lastName" class="form-control" placeholder="LastName">
</div>
</div>
<div class="form-group">
<label >Email</label>
<div class="col-sm-10">
<input type="email" name="email" class="form-control" placeholder="Email">
</div>
</div>
<div class="form-group">
<label >Gender</label>
<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>
<div class="col-sm-10">
<!-- 我们在controller层接收的是一个Employee,所以我们需要提交的是其中的一个属性-->
<select class="form-control" name="department.id">
<option th:each="dept:${departments}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"></option>
</select>
</div>
</div>
<div class="form-group">
<label >Birth</label>
<div class="col-sm-10">
<input type="text" name="birth" class="form-control" placeholder="Birth">
</div>
</div>
<div class="form-group">
<div class="col-sm-10">
<button style="display:block;margin:0 auto" type="submit" class="btn btn-success">确认添加</button>
</div>
</div>
</form>
- 写前端提交过去的请求,并且返回到list页面
@PostMapping("/emp")
public String add(Employee employee){
employeeDao.save(employee);//调用底层业务方法保存员工信息
return"redirect:/emps";
}
3、修改员工信息
- 从list页面提交去修改页面的按钮,发送请求
- 携带参数的提交,注意用拼接
<a class="btn btn-sm btn-primary" th:href="@{/emp/}+${emp.getId()}">编辑</a>
- 后端写接收去到修改页面的请求,返回到修改页面
//去到员工的修改页面
@GetMapping("/emp/{id}")
public String toUpdate(@PathVariable("id")Integer id,Model model){
//查出原来的数据
Employee employeeById = employeeDao.getEmployeeById(id);
model.addAttribute("emp",employeeById);
Collection<Department> departments = departmentDao.getDepartments();
model.addAttribute("departments",departments);
return "update";
}
- 写修改页面,其他样式都一样,主要是一个表单内容
<form th:action="@{/update}" method="post">
<!--添加一个隐藏域属性的id,这样就不会和添加一样了 -->
<input type="hidden" name="id" th:value="${emp.getId()}">
<div class="form-group">
<label >LastName</label>
<div class="col-sm-10">
<input type="text" th:value="${emp.getLastName()}" name="lastName" class="form-control" placeholder="LastName">
</div>
</div>
<div class="form-group">
<label >Email</label>
<div class="col-sm-10">
<input type="email" th:value="${emp.getEmail()}" name="email" class="form-control" placeholder="Email">
</div>
</div>
<div class="form-group">
<label >Gender</label>
<div class="form-check form-check-inline" >
<input th:checked="${emp.getGender()==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="${emp.getGender()==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>
<div class="col-sm-10">
<!-- 我们在controller层接收的是一个Employee,所以我们需要提交的是其中的一个属性-->
<select class="form-control" name="department.id">
<option th:selected="${dept.getId()==emp.getDepartment().getId()}" th:each="dept:${departments}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"></option>
</select>
</div>
</div>
<div class="form-group">
<label >Birth</label>
<div class="col-sm-10">
<input th:value="${#dates.format(emp.getBirth(),'yyyy-MM-dd HH:mm')}" type="text" name="birth" class="form-control" placeholder="Birth">
</div>
</div>
<div class="form-group">
<div class="col-sm-10">
<button style="display:block;margin:0 auto" type="submit" class="btn btn-success">确认修改</button>
</div>
</div>
</form>
- 后端写提交修改的请求,并返回到列表
@PostMapping("/update")
public String update(Employee employee){
employeeDao.save(employee);//调用底层业务方法保存员工信息
return "redirect:/emps";
}
- 关于日期默认是斜杠方式,修改可以在application.properties中修改
#时间日期格式化
spring.mvc.date-format=yyyy-MM-dd
4、删除员工实现
- list页面内提交删除的请求
<a class="btn btn-sm btn-danger" th:href="@{/delemp/}+${emp.getId()}">删除</a>
- 后端接收删除请求,并返回到列表页面去
//删除员工
@GetMapping("/delemp/{id}")
public String toDelete(@PathVariable("id")Integer id){
employeeDao.delete(id);
return "redirect:/emps";
}
7.如何写一个网站
- 前端:
- 模板:别人写好的,我们拿来改成自己需要的
- 框架、组件: 自己动手组合拼接! Bootstrap ,Layui,semantic-ui
- 栅格系统
- 导航栏
- 侧边栏
- 表单
-
设计数据库(难点)
-
前端让它能够自动运行,独立化工程
-
数据接口如何对接:json,对象 all in one
-
前后端联调测试
-
自己需要的准备的东西
-
有一套自己熟悉的后台模板:工作必要!x-admin
-
前端界面:至少自己能够通过前端框架,组合出来一个网站页面
- index
- about
- blog
- post
- user
-
让这个网站能够独立运行!
-
多练习