问题1 :Error resolving template [xxx], template might not exist or might not be accessible by any of the configured Template Resolvers
解决方案: 这个问题出现的原因是什么呢,从翻译来说,这个就是解析不了template模板,在我们return的时候,因为springboot的配置静态资源默认在 static下,读取的模板在template下,如果不将thyemleaf渲染的模板放到template下,那么 就会报这个错误,
.yml 配置如下:
thymeleaf:
prefix: classpath:/templates/
suffix: .html
mode: HTML
encoding: UTF-8
cache: false
servlet:
content-type: text/html
问题2 :springboot如何设置未登录不能跳转到其他页面只能跳转 到登陆页面
解决方案: 用到 springmvc 的拦截器,自定义拦截路径:
配置是这样的:
代码附上:
package com.config;
import com.incerceptor.LoginInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MvcConfig implements WebMvcConfigurer {
/**
* 通过@Bean注解,将我们定义的拦截器注册到Spring容器
* @return
*/
@Bean
public LoginInterceptor loginInterceptor(){
return new LoginInterceptor();
}
/**
* 可以将不需要拦截的路径 ,比如说静态资源的路径放行,将下面的路劲添加到拦截器的后缀即可
* */
String[] excludePathPatterns = {
"/user/login","/user/error","/user/out"
};
/**
* 重写接口中的addInterceptors方法,添加自定义拦截器
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 通过registry来注册拦截器,通过addPathPatterns来添加拦截路径
registry.addInterceptor(this.loginInterceptor()).addPathPatterns("/admin/**").addPathPatterns("/teacher/**");
}
}
package com.incerceptor;
import com.pojo.admin;
import com.pojo.teacher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LoginInterceptor implements HandlerInterceptor {
private Logger logger = LoggerFactory.getLogger(LoginInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
logger.debug("处理器执行前执行!");
String basePath = request.getContextPath();//输出为空 其实就是输出端口号之前的url
/*
* 在后端重定向页面的时候可以这样用
* response.sendRedirect(request.getContextPath()+"/IndexServlet");
* */
String path = request.getRequestURI();//输出为去掉端口号后的URL
System.out.println(path);
//获取登录对象的账号密码存入session
admin a=(admin)request.getSession().getAttribute("admin");
teacher t= (teacher) request.getSession().getAttribute("teacher");
//根据不同的请求让他跳转到不同的路径
if(path.startsWith("/admin")){
if (a==null){
//此处 加.html 原因是因为 登录页面不在默认的template下,在static下
// response.sendRedirect("/AdminLogin.html");
response.sendRedirect("/AdminLogin.html");
return false;
}
}
else if (path.startsWith("/teacher")){
if (t==null){
response.sendRedirect("/TeacherLogin.html");
return false;
}
}
else{
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object
handler, ModelAndView modelAndView) {
logger.debug("处理器执行后执行!");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object
handler, Exception ex) {
logger.debug("跳转后执行!");
}
}
问题3 :springboot 启动如何访问到templates下的html页面
解决方案: springboot 启动默认访问的是static下的 index页面,如果登录页面写到了template下 我们就需要根据请求 去到达那个页面 :案例如下:
@RequestMapping("/Alogin")
public String loginPage(){
//这里不用这种方法的原因是因为把 该页面从static移到了templates目录下
//return "redirect:AdminLogin.html";
return "AdminLogin";
}
问题4 :如何让springboot项目不同页面只需要登录一次-----用session来解决这个问题
解决方案: 现在上线的网站的登录功能都是这样的,只需要一次登录,那么在打开新窗口的时候 再次访问别的页面的时候,被拦截器拦截下来,因为我们登录时的 账户是“无状态的”,现在要让他有状态,那就把登录信息存储到session里面,操作如下:
/*
* 可以用两种方法来获取前端输入的账号密码
* 1 写一个对象 包含账号密码,然后读取数据
* 2 用servlet来获取
* 3 用下面这种方式,参数名和传来的 name 名相同就行
* */
@RequestMapping(value = "/login" ,method = RequestMethod.POST)
public String login(int id, String pass,Model model, HttpServletRequest request, HttpServletResponse response) throws InterruptedException {
List<admin> list =adminService.list();
for (int i = 0; i < list.size() ; i++) {
//先判断账号是否存在,如果存在在进一步判断密码
if (id== list.get(i).getId()){
//判断密码是否正确
if (pass.equals(list.get(i).getPassword())) {
admin admin=new admin();
admin=adminService.getById(id);
// 将登录信息存到session里边,这样在登录的情况下是可以访问其他页面的
// request.getSession().setAttribute("admin",admin);
HttpSession session=request.getSession();
session.setAttribute("admin",admin);
//设置session的超时时间 此处为半小时
session.setMaxInactiveInterval(30*60);
model.addAttribute("admin",admin);
return "adminIndex";
}
//密码不正确 则弹出框提示
else {
model.addAttribute("msg", "密码错误");
return "AdminLogin";
}
}
else {
model.addAttribute("msg", "账号不存在");
//这里不用这种方法的原因是因为把 该页面从static移到了templates目录下
//return "redirect:AdminLogin.html";
return "AdminLogin";
}
}
/*这里返回不带后缀的请求只针对thyemleaf,因为这个模板不在template下,所以用重定向
return "redirect:AdminLogin.html";
*/
return "AdminLogin";
}
在上边的拦截器里 我们已经写过了,
问题5 :如何让 用户信息到了指定的时间让session失效
解决方案:在一般系统登录后,都会设置一个当前session失效的时间,以确保在用户长时间不与服务器交互,自动退出登录,销毁session给session设置失效时间,到了指定时间 ,session过期,那么访问其他请求就会被拦截下来。
简单的方法:不在前端做判断,只在后端设置一个常规的存活时间,到期删除掉session即可
设计正常的 判断页面用户无操作,然后向后端发送请求,删除session后返回前端
代码:
<script>
//浏览器长时间微操作,注销session ,
var oldTime = new Date().getTime();
var newTime = new Date().getTime();
var outTime = 8*60*1000; //设置超时时间: 8分钟
console.log(oldTime);
console.log(newTime);
$(function(){
/* 鼠标移动事件 */
$(document).mouseover(function(){
oldTime = new Date().getTime(); //鼠标移入重置停留的时间
console.log(oldTime);
});
});
function OutTime(){
newTime = new Date().getTime(); //更新未进行操作的当前时间
if(newTime - oldTime > outTime){ //判断是否超时不操作
console.log("时间到,退出登录");
//发送请求到后端删除session;
window.parent.location.replace("delSession");
}
}
/* 定时器 判断每5秒是否长时间未进行页面操作 */
window.setInterval(OutTime, 3000);
</script>
@RequestMapping("/delSession")
public String delSession(){
session.removeAttribute("admin");
return "AdminLogin";
}
问题6 :Uncaught ReferenceError: $ is not defined
解决方案:这个问题是js文件没有成功引入,还是thyemleaf模板引入静态资源的问题,
注意引入路径的问题即可,静态资源一般还是放在static下,放在template下访问不到
问题7 :thyemleaf模板接收不到后端传来的msg消息
解决方案:这个问题出现的原因是因为我的static里放了 thyemleaf模板渲染的html,导致传过去的参数在static下接收不到,还有一点是 script 接收model参数是这样接收的
@RequestMapping("/parameterTest")
public String ParamTest(Model model){
model.addAttribute("param","test" );
return "paramTest";
}
<script th:inline="javascript">
//方式一
var param = [[${param}]];
//方式二
param = /*[[${param }]]*/""
console.log("param :"+ param )
</script>
问题8 :如何设置提示消息定时消失
解决方案:有时候需要做这样一个业务操作,就是账号密码输入错误的时候,弹框提醒,然后几秒后消失
<script th:inline="javascript">
// 让提示定时消失
setTimeout(function (){
$ ("#div").css('display','none');
},1000);
</script>
<div id="div" style="text-align: center">
<p style=" font-size:20px ;color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
</div>
问题9 :表单验证 账号密码是否达到位数
解决方案:业务需求 ,有时候账号密码输入并不符合规则,这样发送到后端无疑是浪费服务器资源,然后我们可以在前端进行判断,代码是这样操作
<script type="text/javascript">
//验证账号密码是否符合规则
function checkusrn() {
var check = false;
var username = document.getElementById("id").value;
if (username.length < 5) {
document.getElementById("checktext1").innerHTML = " × 账号不要少于5位";
check = false;
} else {
document.getElementById("checktext1").innerHTML = " √";
check = true;
}
return check;
}
function checkpwd() {
var check = false;
var password = document.getElementById("pass").value;
if (password.length < 6) {
document.getElementById("checktext2").innerHTML = " ×密码 不要少于6位";
check = false;
} else {
document.getElementById("checktext2").innerHTML = " √";
check = true;
}
return check;
}
//满足上两条才能提交
function check() {
var check = checkusrn() && checkpwd() ;
return check;
}
</script>
问题10: 为什么要用QueryWrapper?QueryWrapper的效率高吗
解决方案:
什么是QueryWrapper?
在调用service层封装好的查询方法getOne时,可以看到需要传的参数是queryWrapper。那么queryWrapper是啥呢?实现查询的对象封装操作类,讲人话就是queryWrapper封装了sql语句where后面的内容
QueryWrapper是在mp上更加高效的查询方式,大大的简化了我们编写SQL语句,提高我们的工作效率。