前言
这一篇我们就先引入前端页面和相关的静态资源,再做一下管理员的登陆和注销的功能,为后续在页面上操作数据做一个基础。
前端页面
前端的页面是我从网上找的一个基于Bootstrap 的dashboard模板,可以用来作为后台管理的界面,前端页面代码繁多,我只贴一些重要的,就不全部贴出来了。
引入静态资源
<!-- Bootstrap core CSS -->
<!--公共资源通过webjars引入-->
<link href="/asserts/css/bootstrap.min.css" th:href="@{/webjars/bootstrap/4.0.0/css/bootstrap.css}" rel="stylesheet">
<!-- Custom styles for this template -->
<!--自定义资源通过普通方式引入-->
<link href="/asserts/css/signin.css" th:href="@{/asserts/css/signin.css}" rel="stylesheet">
要使用th:href,要先倒入thymeleaf命名空间。
添加xmlns:th="http://www.thymeleaf.org"。idea就会出语法提示。
webjars:
- 将静态资源版本化,更利于升级和维护。
- 剥离静态资源,提高编译速度和打包效率。
- 实现资源共享,有利于统一前端开发。
怎么使用webjars呢?
依赖
<!--通过webjar引入前端库-->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>4.0.0</version>
</dependency>
可以在官网快速找到各种常用前端库的引用:https://www.webjars.org/
资源所在位置
项目External Libraries文件夹:
webjars映射规则
th:href="@{/webjars/bootstrap/4.0.0/css/bootstrap.css}"
所有/webjars/**的url 都去classpath:/META-INF/resources/webjars/找资源。
springboot资源映射规则
以"/**"访问当前项目的任何资源都会首先去如下路径寻找,这些路径是静态资源的文件夹:
classpath:/META-INF/resources/,
classpath:/resources/,
classpath:/static/,
classpath:/public/
ps: classpath src->main->resources文件夹
#可以在配置文件中修改静态资源文件路径
spring:
resources:
static-locations:
th:href="@{/asserts/css/signin.css}"
我的sign.css是放在classpath:/static/asserts/css文件夹下
禁止自动填充
现在很多浏览器都会把cookie信息自动填充到我们的表单中,我们如果想要禁止自动填充,怎么做呢?
<input name="username" autocompleted="off" type="text" class="form-control" placeholder="Username" th:placeholder="#{login.username}" required="" autofocus="">
<input name="password" autocomplete="new-password" autocompleted="off" type="password" class="form-control" th:placeholder="#{login.password}" placeholder="Password" required="">
在username中添加autocompleted="off"
在password中添加autocomplete="new-password" autocompleted="off"
扩展springmvc
在config包下新建MyMvcConfig类实现了WebMvcConfigurer接口,然后实现了addViewControllers方法。
package com.jotal.springboot08restfulcrud.config;
/*
* 不能使用@EnableWebMvc,使用了就是全面接管springmvc,自动配置就会失效
* 实现WebMvcConfigurer,来扩展springmvc的功能
* */
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
//识图适配器
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//登陆
registry.addViewController("/login").setViewName("login");
registry.addViewController("/").setViewName("login");
registry.addViewController("/login.html").setViewName("login");
}
}
springboot已经帮我们自动配置好了springmvc,我们为什么还要扩展springmvc?
例如我们需要项目一启动就跳转到一个页面,我们以往可能会写一个Controller方法来跳转,但是方法里没有什么内容,这样就显得很浪费。这时候我们就可以addViewControllers中添加视图适配规则。不仅仅是视图适配,我们还可以扩展拦截器、国际化等,来丰富系统功能。这些将会在下面介绍到。
registry.addViewController("/").setViewName("login"); 这句话就定义了项目一启动就跳转login页面。
/login和/login.html都会跳转到login页面。那么是怎么通过一个字符串“login”就会跳转到login.html呢?是thymeleaf视图解析器完成的。
thymeleaf视图解析器
初始化的默认页面路径在classpath:/templates/ 下,视图后缀为.html。默认路径也可以在配置文件中修改。
管理员登陆、注销
下面我们开始写管理员登陆、注销相关功能
实体类
package com.jotal.springboot08restfulcrud.entities;
public class User {
private String username;
private String password;
//getter、setter、constructor、toString
}
Dao
@Mapper
public interface UserDao {
int login(User user);
}
映射文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jotal.springboot08restfulcrud.dao.UserDao">
<select id="login" parameterType="user" resultType="Integer">
select count(*) from user
where username=#{username} and password=#{password}
</select>
</mapper>
Service
@Service
public class UserServiceImpl implements UserService {
@Autowired
UserDao userDao;
@Override
public int login(User user) {
return userDao.login(user);
}
}
Controller
@Controller
@RequestMapping(value = "/user")
public class UserController {
@Autowired
UserServiceImpl userService;
@PostMapping(value = "/login")
public String login(@RequestParam("username") String username,
@RequestParam("password") String password,
Map<String,Object> map,
HttpSession session){
User user = new User(username, password);
if(userService.login(user)>0){
//登录成功,为了防止表单重复提交,利用重定向
session.setAttribute("loginUser", username);
return "redirect:/main";
}else{
// 登陆失败
map.put("msg","用户名或密码错误");
return "login";
}
}
// 用户注销
@GetMapping("/logout/{username}")
public String logout(@PathVariable("username") String username,HttpSession session) {
// 清除session
session.invalidate();
return "redirect:/login";
}
}
首先form表单中的请求路径定义为该Controller方法,用POST方法提交
<form class="form-signin" th:action="@{/user/login}" method="post">
然后分别在用户名和密码框的输入框加上name属性,方便springmvc取值参数。springmvc用@RequestParam("xxx")取得前端请求发送来的参数值。
name="username" name="password"
我们利用拿到的数据和数据库中用户名密码是否一致,判断是否成功登陆。如果登陆成功,就将用户名添加到session中,然后重定向到主页。
如果用户名或者密码不对,就利用Map添加一个包含提示信息的属性到视图中,然后回到login.html。
这里利用thymeleaf的 th:if 判断决定msg是否显示。判断msg不为空段落才会显示。
<p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
登陆进到主页之后,如果刷新主页的页面,会发现浏览器弹窗提示登陆表单会重复提交。这种情况利用重定向来解决!
return "redirect:/main"; 就是这一句 重定向到main,然后在我们扩展springmvc的地方加入适配main的规则。
//登录成功之后,重定向解决表单重复提交问题
registry.addViewController("/main").setViewName("dashboard");
所以最终由thymeleaf视图解析器最终转发到主页dashboard.html。
拦截器
登陆功能怎么能少得了拦截器?拦截器在登陆功能中主要是为了防止在未登录的情况下通过uri的方式访问需要权限的页面。我们看一下如何在springboot中定义拦截器。
我们在component新建LoginHandlerInterceptor类实现HandlerInterceptor类。
package com.jotal.springboot08restfulcrud.component;
public class LoginHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
Object user = session.getAttribute("loginUser");
if (user == null) {
// 未登录返回登录页面
request.setAttribute("msg","未登录,请先登录");
request.getRequestDispatcher("/login").forward(request,response);
return false;
}else{
return true;
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
我们判断session中是否存在loginUser,loginUser是我们登陆成功才会添加到session中的。如果loginUser不存在,就在request中添加msg提示信息,然后转发到登录页面。如果loginUser存在就直接放行。
我们实现了拦截器,还要加入到springmvc的环境中。在MyMvcConfig中类重写addInterceptors方法。
//拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**")
.excludePathPatterns("/login","/","/login.html","/user/login","/webjars/**","/asserts/**");
}
我们定义了拦截规则,就是除了"/login","/","login.html","/user/login"之外的所有uri都会被拦截下来进行判断再决定是否放行。/user/login 是用来提交登陆表单请求的,"/login","/","login.html"是转发到登录页的。springboot已经默认静态资源不会被拦截器拦截。
注销
@GetMapping("/logout/{username}")
这样的请求会转发到实现注销的Controller方法。这里使用了restful api风格
我们使用@PathVariable("username")来获取参数,然后清除session并重定向到login.html。
// 用户注销
@GetMapping("/logout/{username}")
public String logout(@PathVariable("username") String username,HttpSession session) {
// 清除session
session.invalidate();
return "redirect:/login";
}
测试
输入错误账号密码
不登录访问主页http://localhost:8080/crud/main
注销后访问主页http://localhost:8080/crud/main
**主页**
![](https://img2018.cnblogs.com/blog/1738909/201908/1738909-20190813134917807-918042939.png)
今天这篇就到这里了,今天讲了前端页面和登录注销的功能,另外还有springboot静态资源的映射规则,thymeleaf的视图解析规则,以及扩展springmvc的功能。下面我们会讲一些国际化的问题,以及正式开始在页面中进行数据操作。