我是靠谱客的博主 笑点低大船,最近开发中收集的这篇文章主要介绍springboot实现登录功能和拦截器功能实例功能需求:补充:请求转发与请求重定向的区别,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

功能需求:

    springboot登陆页面进行登陆验证,并完成登陆跳转。错误的账户提示用户名密码错误,正确的账户跳转到index页面。 

同时加上登陆拦截器,对于错误的账户不允许直接访问index页面。

一  登陆验证 

实现输入正确的用户名密码直接进入index页面,输入错误提示用户名密码错误。

  1. 要实现登录,我们需要先编写一个登录的controller类:

package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpSession;
import java.util.Map;
@Controller
public class LoginController {
@RequestMapping("login")
public String tologin()
{
return "login";
}
@PostMapping(value="/login")
public String login(@RequestParam("username") String username, @RequestParam("password") String password, Map<String,Object> map,
HttpSession session){
//验证用户名和密码,输入正确,跳转到index
if(!StringUtils.isEmpty(username)&&"lss".equals(password)){
session.setAttribute("userName",username);
System.out.println("username===" + username);
return "redirect:/index";
}
else
//输入错误,清空session,提示用户名密码错误
{
session.invalidate();
map.put("msg","用户名密码错误");
return "login";
}
}
@RequestMapping("index")
public String goIndex(Map<String,Object> map)
{
map.put("name","lishanshan");
map.put("age",29);
map.put("sex","女");
return "index";
}
}

说明:

(1) 跳转页面时使用  return ”redirect:/ index“,而不是 return ”index“ .

 return ”redirect:/ index“,会直接调用controller,  return ”index“ 只会访问目录下的文件

2. 登陆页面 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>首页</title>
</head>
<body>
<form th:action="@{/login}" method="post">
<!-- 取值替换原来默认的值-->
<h1>Please sign in</h1>
<p style="color:#ff0000" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
<label>Username</label>
<input type="text" name="username"
placeholder="Username" required="" autofocus="">
<label>Password</label>
<input type="password" name="password" placeholder="Password" required="">
<button type="submit" >Sign in</button>
</form>
</body>

说明:

(1)action 配置为th:action="@{/login}" method="post"

添加th:action,告诉模板,我们要跳转的请求是/login,而且是post请求的;

3.简单index页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>注册成功</h1>
姓名:<spn th:text="${name}"></spn>
年龄:<spn th:text="${age}"></spn>
性别:<spn th:text="${sex}"></spn>
</body>
</html>

4. properties配置

server.port=8002
spring.thymeleaf.cache=false

说明:为了开发方便,我们还可以将application.properties中添加一个 禁用缓存的参数: spring.thymeleaf.cache=fasle ,这样html页面有改动的时候,我们只需要用快捷键crtl+F9或者点击如图的编译按钮,重新编译下就可以在页面看结果,而不需要再次启动Tomcat服务了

二. 配置拦截器

我们在不输入用户名密码的时候,在地址栏里直接输入

http://localhost:8002/index也能直接访问地址。这是不允许的。所以需要配置拦截器,当用户密码不正确的时候,页面直接跳转到登陆页面,并显示无权限访问。

1.注册拦截器

新建类  webConfigurer  

package com.example.demo.configure;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfigurer implements WebMvcConfigurer {
// 这个方法是用来配置静态资源的,比如html,js,css,等等
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
WebMvcConfigurer.super.addResourceHandlers(registry);
}
// 这个方法用来注册拦截器,我们自己写好的拦截器需要通过这里添加注册才能生效
@Override
public void addInterceptors(InterceptorRegistry registry) {
// addPathPatterns("/**") 表示拦截所有的请求,
// excludePathPatterns("/login", "/register") 表示除了登陆与注册之外,因为登陆注册不需要登陆也可以访问
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**").excludePathPatterns("/login");
WebMvcConfigurer.super.addInterceptors(registry);
}
//设置默认页面
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("forward:/login");
//设置优先级
当请求地址有重复的时候
执行优先级最高的
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
WebMvcConfigurer.super.addViewControllers(registry);
}
}

 

2.拦截器

实现 HandlerInterceptor 

三个方法分别是

  • 1.preHandle:在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制、权限校验等处理;
  • 2.postHandle:在业务处理器处理请求执行完成后,生成视图之前执行。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView (这个博主就基本不怎么用了);
  • 3.afterCompletion:在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面);
    package com.example.demo.configure;
    import org.springframework.lang.Nullable;
    import org.springframework.stereotype.Component;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import java.io.IOException;
    @Component
    public class LoginInterceptor implements HandlerInterceptor {
    //这个方法是在访问接口之前执行的,我们只需要在这里写验证登陆状态的业务逻辑,就可以在用户调用指定接口之前验证登陆状态了
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException, ServletException {
    //每一个项目对于登陆的实现逻辑都有所区别,我这里使用最简单的Session提取User来验证登陆。
    HttpSession session = request.getSession();
    //这里的User是登陆时放入session的
    //如果session中没有user,表示没登陆
    Object user = request.getSession().getAttribute("userName");
    System.out.println("preHandle----" + user + " ::: " + request.getRequestURL());
    if (user == null) {
    request.setAttribute("msg","无权限请先登录");
    // 获取request返回页面到登录页
    request.getRequestDispatcher("/login").forward(request, response);
    //response.sendRedirect("/login");
    return false;
    } else {
    //如果session里有user,表示该用户已经登陆,放行,用户即可继续调用自己需要的接口
    System.out.println("进入拦截器......");
    System.out.println(request.getRequestURL());
    return true;
    }
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
    }
    

    上边配置的session需要取值才能做判断,那么我们需要在loginController中设置这个session值,以让它生效: session.setAttribute("userName",username);

补充:请求转发与请求重定向的区别

请求重定向和转发

1、请求重定向:浏览器的行为(通过响应对象HttpServletResponse来执行)

特点:可以重新定向访问其他Web应用下的资源

浏览器发出了2次请求,得到了2次响应

地址栏地址会变,跳转到要求指定的Servlet

代码演示:

//请求重定向方式一:

public void sent1(HttpServletResponse response) {
response.setStatus(302);
response.setHeader("Location", "/ServletStudy/servlet/ServletDemo2");
//这个地址是要求浏览器重新访问的。
}

//请求重定向方式二:

public void send2(HttpServletRequest request,HttpServletResponse response)
throws IOException {
//服务器向访问的浏览器的请求中添加属性,当被请求重定向后,在新的Servlet中不能得到添加的属性。
//因为请求重定向后的请求request对象不懂,这就是request的生命周期。
request.setAttribute("name", "zhangsan");
//与方式一实现的原理相同,较为常用
response.sendRedirect("/ServletStudy/servlet/ServletDemo2");
}

2、请求转发:服务器的行为(转发的瞬间是一个ServletRequest的生命周期)

特点:转发只能发生在当前Web应用下

浏览器发出了1次请求,得到了1次响应

(源组件和目标组件共享request和response中的数据)

地址栏地址不会发生变化。

应用:

(1)可以利用request的域对象的特点,由源组件向其中存放写数据。

(2)可以让用户访问到存放在WEB-INF目录中的目标资源

代码演示:

//请求转发
public void send3(HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException{
//在请求转发之前进行属性添加,在新的Servlet资源中能获取这个属性
request.setAttribute("name", "zhangsan");
//获取当前Servlet资源的转发器对象RequestDispatcher,传入当前应用的下要访问的那个Servlet资源
RequestDispatcher rd = getServletContext()
.getRequestDispatcher("/servlet/ServletDemo2");
//注意:传入的要访问的Servlet资源的地址中/代表的就是当前应用,所以就可以访问当前应用中WEB-INF中的信息
rd = getServletContext()
.getRequestDispatcher("/WEB-INF/form.html");
//也可以通过request得到转发器对象,用request得到的转发器在传入路径时,可以传入相对路径,不用加/
rd = request.getRequestDispatcher("/servlet/ServletDemo2");
//这里传入的路径地址:相对去被转发地址不同地方
//被转发地址:
http://localhost:8080/ServletStudy/servlet/ServletDemo1
//转发地址:
http://localhost:8080/ServletStudy/servlet/ServletDemo2
//所以填写相对资源地址:ServletDemo2
rd = request.getRequestDispatcher("ServletDemo2");
//调用转发器的forward()方法,进行请求转发
rd.forward(request, response);
}

3.RequestDispatcher中forward()转发和include()包含的区别

forword()转发:源组件<--->头+体

源组件转向目标组件,由目标组件显示响应正文结果(只有目标的响应)

转发前,容器会清空response对象的缓存,源组件的任何页面输出都无效,也就是会清空源组件的体

转发前不要刷新或关闭response的流

 

include()包含:

源组件包含目标组件,由源组件显示响应正文结果(还会把目标的响应结果包含进来)

包含前,容器会清空目标组件设置的响应头信息,目标组件所有设置的所有头都无效。

代码演示:

//RequestDispatch转发器中的:forward()和include()方法的区别

/*forword()转发:

源组件转向目标组件,由目标组件显示响应结果(只有目标的响应)

转发前,容器会清空response对象的缓存,源组件的任何页面输出都无效。

转发前不要刷新或关闭response的流

 

include()包含:

源组件包含目标组件,由源组件显示响应结果(还会把目标的响应结果包含进来)

包含前,容器会清空目标组件设置的响应头信息,目标组件所有设置的所有头都无效*/

public class ServletDemo3 extends HttpServlet {
//当做源组件
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
forwardTest(request, response);
}
public void forwardTest(HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
//response.setHeader("Refresh", "2");
OutputStream out = response.getOutputStream();
System.out.println("转发前向控制台输出");
out.write("转发前向页面输出".getBytes());
RequestDispatcher rd = request.getRequestDispatcher("ServletDemo4");
rd.forward(request, response);
System.out.println("转发后向控制台输出");
out.write("转发后向页面输出".getBytes());
}
public class ServletDemo4 extends HttpServlet {
//当做目标组件
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setHeader("Refresh", "2");
response.getOutputStream().write("目标组件".getBytes());
}

4.ServletContext和ServletRequest都能得到RequestDispatcher区别

(1)ServletContext

RequestDispatcher getRequestDispatcher(String path):path必须以"/"开头,代表当前的应用。这种写法,叫做绝对路径写法。

(2)ServletRequest

RequestDispatcher getRequestDispatcher(String path):

path可以以"/"开头:代表当前的应用。这种写法,叫做绝对路径写法。

也可以不以"/"开头:代表相对路径。

 

5.各种URL的写法:绝对路径和相对路径,建议大家使用绝对路径

绝对路径:如:/day05  地址前加了/就是一个绝对路径

原则:要不要加应用名称,看地址为谁服务的?

如果是给服务器用的,就不用加/MyApp,"/"代表的是当前应用。

如果是给客户端用的,要加上"/MyApp","/"代表的是要访问的服务器的URL地址(域名+端口),

getRequestDispatcher(String path):

path是一个路径。 不要加"/MyApp",只需要"/"即可

form action="url":要加"/MyApp"

a href="url":要加"/MyApp"

img src="url":要加"/MyApp"

link href="url":要加"/MyApp"

script src="url":要加"/MyApp"

302+Location="url":要加"/MyApp"

最后

以上就是笑点低大船为你收集整理的springboot实现登录功能和拦截器功能实例功能需求:补充:请求转发与请求重定向的区别的全部内容,希望文章能够帮你解决springboot实现登录功能和拦截器功能实例功能需求:补充:请求转发与请求重定向的区别所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(50)

评论列表共有 0 条评论

立即
投稿
返回
顶部