文章目录
首页实现
@RequestMapping({"/", "/index.html"})
public String index() {
return "login";
}
- 注意导入thymeleaf,变更页面匹配thymeleaf语法
- 静态资源最好使用thymeleaf接管,@{/}
国际化
-
步骤:
-
编写国际化配置文件,抽取页面需要显示的国际化消息
-
springboot自动配置好了管理国际化资源文件的组件,只需要在配置文件中修改值即可
# 国际化配置文件的路径 spring.messages.basename=i18n.login
-
thymeleaf获取国际化信息值
th:text="#{login.find}
,th:placeholder="#{login.email}"
等
-
点击按钮切换语言信息
-
原理:国际化Locale(区域信息对象),LocaleResolver(获取区域信息对象)
@Bean //容器中没有localeResolver这个bean的时候使用,也就是说用户写了的话不会生成 @ConditionalOnMissingBean(name = DispatcherServlet.LOCALE_RESOLVER_BEAN_NAME) @SuppressWarnings("deprecation") //这个默认的区域信息解析器是根据请求头带来的区域信息获取Locale进行国际化 public LocaleResolver localeResolver() { if (this.webProperties.getLocaleResolver() == WebProperties.LocaleResolver.FIXED) { return new FixedLocaleResolver(this.webProperties.getLocale()); } if (this.mvcProperties.getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) { return new FixedLocaleResolver(this.mvcProperties.getLocale()); } AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver(); Locale locale = (this.webProperties.getLocale() != null) ? this.webProperties.getLocale() : this.mvcProperties.getLocale(); localeResolver.setDefaultLocale(locale); return localeResolver; }
-
点超链接后重新转到当前页面
<a th:href="@{/index.html(l='zh_CN')}">中文</a> <a th:href="@{/index.html(l='en_US')}">English</a>
-
自己写一个区域信息解析器
public class MyLocaleResolver implements LocaleResolver { @Override public Locale resolveLocale(HttpServletRequest httpServletRequest) { //获取前端传来的值 String l = httpServletRequest.getParameter("l"); //初始化为默认 Locale locale = Locale.getDefault(); if(!StringUtils.isEmpty(l)){ String[] split = l.split("_"); locale = new Locale(split[0], split[1]); } return locale; }
-
把写好的解析器放入到spring容器
@Configuration public class MyMvcConfig { @Bean //注意!!因为要保证只存在我们写的localeResolver,所以bean名称只能为localeResolver public LocaleResolver localeResolver() { return new MyLocaleResolver(); } }
登录功能实现
-
登录表单
<form class="form-login" th:action="@{/user/login}"> <h2 class="form-login-heading" th:text="#{login.tip}">请登录</h2> <!--这里判断msg是否为空,虽然没必要,但了解一下怎么写--> <p style="color: red;text-align: center" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p> <div class="login-wrap"> <input type="text" name="username" class="form-control" th:placeholder="#{login.username}" autofocus> <br> <input type="password" name="password" class="form-control" th:placeholder="#{login.password}">
-
编写controller
@RequestMapping("/user/login") public String login( @RequestParam("username") String username, @RequestParam("password") String password, Model model){ if (!StringUtils.isEmpty(username) && "123456".equals(password)){ return "redirect:/index"; }else { model.addAttribute("msg","用户名或者密码错误"); return "login"; } } @RequestMapping("index") public String index(){ return "index"; }
拦截器功能实现
-
实现拦截器方法
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; } } }
-
配置拦截器
@Configuration public class MyMvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { //所有请求都拦截,再排除一些请求 registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**") .excludePathPatterns("/index.html", "/", "/user/login", "/assets/**", "/css/**", "/img/**", "/js/**"); } }
员工表展示
-
实现导航栏、侧边栏等构建的重用
<!--可重用组件加上th:fragment="menu"--> <aside th:fragment="menu"> <!--其他页面放入组件,需要标识组件所在的页面--> <div th:replace="~{index.html :: menu}"></div>
-
js实现侧边栏获取点击状态(有瑕疵)
<script th:src="@{/js/menu.js}"></script> <script type="text/javascript" th:inline="javascript"> msg('table'); </script>
-
menu.js
function msg(message) { //根据传参(id)获取需要改变class的标签 $("#" + message).attr("class", "active"); let li = $("#" + message + "_li"); //如果id存在 if(li.length>0){ li.attr("class", "active"); } }
-
-
thymeleaf实现侧边栏获取点击状态
-
在调用语句里传参
<div th:replace="~{index.html :: menu(active = 'table')}"></div>
-
被调用语句中获取参数并进行判断
<li th:class="${active=='table'} ? 'active'"><a th:href="@{/employees}">Basic Table</a></li>
-
-
controller
private EmployeeDAO employeeDAO; @Autowired public void setEmployeeDAO(EmployeeDAO employeeDAO) { this.employeeDAO = employeeDAO; } @RequestMapping("/employees") public String list(Model model){ Collection<Employee> employees = employeeDAO.getAll(); model.addAttribute("employees", employees); return "basic_table"; }
-
获取和展示信息
<thead> <tr> <th>编号</th> <th>姓名</th> <th>邮箱</th> <th>性别</th> <th>部门</th> </tr> </thead> <tbody> <tr th:each="employee : ${employees}"> <td th:text="${employee.getId()}"></td> <td th:text="${employee.getLastName()}"></td> <td th:text="${employee.getEmail()}"></td> <!--判断,符合条件则有效--> <td th:if="${employee.getGender()} == 1">男</td> <td th:if="${employee.getGender()} == 0">女</td> <!--或者--> <td th:text="${employee.getGender()==0?'女':'男'}"></td> <td th:text="${employee.getDepartment().getDepartmentName()}"></td> <!--日期处理--> <td th:text="${#dates.format(employee.getBirth(),'yyyy-mm-dd')}"></td> </tr>
实现ajax和分页
-
页面中调用ajax
<script type="text/javascript" th:inline="javascript"> //第一个参数为当前页数,第二个参数为ajax请求url tableAjax(page, [[@{/}]]+'employeesAjax'); </script>
-
ajax.js
function tableAjax(page, url) { $.ajax({ url: url, //给后端传当前页面,用于分页 data: {"page": page}, success: function (employees) { //显示和隐藏上一页、下一页,用于分页 if (page > 1) { $("#up").show(); } else{ $("#up").hide(); } if (page >= employees.length / 2) { $("#down").hide(); } else{ $("#down").show(); } let html = null; for (let i = 0; i < employees.length; i++) { if(employees[i].gender === 1){ gender = '男'; }else{ gender = '女'; } html += "<tr>" + "<td>" + employees[i].id + "</td>" + "<td>" + employees[i].lastName + "</td>" + "<td>" + employees[i].email + "</td>" + "<td>" + employees[i].gender + "</td>" + "<td>" + employees[i].department.departmentName + "</td>" + "<td>" + employees[i].birth + "</td>" + "</tr>"; } $("#table").html(html); $("#page").text(page); } }); }
-
分页
<div> <!--显示当前页面--> <span id="page" th:text="${page}"></span> <a id="up" hidden onclick="pagedown()">上一页</a> <a id="down" onclick="pageup()">下一页</a> <script type="text/javascript" th:inline="javascript"> let page = [[${page}]]; function pageup() { page += 1; tableAjax(page, [[@{/}]]+'employeesAjax'); } function pagedown() { page -= 1; tableAjax(page, [[@{/}]]+'employeesAjax'); } </script> </div>
-
controller
@RequestMapping("/employees") public String list(Model model){ Collection<Employee> employees = employeeDAO.getAll(); model.addAttribute("employees", employees); model.addAttribute("page",1); return "basic_table"; } @RequestMapping("/employeesAjax") @ResponseBody public Collection<Employee> employeesAjax(int page){ //返回的java对象springboot集成的jackson会自动帮我们解析成json对象并传输给前端 return employeeDAO.getAll(page); }
一对多前端传值
-
当后端需要一个对象参数,且该对象内包含其他对象时
public class Employee { private Integer id; private String lastName; private String email; private Integer gender; //0:女 1:男 private Department department; private Date birth;
//例如 public String addEmployee(Employee employee) {
-
前端可以这样传值
<!--用对象.对象的属性作为参数名即可--> <select name="department.id"></select> <!--一般情况直接用对象的属性名传参即可--> <input type="text" name="lastName">
- 猜测一下大概原理,mvc会获取到form提交的所有name和对应的值,然后每个name找对应的controller方法的参数并赋值,如果name里面有.的话就会查找对应对象里的属性,例如department.id,会先判断出department是所需对象参数的类的属性,然后再在department对象中找id属性
员工增加更新删除
-
增加controller
@RequestMapping("/toAdd") public String toUpdate(Model model) { //获取所有部门,用于下拉框选择部门 Collection<Department> departments = departmentDAO.getDepartments(); model.addAttribute("departments", departments); return "add_table"; } @RequestMapping("/addEmployee") public String addEmployee(Employee employee) { System.out.println(employee); employeeDAO.save(employee); return "redirect:/employees"; }
-
更新html
<form class="form-horizontal style-form" role="form" th:action="@{/updateEmployee}" method="post"> <input hidden name="id" th:value="${employee.getId()}"> <div class="form-group"> <label class="col-sm-1 control-label">姓名</label> <div class="col-sm-8"> <input type="text" class="form-control" name="lastName" th:value="${employee.getLastName()}"> </div> </div> <div class="form-group"> <label class="col-sm-1 control-label">邮箱</label> <div class="col-sm-8"> <input type="email" class="form-control" id="text3" name="email" th:value="${employee.getEmail()}"> </div> </div> <div class="form-group"> <label class="col-sm-1 control-label">性别</label> <div class="col-sm-8"> <div class="radio"> <label> <input type="radio" name="gender" value="1" th:checked="${employee.getGender() == 1}"> 男 </label> <label> <input type="radio" name="gender" value="0" th:checked="${employee.getGender() == 0}"> 女 </label> </div> </div> </div> <div class="form-group"> <label class="col-sm-1 control-label">部门</label> <div class="col-sm-8"> <label> <select class="form-control" name="department.id" style="margin: 5px 0 0 0"> <option th:selected="${dept.getId()==employee.getDepartment().getId()}" th:each="dept : ${departments}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"> </option> </select> </label> </div> </div> <div class="form-group"> <label class="col-sm-1 control-label">生日</label> <div class="col-sm-8"> <input type="text" class="form-control"> </div> </div> <button type="submit" class="btn btn-theme">Sign in</button> </form>
-
更新controller
@RequestMapping("/toUpdate/{id}") public String toUpdate(@PathVariable("id") Integer id, Model model) { //根据获取的员工id获取员工所有信息并传给前端 Employee employee = employeeDAO.getEmployeeByID(id); Collection<Department> departments = departmentDAO.getDepartments(); model.addAttribute("departments", departments); model.addAttribute("employee", employee); return "update_table"; } @RequestMapping("/updateEmployee") public String updateEmployee(Employee employee) { employeeDAO.update(employee); return "redirect:/employees"; }
-
删除controller
@RequestMapping("/delete/{id}") public String delete(@PathVariable("id") Integer id){ employeeDAO.delete(id); return "redirect:/employees"; }
错误页面
- 404等错误页面定制,只需要在该目录下创建对应的html,404.html、500.html等
退出登录
@RequestMapping("/user/logout")
public String logout(HttpSession session){
//清除当前session对象
session.invalidate();
return "redirect:/";
}