SpringBoot之Web应用(未使用数据库)
Web应用(未使用数据库)编写Web前准备静态资源导入问题在springboot中,我们可以使用以下方式处理静态资源https://www.webjars.org/webjarslocalhost:8080/webjars/示例(导入依赖):<dependency><groupId>org.webjars.npm</groupId><artifactId&
Web应用(未使用数据库)
编写Web前准备
静态资源导入问题
-
在springboot中,我们可以使用以下方式处理静态资源
https://www.webjars.org/
-
webjars localhost:8080/webjars/
示例(导入依赖):
<dependency> <groupId>org.webjars.npm</groupId> <artifactId>jquery</artifactId> <version>3.6.0</version> </dependency>
-
在resources目录下的resources、static、public包 localhost:8080/
-
-
优先级:resources>static(默认)>public
-
在templates目录下的所有页面,只能通过controller来跳转(需要模板引擎的支持)
模板引擎
与springmvc中的视图解析器相识,可以让controller访问template下的html页面
thymeleaf
官方使用文档:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#attribute-precedence
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
-
导入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
-
在需要使用的html页的标签后加上约束
<html lang="en" xmlns:th="http://www.thymeleaf.org">
-
更多语法可以查看官方文档
修改mvc的默认配置
比如默认的时间格式等等
首页配置和国际化
首页配置
页面的所有静态资源都需要使用thymeleaf接管
使用thymeleaf需要先在头部导入约束
访问url需要使用 @{}
# 关闭模板引擎的缓存
spring.thymeleaf.cache=false
# 我们的配置文件的真实位置
spring.messages.basename=i18n.login
#时间日期格式化
spring.mvc.format.date=yyyy-MM-dd
国际化
示例为将首页国际化
-
配置i18n文件(在resources目录下创建i18n目录,然后再创建如下文件)
login.properties
login.btn=登录 login.password=密码 login.remember=记住我 login.tip=请登录 login.username=用户名
login_en_US.properties
login.btn=Sign in 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=用户名
-
编写application.properties文件,进行配置
# 我们的配置文件的真实位置 spring.messages.basename=i18n.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="@{/css/bootstrap.min.css}" rel="stylesheet"> <!-- Custom styles for this template --> <link th:href="@{/css/signin.css}" rel="stylesheet"> </head> <body class="text-center"> <form class="form-signin" action="dashboard.html"> <img class="mb-4" th:src="@{/img/bootstrap-solid.svg}" alt="" width="72" height="72"> <h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1> <label class="sr-only">Username</label> <input type="text" class="form-control" th:placeholder="#{login.username}" required="" autofocus=""> <label class="sr-only">Password</label> <input type="password" class="form-control" th:placeholder="#{login.password}" required=""> <div class="checkbox mb-3"> <label> <input type="checkbox" value="remember-me">[[#{login.remember}]] </label> </div> <button class="btn btn-lg btn-primary btn-block" type="submit">[[#{login.btn}]]</button> <p class="mt-5 mb-3 text-muted">© 2017-2018</p> <a class="btn btn-sm" th:href="@{/index(l='zh_CN')}">中文</a> <a class="btn btn-sm" th:href="@{/index(l='en_US')}">English</a> </form> </body> </html>
-
在config包下创建MyLocaleResolver
public class MyLocaleResolver implements LocaleResolver { //解析请求 @Override public Locale resolveLocale(HttpServletRequest request) { //获取请求中的语言参数 String language = request.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 request, HttpServletResponse response, Locale locale) { } }
-
在config包下创建MyMvcConfig,将MyLocaleResolver载入spring容器中
@Configuration public class MyMvcConfig implements WebMvcConfigurer { //自定义的国际化组件就生效了 @Bean public LocaleResolver localeResolver(){ return new MyLocaleResolver(); } }
-
检查Controller(检查是否能够访问index)
@Controller public class IndexController { //地址栏访问这两个路径都可以访问首页 @RequestMapping({"/","/index"}) public String index(){ return "index"; } }
-
测试
登录功能的实现
-
编写controller
@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); System.out.println("成功"); return "redirect:/main"; }else { model.addAttribute("msg","用户名或者密码错误"); System.out.println("错误"); return "index"; } } @RequestMapping("/main") public String dashboard(){ return "dashboard"; } }
-
修改html页面中的表单action,判断msg返回值是否未空
<form class="form-signin" th:action="@{/user/login}" method="post"> <img class="mb-4" th:src="@{/img/bootstrap-solid.svg}" alt="" width="72" height="72"> <h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1> <!-- 如果msg的值为空,则不显示消息--> <p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p> <label class="sr-only">Username</label> <input type="text" name="username" class="form-control" th:placeholder="#{login.username}" required="" autofocus=""> <label class="sr-only">Password</label> <input type="password" name="password" class="form-control" th:placeholder="#{login.password}" required=""> <div class="checkbox mb-3"> <label> <input type="checkbox" value="remember-me">[[#{login.remember}]] </label> </div> <button class="btn btn-lg btn-primary btn-block" type="submit">[[#{login.btn}]]</button> <p class="mt-5 mb-3 text-muted">© 2017-2018</p> <a class="btn btn-sm" th:href="@{/index(l='zh_CN')}">中文</a> <a class="btn btn-sm" th:href="@{/index(l='en_US')}">English</a> </form>
编写拦截器
-
在config目录下创建LoginHandlerInterceptor类
public class LoginHandlerInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Object loginUser = request.getSession().getAttribute("loginUser"); if(loginUser==null){ request.setAttribute("msg","没有权限,请先登录"); request.getRequestDispatcher("/").forward(request,response);; return false; }else { return true; } } }
-
在MyMvcConfig类中配置拦截器到spring容器中
@Configuration public class MyMvcConfig implements WebMvcConfigurer { public void addInterceptors(InterceptorRegistry registry){ registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**").excludePathPatterns("/","/index","/user/login","/css/**","/img/**","/js/**"); } }
-
测试
展示员工列表
实体类
Department
@Data
@AllArgsConstructor
@NoArgsConstructor
//部门表
public class Department {
private Integer id;
private String departmentName;
}
Employee
@Data
@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
@Repository
public class DepartmentDao {
//模拟数据库中的数据
private static Map<Integer, Department> departments=null;
static {
departments=new HashMap<Integer, Department>();//创建一个部门表
departments.put(101,new Department(101,"教学部"));
departments.put(102,new Department(102,"市场部"));
departments.put(103,new Department(103,"教研部"));
departments.put(104,new Department(104,"运营部"));
departments.put(105,new Department(105,"后勤部"));
}
//获得所有部门信息
public Collection<Department> getDepartments(){
return departments.values();
}
//通过id得到部门
public Department getDepartmentById(Integer id){
return departments.get(id);
}
}
EmployeeDao
@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,"AA","A123456789@qq.com",0,new Department(101,"教学部")));
employees.put(1002,new Employee(1002,"BB","B123456789@qq.com",1,new Department(102,"市场部")));
employees.put(1003,new Employee(1003,"CC","C123456789@qq.com",0,new Department(103,"教研部")));
employees.put(1004,new Employee(1004,"DD","D123456789@qq.com",1,new Department(104,"运营部")));
employees.put(1005,new Employee(1005,"EE","E123456789@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);
}
}
提取公共页面
-
在需要提取出来的标签中加入如下语句
th:fragment="sidebar"
-
在需要引用的位置加入如下语句
commons/commons为commons路径下的comoms.html文件
sidebar为自定义的名字
后面括号内的为需要传参的值
<div th:insert="~{commons/commons::sidebar(active='main.html')}"></div>
-
另一页面接收判断值
使用${}取值判断,使用三元运算符进行判断
"${active=='main.html'?'nav-link active':'nav-link'}"
列表循环展示
使用三元判断输出男女
使用thymeleaf将时间进行格式化输出
<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.getDepartment().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>
添加员工
-
编写controller
@GetMapping("/emp") public String toAddpage(Model model){ //查出所有部门的信息 Collection<Department> departments = departmentDao.getDepartments(); model.addAttribute("departments",departments); return "/emp/add"; } @PostMapping("/emp") public String addEmp(Employee employee){ System.out.println("save=>"+employee); employeeDao.save(employee); //查出所有部门的信息 return "redirect:/emps"; }
-
编写前端from表单
<form th:action="@{/emp}" method="post"> <div class="form-group"> <label>LastName</label> <input name="lastName" type="text" class="form-control" placeholder="lzj"> </div> <div class="form-group"> <label>Email</label> <input name="email" type="email" class="form-control" placeholder="1481315703@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> <select class="form-control" name="department.id"> <!-- 我们在controller接收的是一个Employee,所以我们需要提交的是其中的一个属性--> <option th:each="dept:${departments}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"></option> </select> </div> <div class="form-group"> <label>Birth</label> <input name="birth" type="text" class="form-control" placeholder="嘤嘤嘤"> </div> <button type="submit" class="btn btn-primary">添加</button> </form>
-
修改时间格式
#时间日期格式化 spring.mvc.format.date=yyyy-MM-dd
修改员工信息
-
编写controller
//全部员工页面传递id值过来 @GetMapping("/emp/{id}") public String toUpdateEmp(@PathVariable("id") Integer id,Model model){ Employee employee = employeeDao.getEmployeeById(id); model.addAttribute("emp",employee); Collection<Department> departments = departmentDao.getDepartments(); model.addAttribute("departments",departments); System.out.println(employee); return "emp/update"; } @PostMapping("/updateEmp") public String updateEmp(Employee employee){ employeeDao.save(employee); return "redirect:/emps"; }
-
编写前端from表单
<form th:action="@{/updateEmp}" method="post"> <input type="hidden" name="id" th:value="${emp.getId()}"> <div class="form-group"> <label>LastName</label> <input th:value="${emp.getLastName()}" name="lastName" type="text" class="form-control" placeholder="lzj"> </div> <div class="form-group"> <label>Email</label> <input th:value="${emp.getEmail()}" name="email" type="email" class="form-control" placeholder="1481315703@qq.com"> </div> <div class="form-group"> <label>Gender</label><br> <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> <select class="form-control" name="department.id"> <!-- 我们在controller接收的是一个Employee,所以我们需要提交的是其中的一个属性--> <option th:selected="${dept.getId()}==${emp.getDepartment().getId()}" th:each="dept:${departments}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"></option> </select> </div> <div class="form-group"> <label>Birth</label> <input th:value="${#dates.format(emp.getBirth(),'yyyy-MM-dd HH:mm:ss')}" name="birth" type="text" class="form-control" placeholder="嘤嘤嘤"> </div> <button type="submit" class="btn btn-primary">修改</button> </form>
删除员工、404页面和注销
-
删除员工
-
编写controller
@GetMapping("/delemp/{id}") public String deleteEmp(@PathVariable("id") Integer id){ employeeDao.delete(id); return "redirect:/emps"; }
-
-
404页面
在templates目录下创建error文件夹,将404.html页面放进去即可
-
注销
-
编写controller
@RequestMapping("/user/logout") public String logout(HttpSession session){ session.removeAttribute("loginUser"); return "redirect:/"; }
-
删除员工、404页面和注销
-
删除员工
-
编写controller
@GetMapping("/delemp/{id}") public String deleteEmp(@PathVariable("id") Integer id){ employeeDao.delete(id); return "redirect:/emps"; }
-
-
404页面
在templates目录下创建error文件夹,将404.html页面放进去即可
-
注销
-
编写controller
@RequestMapping("/user/logout") public String logout(HttpSession session){ session.removeAttribute("loginUser"); return "redirect:/"; }
-
-
更多推荐
所有评论(0)