说在前面:
这个呢,是我最近在自学springboot时候做的一个小项目,目前还没有整合Mybatis框架,后面会有整合。这个呢就是用来熟悉springboot的使用以及Thymeleaf的使用,html页面直接拿的bootstrap的一套后台模板,感觉还不错,这个主要用来练手,也不算是练手吧,算是学完一阶段的小demo,写这个就是为了总结,使脑子中的知识不是那么的杂乱,要清除每一个功能是如何实现,对springboot的使用做总结,也是对idea的一个熟悉的过程把,idea真香。
首先是项目演示:
1. 网站登录页的中英文转换
2. 登录及查看员工信息
3. 登录拦截
4. 添加员工
5. 员工信息修改
6.删除及用户注销
这就是网站的演示,下面对具提功能如何实现做介绍以及可能会写写代码过程中出现的问题(如果我想起来的话…)
项目结构:
config:关于登录拦截器的配置,mvc配置,中英文转换配置,这是用java类进行配置的,也是我的第一次使用java类进行配置。
controller:页面跳转相关
dao:具体表的操作-- 因为没有涉及到数据库,所以是在dao里面,模拟创建表以及表信息
pojo:实体类
Demo03WebApplication:springboot项目从这里启动
i18n:配置国际化相关
static:存放js,css,img这一类的文件
templates:存放html文件,controller里return能直接跳转,Thymeleaf已经做好了视图解析器
application.yml:spring boot的配置文件,很方便
再补一份项目结构:
功能相关:
-
先说一下关于Thymeleaf自己配置的视图解析器,也不是凭空出来的templates文件夹,而是在配置文件里:ThymeleafProperties.java里面定义了详细的内容
-
关于如何实现登录页中英文转换,也就是springboot国际化如何实现:
首先在resource文件夹下面创建i18n(即Internationalization)文件夹,依次创建login.properties文件,login_en_Us.properties,login_zh_Cn.properties这三个文件,idea会自动合并到login文件夹下面。
打开这三个文件其中的一个,点击下方的Resource Bundle,就可以同时编辑这三个文件。
并且在里面配置属性,但是此时又搞不懂如何用上,可以看源码MessageSourceAutoConfiguration.java这个类里面,定义了消息是如何获取到的。
我们只需把spring.message.basename设置一下就好,配置上我们配置文件的路径,是在springboot的配置文件上配置,application.yml里。spring: # 关闭thymleaf的缓存 thymeleaf: cache: false # 配置国际化相关的消息转换 messages: basename: i18n.login # 配置项目路径 server: servlet: context-path: /hou
此时配置文件配置好了,就可以用了,可以在html页面中,按照thymeleaf给的方式取值:
官方文档中提到,Message是如何取值:#{…}
比如在前台页面中写#{login.tip}就会跟去用户请求头中的lanuage来判断显示中文还是英文,从而实现国际化。
但是,我们要实现点击按钮来切换中英文,此时我们需要自己写一个地区解析器,点击按钮携带参数,来实现中英文转换。
在config下面创建MyLocaleResolver类实现LocaleResolver接口,代码如下:package com.hou.config; 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; public class MyLocaleResolver implements LocaleResolver { @Override public Locale resolveLocale(HttpServletRequest request) { //获取请求中的参数 String language = request.getParameter("l"); //获取默认的 Locale locale = Locale.getDefault(); //解析获取到的参数 if (!StringUtils.isEmpty(language)){ //如果language这个不是空的 //开始解析 zh_CN String[] s = language.split("_"); //如果获取到参数就使用获取到的参数 return new Locale(s[0],s[1]); } //如果没有获取到参数就是用默认的参数 return locale; } @Override public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) { } }
写了自己的地区解析器,在html页面里就涉及到了thymeleaf如何携带参数,具体查看html页面的片段:
<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>
Thymeleaf携带参数使用圆括号,其中带th前缀代表是被thymeleaf接管了,超链接的形式要用人家的表达式写Link URL Expressions: @{…} ,就是@符号加上一对大括号,被Thymeleaf接管以后中间的地址就可以填写相对地址了,此时 “/” 代表的是templates文件夹。
但是别忘记在在MyMvcConfig配置类里面把咱们自己写的地区解析器注入到spring的bean里面,只有注入了才会起作用。//配置国际化地区解析器 @Bean public LocaleResolver localeResolver(){ return new MyLocaleResolver(); }
至此,已经完成了登录页的中英文转换问题,也熟悉了thymeleaf的表达式,取值等等…还是要多看文档进行操作。
-
登录及查看员工信息
登录如何实现:点击登录,跳转到登录处理的controller,校验用户名密码,处理页面跳转,跳转到管理界面
登录处理controller
//登录验证
@RequestMapping("/user/login")
public String login(@RequestParam("username") String username, @RequestParam("password") String password, Model model, HttpSession session){
//检查用户名和密码是否正确
if("admin".equals(username) && "123456".equals(password)){
//当用户名为admin且密码是123456的时候可以进入主页面
session.setAttribute("LoginUser",username);
return "redirect:/main.html";
}else{
//用户名或者密码错误的时候给出相应的错误提示,并且返回主页面
model.addAttribute("msg","用户名或者密码输入错误");
return "index";
}
}
重定向到这个main.html,这个是直接跳转到我们后台界面的,但是为了url好看,所以写一个这个跳转,但是对于main.html我们不可能再写一个controller吧?所以就用到了神器!addviewController!实现无业务逻辑跳转
官方推荐实现WebMvcConfigurer来调用此方法
一行代码解决了一个controller,无业务逻辑跳转就不用写controller
无业务逻辑跳转就是类似
@RequestMapping("/hello")
public String hello(){
return "hello";
}
这种,没有任何业务逻辑,只是处理页面跳转。
处理完跳转后就到了主界面
查看员工信息
首先是页面中如何处理点击选中状态
thymleaf实现点击导航栏中的导航文字有选中状态
就比如公共的侧边栏,加入侧边栏的时候可以加入值
<div th:replace="~{commons/common::sidebar(active='emp')}"></div>
这样就可以带着值过去了
<a th:class="${active=='emp'?'nav-link active':'nav-link'}" th:href="@{/emps}" ></a>
也就是当点击进入到展示页面时候就会这个通用侧边栏调用的时候会有一个这样的传值
所以就会有样式
点击员工管理,跳转到emp的controller
到list页面显示
后台如何模拟数据库?
是使用的map
4. 登录拦截
先写一个拦截器
此处记得配置,是使用的类进行配置的,而不是以前使用的xml文件了
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
registry.addViewController("/main.html").setViewName("dashboard");
}
//配置国际化地区解析器
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
//配置拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/","/index.html","/user/login","/css/*","/img/*","/js/*");
}
}
- 添加员工实现
两个controller,一个是跳转到添加的页面,一个是实现添加,跳转到list页面
//get请求走这个添加方法
@GetMapping("/emp")
public String toAdd(Model model){
//查询部门列表
Collection<Department> departments = departmentDao.getDepartments();
model.addAttribute("depts",departments);
//跳转到表单页面
return "emp/add";
}
//post请求走这个方法
@PostMapping("/emp")
public String add(Employee employee){
employeeDao.save(employee);
return "redirect:/emps";
}
页面表单
<form method="post" th:action="@{/emp}">
<div class="form-group">
<label for="username">名字:</label>
<input type="text" name="lastName" class="form-control" id="username" placeholder="请输入名字">
</div>
<div class="form-group">
<label for="exampleInputEmail1">邮箱地址:</label>
<input type="email" name="email" class="form-control" id="exampleInputEmail1" placeholder="请输入邮箱">
</div>
<div class="form-group">
<label>性别:</label><br>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" value="1" name="gender">
<label class="form-check-label">男</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" value="0" name="gender">
<label class="form-check-label">女</label>
</div>
</div>
<div class="form-group">
<label>部门:</label>
<select class="form-control" name="department.id" >
<option th:each="dept:${depts}" th:value="${dept.getId()}" th:text="${dept.getDepartmentName()}"></option>
</select>
</div>
<div class="form-group">
<label>出生日期:</label>
<input class="form-control" name="birth" type="text">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
- 员工修改实现
也是两个controller,一个跳转,一个实现修改
@GetMapping("/emp/{id}")
public String toEdit(@PathVariable("id") Integer id,Model model){
Employee employee = employeeDao.getEmployeeById(id);
//查询部门列表
Collection<Department> departments = departmentDao.getDepartments();
model.addAttribute("depts",departments);
model.addAttribute("emp",employee);
//转向编辑页面
return "emp/edit";
}
@PostMapping("/emp/{id}")
public String edit(@PathVariable("id") Integer id, Employee employee){
//给employee设置id
employee.setId(id);
//进行dao层的修改操作
employeeDao.updateEmployee(employee);
return "redirect:/emps";
}
注意这个表单中如何获取员工信息默认值显示到页面上的
<form method="post" th:action="@{'/emp/'+${emp.getId()}}" >
<div class="form-group">
<label for="username">名字:</label>
<input type="text" name="lastName" th:value="${emp.getLastName()}" class="form-control" id="username" placeholder="请输入名字">
</div>
<div class="form-group">
<label for="exampleInputEmail1">邮箱地址:</label>
<input type="email" name="email" th:value="${emp.getEmail()}" class="form-control" id="exampleInputEmail1" placeholder="请输入邮箱">
</div>
<div class="form-group">
<label>性别:</label><br>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" value="1" name="gender" th:checked="${emp.getGender()==1}">
<label class="form-check-label">男</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" value="0" name="gender" th:checked="${emp.getGender()==0}">
<label class="form-check-label">女</label>
</div>
</div>
<div class="form-group">
<label>部门:</label>
<select class="form-control" name="department.id" th:value="${emp.getDepartment().getDepartmentName()}" >
<option th:each="dept:${depts}" th:value="${dept.getId()}" th:text="${dept.getDepartmentName()}" th:selected="${dept.getId()==emp.getDepartment().getId()}">
</option>
</select>
</div>
<div class="form-group">
<label>出生日期:</label>
<input class="form-control" name="birth" type="text" th:value="${#dates.format(emp.getBirth(),'yyyy/MM/dd')}">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
- 员工删除以及注销功能
删除很简单,就是调用一个controller执行删除即可,具体代码不贴了
注销功能就是点击删除用户的session就行
@RequestMapping("/user/logout")
public String logout(HttpServletRequest request){
HttpSession session = request.getSession();
//清除session,会清除session
// session.invalidate();
//也可以把用户登录的属性删除 也可以达到注销用户的功能
session.removeAttribute("LoginUser");
return "index";
}
一个练手的项目,基本的增删改查吧,主要就是国际化和页面的展示问题。