目录
1.创建一个Servlet项目
2.准备好Tomcat,用于启动Servlet项目
3.检查Servlet项目的起始目录是否准备齐全
4.准备用户登录所需创建文件夹和文件
5.编写Jsp文件
login.jsp
error.jsp
Content.jsp
6.测试
7.题外:会话(session)功能
1.创建一个Servlet项目
在Idea中选择maven-archetype-webapp,点击创建(create)
注:此处Idea版本为2023,若是以往版本,页面会有不同,但找到maven项目一样可以找到
Servlet项目所需依赖
<!-- servlet所需依赖 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.0</version> <scope>provided</scope> </dependency>
2.准备好Tomcat,用于启动Servlet项目
创建本地(local)Tomacat,在菜单Server中选择对应的可使用的tomcat程序,此处用的版本为Tomcat.9.0.62,接着在Http port中设置服务器端口(默认为8080),配置完成后点击Apply
接着在菜单Deployment中添加要部署的项目,点击+号作添加,选择以war为后缀的项目文件,此处我的项目名称为ServletReview1,因此显示为ServletReview1:war;下面的Application context指的是基于8080端口下的映射路径,这里可以自定义作选择,我这里直接默认以/作为起始映射点
3.检查Servlet项目的起始目录是否准备齐全
一个基本的Servlet项目,包含蓝色的java文件(注:蓝色是表示该文件是源代码文件夹,用于存放所有与Java相关的代码文件,若不是蓝色,则需点击右键-Mark directory as-Source-root)、resource资源文件(可以用于存放静态资源,如图片、视频、图标等)、webapp目录(注:该文件是有蓝色小圆点的,表示Tomcat启动后会默认被扫描到的地方)
注:如果你想手动配置一个webapp(带蓝点)的文件,则需要点击File-Project Structure-Modules-点击+号,然后用一个已有的web.xml的路径,将两者关联
4.准备用户登录所需创建文件夹和文件
此处根据自己的创建习惯,在java文件夹下自定义文件夹,一般我的习惯是Controller文件夹+Filter文件夹,分别用来编写Servlet和过滤器代码
写登录的逻辑代码,存在controller中(此处不添加数据库,模拟一套用户名和密码)
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); resp.setContentType("text/html;charset=UTF-8"); // 获取请求参数 String username = req.getParameter("username"); String password = req.getParameter("password"); if ("admin".equals(username) && "123456".equals(password)) { System.out.println("登陆成功"); // 倘若校验成功 则将其存在session中,便于到时在过滤器代码中取出作筛选 HttpSession httpSession = req.getSession(); httpSession.setAttribute("username",username); resp.sendRedirect("/jsp/Content.jsp"); } else { String message = "登录失败,请检查用户名和密码"; resp.getWriter().write("<script>alert('" + message + "');location.href='login.jsp';</script>"); } } }
写完一个Servlet后,马上在web.xml中作映射(避免遗忘的好习惯)
<!--xml是一个配置文件,属于一种标记语言,通过标签定义内容--> <!--声明Servlet--> <servlet> <!--servlet命名--> <servlet-name>LoginServlet</servlet-name> <!--servlet类的全限定名(路径+文件名)--> <servlet-class>zhan.controller.LoginServlet</servlet-class> </servlet> <!--定义Servlet的请求映射--> <servlet-mapping> <!--要映射的servlet名,与上方定义的servlet-name一致--> <servlet-name>LoginServlet</servlet-name> <!--请求映射url,必须以/开头--> <!--之后通过项目上下文路径+该路径,就能访问FirstServlet类--> <url-pattern>/LoginServlet</url-pattern> </servlet-mapping>
写过滤器代码
import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; public class AuthenticationFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; // 根据您的登录验证逻辑判断用户是否已登录 boolean isLoggedIn = checkLoginStatus(request); if (isLoggedIn) { // 用户已登录,继续执行下一个过滤器或请求(放行) filterChain.doFilter(request, response); } else { response.sendRedirect("/jsp/error.jsp"); } } @Override public void destroy() { } private boolean checkLoginStatus(HttpServletRequest request) { // 在这里编写您的登录验证逻辑 // 返回 true 表示已登录,返回 false 表示未登录 // 这里只是一个示例,您需要根据您的实际情况进行修改 HttpSession session = request.getSession(false); if (session != null) { // 获取session中的用户名,并打印检查 System.out.println(session.getAttribute("username")); System.out.println(session); } return session != null && session.getAttribute("username") != null; } }
然后跟Servlet一样的,Filter类也要在web.xml中作映射
<!-- 定义一个名为"AuthenticationFilter"的过滤器 --> <filter> <filter-name>AuthenticationFilter</filter-name> <!-- 过滤器类 --> <filter-class>zhan.Filter.AuthenticationFilter</filter-class> </filter> <!-- 配置"AuthenticationFilter"过滤器映射 --> <filter-mapping> <!-- 过滤器名称 --> <filter-name>AuthenticationFilter</filter-name> <!-- URL模式,表示所有以"/jsp/"开头的URL路径都会被该过滤器拦截 --> <url-pattern>/jsp/*</url-pattern> </filter-mapping>
这个过滤器的作用是对所有以"/jsp/"开头的URL进行身份认证,如果用户未登录或登录信息不正确,则重定向到登录页面。可以看出,这个过滤器是在保护Web应用程序的安全方面起作用的。
注:这是一段典型的web.xml配置文件中的过滤器(filter)代码段,其中定义了名字为“AuthenticationFilter”的过滤器,该过滤器由“zhan.Filter.AuthenticationFilter”类实现。通过filter-mapping元素将此过滤器映射到所有以“/jsp/”开头的请求路径上。当请求的URL路径被匹配时,容器就会先调用该过滤器来进行身份认证,保障Web应用程序的安全性。
5.编写Jsp文件
此处是我的webapp目录,其中web.xml是必须要在WEB-INF下的
我个人习惯是创建jsp文件夹,用于存放不同模块下的不同jsp页面,然后在webapp目录下直接创建一个登陆页面和错误页面(login.jsp和error.jsp),当然用index作登陆首页也没问题
由于我此处选择了用login作为首页,因此跟以往Servlet启动时,自动跳转到index.jsp不同的是,我需要在web.xml中额外作首页配置:
<!--设置首页--> <welcome-file-list> <welcome-file>login.jsp</welcome-file> </welcome-file-list>
配置完后,每次运行Servlet项目时,会先跳转到login.jsp页面
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <title>登录</title> <body> <form action="LoginServlet" method="post" onsubmit="return checkStringFormat()"> 用户名:<input type="text" name="username" id="username" > <br> 密码:<input type="password" name="password" id="password"> <button type="submit">提交</button> </form> </body> <script> function checkStringFormat() { var username = document.getElementById("username").value; var password = document.getElementById("password").value; if (username.length===0||password.length===0) { alert("用户名或密码不能为空"); return false; } return true; } </script> </html>
error.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>无权限</title> </head> <body> <p> 请登录后再访问该页面!<a href="login.jsp" style="color: #0cde28" >返回</a> </p> </body> </html>
Content.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%--<%= session.getAttribute("username") %>--%> <html> <head> <title>首页</title> </head> <body> <h1><%= session.getAttribute("username")%></h1> <h1>hello world!</h1> </body> </html>
至此,一个基本的用户登录(带过滤)的代码工作基本完成
6.测试
登录:
倘若登录失败:
倘若想跳过登录,直接访问路径:
则会响应过滤器,发现session中没有username,就跳转到error.jsp页面
7.题外:会话(session)功能
其中无论是在LoginServlet还是filter类中,都离不开会话session的功劳,在前者代码里,登录成功后将username存进了session里:
if ("admin".equals(username) && "123456".equals(password)) { System.out.println("登陆成功"); // 倘若校验成功 则将其存在session中 HttpSession httpSession = req.getSession(); httpSession.setAttribute("username",username); resp.sendRedirect("/jsp/Content.jsp"); }
然后又在Filter类中,检查session里是否有username进而作筛选:
private boolean checkLoginStatus(HttpServletRequest request) { // 在这里编写您的登录验证逻辑 // 返回 true 表示已登录,返回 false 表示未登录 // 这里只是一个示例,您需要根据您的实际情况进行修改 HttpSession session = request.getSession(false); if (session != null) { // 获取session中的用户名,并打印检查 System.out.println(session.getAttribute("username")); System.out.println(session); } return session != null && session.getAttribute("username") != null; }
基本上,一个Servlet项目往往离不开session:
Session(会话)是一种在Web应用程序中用于跟踪用户状态和存储用户相关信息的机制。在HTTP协议的无状态特性下,为了实现用户的连续性和数据的持久化,可以使用会话来跟踪用户在多个HTTP请求之间的状态。
其工作原理如下:
-
当用户首次访问Web应用程序时,服务器会为该用户创建一个唯一的会话标识,通常是一个会话ID。这个会话ID会被发送到用户的浏览器,并保存在cookie或URL参数中。
-
用户的每次请求都会携带会话ID,服务器通过会话ID来识别用户并检索与之关联的会话数据。
-
服务器可以在会话中存储用户的相关信息,例如登录状态、购物车内容等。这些信息可以在不同的页面和请求之间进行共享和传递,从而实现用户状态的保持。
-
会话的有效期可以根据需要进行设置,可以是固定的时间段,也可以是用户关闭浏览器时结束。
通过会话,Web应用程序可以实现以下功能:
- 用户认证和授权:会话可以跟踪用户的登录状态,确保只有经过身份验证的用户才能访问受限资源。
- 数据持久化:可以在会话中存储和获取用户的数据,以便在不同页面和请求之间进行传递和共享。
- 购物车管理:会话可以用于存储用户的购物车内容,并在用户提交订单时进行处理。
- 记录用户行为:可以通过会话来记录用户在网站上的操作和浏览历史,用于统计和个性化推荐等。
需要注意的是,由于会话是在服务器端进行管理的,因此需要在跨页面和跨请求之间正确传递会话ID。一般情况下,浏览器会自动处理这些细节,但在某些特殊情况下,可能需要手动管理会话ID的传递和处理。
我们也可以在web.xml中设置session的超时时间:
<session-config> <session-timeout>30</session-timeout> <!-- 以分钟为单位 --> </session-config>