文章目录
3 jsp技术
jsp
的基本语法、jsp
动作元素的使用jsp
指令和隐式对象的使用jsp
的运行原理
前言
编写Servlet
响应遇到的问题:
我们需要通过拼接字符串的方式把html
写入Servlet
响应中。
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");//一段文本,html响应,字符编码utf-8
String name = req.getParameter("name");
PrintWriter writer = resp.getWriter();
writer.println("<!DOCTYPE html>");
writer.println("<html>");
writer.println("<head>");
writer.println("<meta charset=\"utf-8\">");
writer.println("<title>Servlet + html + </title>");
writer.println("</head>");
writer.println("<body>");
writer.println("<h2>你好" + name + "</h2>");
writer.println("</body>");
writer.println("</html>");
}
实验结果:
- 运行上文代码,即在
Java
中插入html
代码。(此时name为空L)
在URL
配置后,得到了name
知识点:什么是 JSP?
概念:
jsp
全名是Java Server Pages
,它是建立在Servlet
规范之上的动态网页开发技术。- 在
JSP文件
中,HTML代码
与Java代码
共同存在。 - 其中,
HTML代码
用来实现网页中的静态内容的显示,Java代码
用来实现网页中动态内容的显示。
JSP的特征:
- 跨平台:当从一个平台移植到另一个平台时,
JSP
和JavaBean
的代码并不需要重新编译,这是因为Java
的字节码是与平台无关的。 - 业务代码相分离:在使用
JSP
技术开发Web
应用时,可以将界面的开发与应用程序的开发分离。 - 预编译:预编译就是用户第一次通过浏览器访问
JSP
页面时,服务器将对JSP
页面代码进行编译,并且仅执行一次编译。编译好的代码将被保存,在用户下一次访问时,会直接执行编译好的代码。 - 组件重用:
JSP
中可以使用JavaBean
编写业务组件,也就是使用JavaBean
类封装业务处理代码或者作为一个数据存储模型。
JSP
的运行原理:
当一次访问jsp页面时,客户端(即浏览器)会向一个JSP容器(tomcat等)发出请求,servlet容器先要把jsp页面转化为servlet代码(.java),再编译成.class文件再进行调用。当再次访问jsp页面时,会跳过翻译和编译的过程,直接调用,
3.1 创建jsp-对比jsp与生成的Servlet
步骤:
- 编写第一个
JSP
,在其中插入Java
代码 - 查看
jsp
编译的java
文件与class
文件:- 在控制台找到jsp编译的文件的位置:
- 在这个
work/Catalina/localhost/jap_war_exploded/org/apache/jsp
目录下,就可以找到hello_jsp.class
和hello_jsp.java
- 在控制台找到jsp编译的文件的位置:
- 打开
hello_jsp.java
,对比jsp与生成的Servlet
代码:
hello.js
代码:在其中插入了Java
代码
<%@ page contentType="text/html;charset=UTF-8"
pageEncoding="utf-8" %>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<%-- <%= >表示要输出表达式的值%> --%>
<h2>你好 <%= request.getParameter("name")%></h2>
</body>
</html>
实验结果:
- 在
jsp
中插入了Java
代码:
刚开始未在url
中配置name
配置后
- 打开
hello_jsp.java
,对比jsp与生成的Servlet
知识点:JSP 脚本元素、JSP 注释
JSP 脚本元素
JSP
脚本元素是指嵌套在<%
和%>
之中的一条或多条Java
程序代码。
通过JSP
脚本元素可以将Java
代码嵌入HTML
页面中,所有可执行的Java
代码,都可以通过JSP
脚本来执行。- 脚本元素的三种类型
JSP注释
语法格式:<%-- 注释信息 --%>
注意:Tomcat在将JSP页面转换成Servlet的Java程序时会丢弃JSP注释,不会将注释信息发送到客户端。
JSP注释只存在于JSP页面中,转化成java文件就消失了,但是html注释在浏览器中还是可以看到的
3.2 使用jsp的脚本元素并对比Java文件
目标:
三种脚本元素类型 + 两种注释,找到它们在Java
文件中的位置
步骤:
- 编写代码
- 打开网页
http://localhost:8080/jsp_war_exploded/test01.jsp
,查看其中的内容 - 打开
jsp
生成的对应的.java
文件,对比它们在Java
中的位置
代码:
JSP声明语句<%! %>
,代码段<% %>
,JSP表达式:<%= %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>jsp test01</h1>
<%! int a = 2
,
b = 3; %>
<h1>test02</h1>
<%!
void showAb() {
System.out.println("a + b = " + (a + b));
}
%>
<h1>test03</h1>
<%
System.out.println("a * b = " + (a * b));
showAb();
%>
<h1>test04</h1>
<%= a * b %>
</body>
</html>
实验结果:
<%! %>
这个标签所定义的内容,并没有出现在Service
方法中,而是定义成了这个类的成员变量/成员方法
<% %>
出现在Service
方法中,外面没有包裹out.wirte()
<%= %>
出现在Service
方法中,其内容作为一个表达式包裹在out.print()
里面输出
<%-- this is .....--%>
jsp注释只存在于jsp页面
中,转换成Java
文件就消失了
<!-- this is .....-->
转换成Java
文件,html
的注释是在Service
方法中的,是可以看到的的。在浏览器端也是可以看到的。
知识点:JSP 指令
- 为了设置
JSP
页面中的一些信息,可以使用page、include和taglib
指令,每种指令都定义了各自的属性。
page 指令
page
指令用于对页面的某些特性进行描述。例如,页面的编码方式、JSP页面采用的语言等。- 语法为:
<%@ page 属性名="属性值"%>
- page指令提供了一系列与JSP页面相关的属性
language JSP文件采用的语言,默认为Java
import 导包
contentType 根据属性判断文档类型,返回值为文档类型
pageEnCoding 指定页面编码格式
session JSP内是否内置Session对象,返回值为true/false
isErrorPage 该页面是否为错误处理页面,返回值true/false
errorPage 指定一个错误页面
include 指令
include
指令只有一个file
属性,该属性用来指定插入到JSP页面目标位置的文件资源
。(即先把另一个文件包含进来,再翻译成Java文件)include
指令 使用注意的问题:- 被引入的文件必须遵循
JSP
语法,其中的内容可以包含静态HTML
、JSP
脚本元素和JSP
指令等普通JSP
页面所具有的一切内容。 - 除了指令元素之外,
被引入的文件中的内容会插入进当前JSP文件
,然后转换成Servlet
源文件(.java
),插入位置与include
指令在当前JSP
页面中的位置保持一致。
- 被引入的文件必须遵循
- file属性:
- 如果以
/
开头,表示相对于当前Web应用程序的根目录
- 否则,表示
相对于当前文件
。需要注意的是,这里的file属性指定的相对路径是相对于文件(file),而不是相对于页面(page)
- 如果以
- 语法为:
<%@ include file="relativeURL"%>
3.3 JSP指令
page指令
步骤:
- 修改jsp文件模版
win系统就点file---->setting
点击进入
- 创建
jsp
文件info1.jsp
,编写代码,查看运行情况 - 创建
err1.jsp
专门作为错误的展示页面,让info1.jsp
与错误页面err1.jsp
关联,即在info1的中加一句errorPage="err1.jsp"
,访问http://localhost:8080/jsp_war_exploded/ex01/info1.jsp
,即可查看错误页面
代码:
info1.jsp
- 用
page
指令 导包:import=""
- 可以设置
session
,读取session
,因为page
中session
属性默认为true
int x = 1/0
会报错:HTTP状态500 - 内部服务器错误- 在
page
中指定,当发生错误时,由哪个页面来展示错误信息。errorPage=""
<%@ page import="java.util.Date" %>
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" errorPage="err1.jsp" %>
<html>
<head>
<meta charset="UTF-8"></meta>
<title>Title</title>
</head>
<body>
<h1> info1.jsp</h1>
<%= new Date()%>
</br>
<% session.setAttribute("user", "zhang3");%>
<%= session.getAttribute("user")%>
</br>
<% int x = 1 / 0; %>
</body>
</html>
err1.jsp
- 在
page
中配置isErrorPage
,这个页面专门做为错误的展示页面 - 通过
exception
对象拿到错误信息
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" isErrorPage="true" %>
<html>
<head>
<meta charset="UTF-8"></meta>
<title>Title</title>
</head>
<body>
<h2>出错啦.....</h2>
<h3><%=exception.getMessage()%>></h3>
</body>
</html>
实验结果:
info1.jsp实验结果
err1.jsp实验结果:
include指令
步骤:
- 创建
home1.jsp
、home2.jsp
和header.html
- 在
home1.jsp
和home2.jsp
中通过include
指令,引入HTML
文件header.html
- 打开对应网页查看实验结果
代码:
home1.jsp
两行分别是:学生信息管理界面,添加
include指令把header.html指令包含进来
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" %>
<html>
<head>
<meta charset="UTF-8"></meta>
<title>Title</title>
</head>
<body>
<%@ include file="header.html"%>
<h2>学生信息管理界面.....</h2>
<h3>添加....</h3>
</body>
</html>
home2.jsp
两行分别是:教师信息管理界面,添加
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" %>
<html>
<head>
<meta charset="UTF-8"></meta>
<title>Title</title>
</head>
<body>
<%@ include file="header.html"%>
<h2>教师信息管理界面.....</h2>
<h3>添加....</h3>
</body>
</html>
header.html
一行内容:学校信息管理系统
style
中给它加上样式
page中设置pageEncoding,防止中文乱码
<%@ page pageEncoding="UTF-8" %>
<style type="text/css">
.header{
height: 200px;
background: orange;
color: white;
}
</style>
<div>
<h1> 学校信息管理系统</h1>
</div>
实验结果:
知识点:JSP 隐式对象
为了简化Web
应用程序的开发,可使用隐式(内置)对象,它们是JSP
默认创建的,可以直接在JSP页面
中使用。
1. 隐式对象的名称、类型和描述信息
request、response、out
代表输入输出
request
请求输入,response
响应,out
也是用于页面输出
- 这些隐式对象实际上就是在
_jspService()
方法中的,两个形参和方法里定义的局部变量
作用范围
(这四个对象都可以用setAttribute、getAttribute
来共享数据)
pageContext 当前请求
request 当前页面有效
application 整个应用有效
session 当前会话有效
2. out对象
out
对象是java.servlet.jsp.JspWriter
类的实例对象,一种带缓存功能的Writer
,其作用是用来向客户端发送文本形式的实体内容。
写Servlet
时,通过response.getWriter()
方法返回PrintWriter
对象的方法写入数据,写到Response的缓冲区
,刷新的时候,就把数据交给了Servlet引擎
,让它响应给浏览器。
调用out隐式对象的方法写入数据
,写到JspWriter对象的缓冲区
,如果没刷新就会一直往下写,刷新/写满时,再把数据写入Response的缓冲区
中,最后再把这些交给Servlet引擎
3. pageContext 对象
提供了用于获取其他隐式对象的方法,都是get....()
(只要拿到了pageContext
对象,其他隐式对象我们都能拿到)
pageContext 对象还提供了存储数据
的功能
pageContext
对象存储数据是通过操作属性来实现的,其操作属性的一系列方法如下。
其中,参数name
用于指定属性的名称,参数scope
指定的是属性的作用范围,
findAttribute()
方法可以在那4
个域中依次查找数据,查找顺序为:pageContext--->request请求域--->session--->application
4. exception对象
在实验3.3 JSP 指令的include指令实验中,在错误信息展示页面err1.jsp中,只要指定了isErrorPage="true"
,那么这个JSP
页面就可以使用exception
对象
3.4 JSP隐式对象
1. out对象
步骤:
- 创建jsp文件,编写代码
- 分别使用out对象和getWrite()调用的println方法,打印数据
- 观察out的内容和getWrite()的内容出现的顺序
- 在page指令buffer设置为0kb之后,在观察两个内容出现的顺序
代码:
testOut.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" buffer="0kb" %>
<html>
<head>
<meta charset="UTF-8"></meta>
<title>Title</title>
</head>
<body>
<%
out.println("write by out <br>");
// out.flush();//先把它刷到Response缓存区中
response.getWriter().println("second line <br>");
%>
</body>
</html>
实验结果:
当内容为时
<%
out.println("write by out <br>");
response.getWriter().println("second line <br>");
%>
- 此时,
second line
写到了write by out
前面了
- 因为
out
的内容先写在JspWrite缓冲区
,第二行代码的getWrite()
写在了Response缓冲区
,当刷新时,out
就会出现在getWriter
后面
- 当内容为
<%
out.println("write by out <br>");
out.flush();//先把它刷到Response缓存区中
response.getWriter().println("second line <br>");
%>
或page
中加入buffer="0kb"
会先把out
内容刷到缓存区中,显示顺序就正常了
2. pageContext对象
pageContext作为域对象共享数据
步骤:
- 创建data_set.jsp文件,给四个域设置数据
- 创建data_get.jsp文件,获取四个作用域中的数据
- 分析四个作用域的作用范围
代码:
data_set.jsp
给四个域application、session、request、pageContext
设置数据
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" %>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<% application.setAttribute("user1", "user-app-zhang3");%>
application.setAttribute("user1","user-app-zhang3");<br>
<% session.setAttribute("user2", "user-session-zhang3");%>
session.setAttribute("user2", "user-session-zhang3");<br>
<% request.setAttribute("user3", "user-request4-zhang3");%>
request.setAttribute("user3","user-request-zhang3");<br>
<% pageContext.setAttribute("user4", "user-page4-zhang3");%>
pageContext.setAttribute("user4","user-page-zhang3");<br>
</body>
</html>
data_get.jsp
,获取四个作用域中的数据
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" %>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<%= request.getParameter("active")%>
<%--四个作用域,作用的范围不同,在自己的范围内可以进行数据共享,
pageContext当前页面, request当前请求, session同一个会话的多次请求, application整个应用--%>
application: user1= <%= application.getAttribute("user1")%> <br>
session: user2= <%= session.getAttribute("user2")%> <br>
request: user3= <%= request.getAttribute("user3")%> <br>
pageContext: user4= <%= pageContext.getAttribute("user4")%> <br>
</body>
</html>
实验结果:
先访问data_get
:发现没有数据,因为还没有写数据
访问data_set
,写数据:
访问data_get
,读数据:
application
读到了,因为它们是同一个应用
session
读到了,因为它们在cookie里面有相同的JSESSION ID
request
、pageContext
没读到,因为不是同一次请求
知识点:<jsp:include>
动作元素
- 在
JSP
页面中,为了把其他资源的输出内容插入到当前JSP页面的输出内容中,JSP
技术提供了<jsp:include>
动作元素。 - 其语法格式为:
<jsp:include>
工作原理:
<jsp:include>
包含的原理是将被包含的页面编译处理后的结果
包含在页面中。当浏览器第一次请求一个使用<jsp:include>
包含其他页面的页面时,Web容器首先会编译被包含的页面,然后将编译处理后的返回结果包含在页面中,之后编译包含页面,最后将两个页面组合的结果回应给浏览器。<jsp:forward>
动作元素将当前请求转发到其他Web资源
(HTML页面、JSP页面和Servlet等)。在执行请求转发之后,当前页面不再执行,而是执行该元素指定的目标页面。- 语法格式:
<jsp:forwar page="relativeURL" />
3.5 <jsp:include>
动作元素
步骤:
- 在
data_set.jsp
中,加入分割线<hr>
,通过<jsp:include>
将data_get.jsp
包含在页面中。
代码:
data_set.jsp:请求包含<jsp:include>
的使用
在<jsp:include> </jsp:include>
这里面可以给它指定参数
在data_get.jsp
中调用getParameter()
方法来获得参数
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" %>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<% application.setAttribute("user1", "user-app-zhang3");%>
application.setAttribute("user1","user-app-zhang3");<br>
<% session.setAttribute("user2", "user-session-zhang3");%>
session.setAttribute("user2", "user-session-zhang3");<br>
<% request.setAttribute("user3", "user-request4-zhang3");%>
request.setAttribute("user3","user-request-zhang3");<br>
<% pageContext.setAttribute("user4", "user-page4-zhang3");%>
pageContext.setAttribute("user4","user-page-zhang3");<br>
<hr>
<jsp:include page="data_get.jsp">
<jsp:param name="active" value="edit"/>
</jsp:include>
</body>
</html>
data_get.jsp:
通过调用getParameter()
方法来获得在data_set.jsp
中<jsp:include> </jsp:include>
中设置的参数
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" %>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<%= request.getParameter("active")%>
<%--四个作用域,作用的范围不同,在自己的范围内可以进行数据共享,
pageContext当前页面, request当前请求, session同一个会话的多次请求, application整个应用--%>
application: user1= <%= application.getAttribute("user1")%> <br>
session: user2= <%= session.getAttribute("user2")%> <br>
request: user3= <%= request.getAttribute("user3")%> <br>
pageContext: user4= <%= pageContext.getAttribute("user4")%> <br>
</body>
</html>
实验结果:
使用include
时,访问页面http://localhost:8080/jsp_war_exploded/ex04/data_set.jsp
,当前页面data_set
的内容有,目标页面data_get
的内容也有
在data_set.jsp
中把include
改为forward
,访问页面http://localhost:8080/jsp_war_exploded/ex04/data_set.jsp
,就只有目标页面data_get
的内容
3.6 实现注册页面
步骤:
任务目标:使用jsp
改写html
;实现修改登录页面,错误时显示用户名;引用公共页面
实现步骤:
- 修改
login.jsp
(需要修改LoginServlet.java和login.jsp中的内容) - 创建
home.jsp
(需要修改HomeServlet.java和home.jsp中的内容) - 运行项目,查看结果
- 引用
header.jsp
代码:
LoginServlet.java
当登录成功时,重定向到home.jsp
当登录失败时,请求转发到login.jsp
,且要把用户名数据传过去,
这里我们没有把数据放在session
里面,而是单独发过去,表示在本次请求里有效。
在login.jsp
中通过request.getAttribute("user")
把转发过来的user填进value里
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
String username = req.getParameter("username");
String pwd = req.getParameter("pwd");
String checkcode = req.getParameter("checkcode");
System.out.println("LoginServlet用户输入的验证码:" + checkcode);
// String s = CheckCodeServlet.instance.s;
// System.out.println("LoginServlet随机生成的验证码: " + s);
HttpSession session = req.getSession();
/**
* 前三个条件,保证可以从session中拿到验证码信息,分别是保证session不为空;
* session里有存验证码信息的键值对,name为code;
* 用户输入的验证码checkcode不为空,空不能使用equals语句
* 最后一个条件是,检验密码、验证码是否正确;
*/
if (session != null && session.getAttribute("code") != null && checkcode != null &&
"123".equals(pwd) && checkcode.equals(req.getSession().getAttribute("code"))) {
req.getSession().setAttribute("user", username);
//如果登录成功,重定向跳转到home页面
req.getRequestDispatcher("home.jsp").forward(req, resp);
} else {
//如果验证失败,请求转发到login.jsp,且要把用户名数据传过去
//数据不放在session里面,单独发过去,表示在本次请求里有效
req.setAttribute("user", username);
req.getRequestDispatcher("login.jsp").forward(req, resp);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
login.jsp
将login.html
改为login.jsp
在login.jsp
中通过request.getAttribute("user")
把从LoginServlet.java
转发过来的user
填进value
里
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" %>
<html>
<head>
<meta charset="UTF-8"></meta>
<title>Title</title>
</head>
<body>
<form action="login" method="post">
<input type="text" name="username" placeholder="账号" value="<%=request.getAttribute("user") %>"/><br/><br/>
<input type="text" name="pwd" placeholder="密码"/><br/><br/>
<%-- 功能:点击验证码图片,刷新验证码--%>
<%-- 当点击这张图片时,就会执行下面的script代码--%>
img: <img id="code" alt="" src="check" onclick="freash()">
<script>
function freash() {
let check = document.getElementById("code");
check.src = "check?" + new Date().getTime();
console.log("freash2....")//控制台上输出freash....
}
</script>
<br/>
<%-- 输出框、登录按钮--%>
<p>请输入验证码:</p>
<input type="text" name="checkcode" placeholder="验证码"/><br/><br>
<input type="submit" value="登录">
</form>
</body>
</html>
HomeServlet.java
如果session中有用户信息,即有用户登录,就通过req.getRequestDispatcher,请求转发到home.jsp。
再在home.jsp中把数据取出来
@WebServlet("/home")
public class HomeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置编码方式
resp.setContentType("text/html;charset=utf-8");
//判断用户是否在登录状态,如果不在登录状态,要重定向到login.html
HttpSession session = req.getSession();
//如果有session对象,并且session对象当中已经保存了user
if (session != null && session.getAttribute("user") != null) {
//展示信息
req.getRequestDispatcher("home.jsp").forward(req,resp);
} else {
//重定向
req.getRequestDispatcher("login.jsp").forward(req,resp);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
home.jsp
-
如何拿到用户名?
通过homeServlet
把数据传过来,传到jsp
里面,让jsp
去展示。 -
jsp
负责展示信息,servlet
负责取得数据 -
在
home.jsp
中把数据取出来
取session
中的数据:通过session.getAttribute("user")
取出
<%@ page contentType="text/html;charset=UTF-8" language="java"
pageEncoding="UTF-8" %>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>管理首页</h1>
<h4>登录用户:<%=session.getAttribute("user")%>
</h4>
<a href='logout'>退出登录</a><br/>
添加成绩<br/>
修改成绩<br/>
....<br/>
</body>
</html>
LogoutServlet.java
重定向到login.jsp
@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//删除session中的数据
if (req.getSession() != null) {
req.getSession().removeAttribute("user");
}
//重定向到login.html
resp.sendRedirect("login.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
CheckCodeServlet.java
@WebServlet("/check")
public class CheckCodeServlet extends HttpServlet {
//刚开始想的是通过一个字符串s获得4个随机生成的字母,再传给LoginServlet进行验证
//即用login里打注释的那两行代码接收字符串s
// public String s = "";
// public static CheckCodeServlet instance;
//
// @Override
// public void init() throws ServletException {
// super.init();
// instance = this;
// }
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1. content-type 返回图片类型
String mimeType = getServletContext().getMimeType(".jpg");
System.out.println("mimetype" + mimeType);
resp.setContentType(mimeType);
//2. 画图大小
int w = 100;
int h = 50;
//3. 生成BufferedImage对象
BufferedImage bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics graphics = bufferedImage.getGraphics();
//4. 填充矩形
graphics.setColor(Color.LIGHT_GRAY);//颜色
graphics.fillRect(0, 0, w, h);//矩形从左上角(0,0)到(x,y)
//5. 画外框
graphics.setColor(new Color(34, 34, 250));//先设置一个颜色
graphics.drawRect(0, 0, w - 1, h - 1);//画一个矩形框
//6. 在这张图片上写4个字母
String s = new String();
graphics.setFont(new Font("", Font.BOLD, 20));
Random random = new Random();
for (int i = 0; i < 4; i++) { //随机生成4个字符,画在图片里
char x = (char) ('A' + random.nextInt(25));
s = s + x;
graphics.drawString("" + x, 5 + i * 20, 30);
}
System.out.println("验证码Servlet随机生成的验证码为:" + s);
//将字符串s保存在session中
HttpSession session = req.getSession();
session.setAttribute("code", s);
//7. 画随机线条
for (int i = 0; i < 10; i++) {
int x1 = random.nextInt(100);
int x2 = random.nextInt(100);
int y1 = random.nextInt(50);
int y2 = random.nextInt(50);
graphics.drawLine(x1, y1, x2, y2);
}
//8. 把图片写出到输出流
ImageIO.write(bufferedImage, "jpg", resp.getOutputStream());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
实验结果:
- 还没有登录时,访问
home
页面,自动跳转到login.jsp
- 验证失败,自动跳转到
login.jsp
,且用户名被保存
- 验证码和密码输入正确,自动跳转到
home.jsp
,
用户名被保存在session
中,home.jsp
拿到session
中的用户名并输出。
- 此时已经登录成功了,且没有退出登录,即
session
中数据未被删除
访问home
页面,自动跳转到home.jsp
- 点击退出登录,会删除
session
中的数据,并重定向到login.jsp
中
小技巧:当jsp页面修改了,不需要重启tomcat,只要点击一下部署按钮即可
例子:
这是一个修改后的页面
点击部署按钮