一、了解Servlet
Servlet是移动动态网页技术。Servlet是由
Java
语言编写的Web服务端程序,也需要JDK和JRE的支持,还需要放置在支持Servlet的Web服务器中运行。本次使用的是tomcat来配置,
Servlet以面向对象的形式解释了HTTP请求和响应内容,它将HTTP请求的内容封装未
HttpServletRequest
对象。用户访问某个网址显示的网页内容,就是服务器通过 HttpServletResponse
对象发送到浏览器的数据。
1.1安装Servlet
系统 | Web服务器 | 代码工具 | 书 |
---|---|---|---|
windows | Tomcat | eclipse | JavaEE企业级框架开发实战教程(蜗牛学院) |
安装完成Eclipse之后创建项目
随后填写 Group_id
公司域名,可以随意填写,然后 Artifact Id
就是项目名称,创建web项目需要选择war
创建好的文件夹的为一下
此时还需要周期webapp目录下创建宇哥
web.xml
文件,右键点击 Deployment Descriptor:servlet
,然后点击 Genterate Deployment Descriptor
选项,就会自动创建 web.xml
文件
2.2配置tomcat
接下来开始配置tomcat,安装tomcat这里就不在赘述了(将tomcat的安装包解压到你想要安装的目录下),安装完成tomcat之后,进入eclipse,在代码下方栏目中选择
Servers
,点击下方蓝色字体,在 Apache
目录下选择你对应的Tomcat的版本然后点击Next
选择你Tomcat安装的目录,点击 finish
在servers双击Tomcat服务器会弹出一个配置,按照以下配置即可
在刚刚的 servers
栏目中选择然后,点击启动 tomcat
进入浏览器访问
配置成功后就可以进入编码工作,一个Web项目的Servlet编码主要包裹以下几个步骤:
1.导入jar包
导入jar包一般是通过Maven导入,需要编写pom.xml配置文件,这里导入Servlet包
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tc</groupId>
<artifactId>servlet</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
2.编写Servlet类
在 src/mian/java
中创建servlet包,在包内创建一个HelloServlet类,继承来自HttpServlet类,并且重写service方法
代码:
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.rmi.ServerException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloServlet extends HttpServlet{
@Override
public void service(HttpServletRequest request,HttpServletResponse response) throws ServerException,IOException {
response.setContentType("text/html;charset=utf-8");
response.setCharacterEncoding("UTF-8");
PrintWriter pw = response.getWriter();
pw.write("HelloWorld!");
pw.close();
}
}
3.编写路由
即浏览器请求到大web容器,并指定处理该请求的Servlet类。需要在web.xml中以标签的形式进行配置,完整的配置包括servlet标签和servlet-mapping标签
servlet标签中的servlet-name表示对Servlet进行命名,在整个web容器中该值是唯一,servlet-class表示方法类的路径
servlet-mapping是请求映射标签,表示HTTP请求与Servlet类的对应关系,和servlet-name进行关联
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name>servlet</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<!-- hello访问路径 -->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
随后启动服务,选择配置好的tomcat的服务器,进入浏览器输入下面的 url
即可
二、动态页面JSP
Jsp是Sun公司联合其他公司一起建立的一种动态网页技术,可以在HTML中直接嵌套java代码的一种技术,他比直接使用servlet代码来显示要方便的多
Servlet使用JSP:
- 代码与视图的分离:在仅使用Servlet的应用中,服务器端的Java代码需要通过打印语句来生成HTML内容,这导致表示层和业务逻辑层混杂在一起,不利于代码的维护和更新。而JSP允许Java代码和HTML标记共存于一个文件中,使得UI设计师可以专注于页面设计,程序员则负责业务逻辑,这种分工合作提高了开发效率。
- 简化开发流程:使用Servlet时,每次修改代码都需要重新编译、部署和重启服务,这在开发过程中非常不便。JSP文件在第一次请求时会被转换成Servlet,之后的请求则直接由这个编译后的Servlet处理,这样减少了重新编译和部署的次数。
- 动态内容生成:Servlet通过HttpServletResponse对象动态输出HTML内容,这种方式在处理复杂的页面时会显得繁琐。JSP允许在HTML中嵌入Java代码,这些代码在页面被请求时动态执行,从而生成最终的HTML内容,这种方式更加直观和方便。
- 提升性能:JSP文件在第一次请求时转换成Servlet,并编译成字节码,之后的请求都由这个已编译的Servlet处理,这样可以提高响应速度。
- 更好的适应MVC模式:在MVC(模型-视图-控制器)设计模式中,Servlet通常作为控制器组件,负责处理用户的请求和调用业务逻辑;而JSP则作为视图组件,负责显示数据。这种分离使得应用结构更清晰,更易于管理和维护。
总的来说,JSP为Servlet提供了一种更为简洁和高效的方式来处理Web应用中的视图层,使得开发人员能够更加专注于业务逻辑的实现,同时提高了Web应用的性能和可维护性。
1.创建jsp文件
在webapp文件目录下创建jsp文件
创建好jsp文件如下代码第一行比html多了一个
<%@ %>
的代码,这是JSP的文档声明,pageEncoding表示当前的表面,ContentType表示服务器发送给客户端的MIME类型编码,注意这里需要讲ISO-8859-1都切换成UTF-8
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
</body>
</html>
修改为:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<p>Hello World!!!</p>
</body>
</html>
打开浏览器访问
2.jsp中的代码片段
JSP页面中可以包含多种类型的Java代码,具体如下:
- Java代码片段(Scriptlets):这是嵌入在
<% %>
标签中的代码,可以执行任何有效的Java语句。通常用于编写业务逻辑或控制页面的流程。 - JSP表达式:使用
<%= %>
标签包围,主要用于在JSP页面中输出变量的值或者执行简单的算术运算。 - JSP声明:在
<%! %>
标签中声明的代码,用于声明变量和方法,这些变量和方法的作用范围是整个页面。 - JSP指令:包括
page
、include
和taglib
等指令,它们用于设置页面属性、包含其他文件或引入标签库。 - JSP动作:如
<jsp:include>
、<jsp:forward>
等,用于包含其他文件或转发请求到其他资源。 - JSP注释:使用
<%-- --%>
标签,用于在JSP文件中添加注释,这些注释不会出现在生成的HTML中。
JSP是属于服务端的文档,而属于客户端的浏览器可以解释HTML、CSS、JavaScript等文档,但无法解释java语言,只能由服务器进行解释,Java文档在服务器端运行,运行时会被当成Web容器解释为一个Servlet类。Web容器对JSP页面进行解释时遵循以下规则
- JSP文档中的HTML代码会被翻译为Servlet类中的out.write()语句
- JSP文档中的表达式最终显示的是其运行的结果
- JSP文档中的
java
片段会被翻译为Servlet类中的service方法中的代码 - JSP文档中的声明会被翻译为Servlet类中的成员变量或者成员方法
3.jsp的内置对象
JSP提供了一系列的内置对象,这些对象可以在JSP页面中直接使用,无需事先声明。下面是一个简单的表格列出了常用的JSP内置对象及其作用:
内置对象 | 描述 |
---|---|
pageContext | 提供对页面上下文信息的访问,包括请求参数、属性范围等。 |
request | 代表客户端的请求信息,提供请求参数、请求头、Cookie等信息的访问。 |
response | 代表服务器的响应信息,用于设置响应头、Cookie、输出结果等。 |
out | 对应于响应输出流,通常用于输出HTML内容到客户端。 |
session | 代表用户会话信息,用于在多个页面之间共享用户数据。 |
application | 代表应用程序级别的全局变量,用于所有用户共享的数据。 |
config | 提供对Servlet配置信息的访问,如初始化参数等。 |
page | 代表当前JSP页面的实例对象,也就是转换后的Servlet类的实例。 |
exception | 用于捕获JSP页面中的异常信息,通常与错误处理结合使用。 |
这些内置对象在JSP页面中非常有用,它们提供了一种方便的方式来访问和操作Web应用程序的各种信息。通过合理地使用这些内置对象,可以简化代码、提高开发效率,并实现更加灵活和动态的Web应用。
4.JSP的作用域
JSP有四种不同的作用域,它们规定了数据在Web应用程序中的可见性和生命周期。下面是一个表格,列出了这四个作用域及其描述:
作用域 | 描述 |
---|---|
页面(Page)作用域 | 这是默认的作用域,仅在当前JSP页面有效。它开始于生成响应的页面,并结束于该页面的输出。 |
请求(Request)作用域 | 在单个用户请求期间有效,可用于多个页面。当请求被转发或者包含到其他页面时,数据仍然保留。 |
会话(Session)作用域 | 跨越多个请求期间在一个用户会话中有效。它开始于用户登录或首次访问应用程序,并持续到会话过期或被终止。 |
应用(Application)作用域 | 在整个Web应用程序中有效,对所有用户和会话可用。它开始于Web应用程序启动,并持续到应用程序被关闭或卸载。 |
这些作用域通过不同的范围定义了数据的可见性,允许开发人员根据需要选择合适的作用域来存储和访问数据。了解这些作用域有助于更好地管理状态信息,并确保数据的一致性和安全性。
5.EL表达式语言
EL可以使得JSP写起来更加简单,提供了在JSP中简化表达式的方法,使JSP打代码更加简练,他的语法要比JS更加简单
${}
即可,它不仅仅可以完成简单的运算,还可以获取作用域中的值还有JavaBean,集合等等,
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>el表达式</title>
</head>
<body>
EL表达式计算:<br>
&nsbp; 1、${3+3}<br>
2、${true || false}<br>
3、${1==1?"张三":"李四"}<br>
El表达式接受前端参数:<br>
${param.uname}<br>
el表达式获取request作用域数据: <br>
${requestScope.msg}<br>
EL表达式获取JavaBean对象的属性值:<br>
${user.name}<br>
El表达式获取集合的值:<br>
我叫${map.name},今年${map.age}岁了,${map.sex}<br>
${list[0]},${list[1]}<br>
</body>
</html>
如果你需要获取一个叫name的值,在EL中直接${name }即可,他会从下往上依次从作用域中寻找一个叫name的值,如果你知道值的准确位置,可以直接加上作用域:
作用域 | EL语法 | 描述 |
---|---|---|
页面作用域 | ${pageScope.variable} | 只在当前JSP页面有效,用于存储和访问局部于当前页面的数据。 |
请求作用域 | ${requestScope.variable} | 在整个用户请求期间有效,可用于多个页面。常用于在不同页面之间传递数据。 |
会话作用域 | ${sessionScope.variable} | 跨越多个请求期间在一个用户会话中有效,用于存储和访问用户特定的数据。 |
应用作用域 | ${applicationScope.variable} | 在整个Web应用程序中有效,对所有用户和会话可用,用于存储和访问全局数据。 |
这些EL语法提供了一种方便的方式来访问和操作不同作用域中的数据,使得在JSP页面中处理数据变得更加简单和灵活。通过合理地使用EL语法,可以更好地管理和维护JSP页面中的数据,并提高代码的可读性和可维护性。
6.JSTL标准标签库
JSTL(JavaServer Pages Standard Tag Library)是一个JSP标准标签库,旨在简化JSP页面上的Java代码编写。
JSTL是Java社区过程(JCP)制定的标准规范,由Apache的Jakarta小组维护。它提供了一系列标准化的标签,用于执行常见的Web开发任务,如条件判断、迭代、XML文档操作、国际化和SQL操作等。这些标签分为以下几类:
- 核心标签:提供了用于流程控制、循环和其他基本功能的标签。
- 格式化标签:用于日期和时间格式化、数字格式化以及货币格式化等。
- SQL标签:简化了数据库交互,允许直接在JSP页面中执行SQL查询和更新操作。
- XML标签:用于解析和操作XML文档。
- 函数标签:提供了一些常用的字符串处理函数。
使用JSTL的好处在于它可以替代JSP页面中的脚本代码,使得页面更加整洁,同时也便于维护和理解。此外,JSTL标签库是可扩展的,允许开发者创建和使用自定义标签。
总的来说,JSTL是一个强大的工具,它通过提供一组标准的标签库,帮助开发者更高效地构建JSP应用程序。
代码:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<!-- if标签 -->
${name }是一个
<c:if test="${age>25 }" var="is">
年轻人
</c:if>
<c:if test="${!is }">
中年人
</c:if>
<!-- set标签 -->
<br><c:set var="a" value="hello"></c:set>
${pageScope.a}<br>
<br><c:set var="b" value="hello2"></c:set>
${pageScope.b}<br>
<!-- remove标签 -->
<c:remove var="a" />
${pageScope.a}<br>
<br><c:set var="a" value="hello3"></c:set>
${pageScope.a}<br>
<!-- choose标签 -->
<c:choose>
<c:when test="${age>25 }">不年轻</c:when>
<c:when test="${age==25 }">刚刚好</c:when>
<c:otherwise>太小</c:otherwise>
</c:choose>
</body>
</html>
java代码:
package com.tc.entiy;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class JstlServlet extends HttpServlet{
/**
*
*/
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException {
req.setAttribute("name", "李四");
req.setAttribute("age", 25);
req.getRequestDispatcher("jstl.jsp").forward(req, resp);
}
}
三.过滤器
Servlet 过滤器是 Java Web 开发中用于处理请求和响应的组件,它可以在请求到达目标资源之前或响应返回给客户端之后进行拦截、检查和修改。
Servlet 过滤器的主要功能包括:
- 请求拦截:在客户端的请求访问后端资源之前,过滤器可以拦截这些请求,进行必要的预处理。
- 响应处理:在服务器的响应发送回客户端之前,过滤器可以对响应进行处理,如添加头部信息或修改内容。
- 类型多样:根据规范建议,有多种类型的过滤器,如身份验证、数据压缩、加密、图像转换、日志记录和审核等。
此外,Servlet 过滤器的工作机制包括以下几个步骤:
- 创建和配置:开发人员需要创建一个实现了 javax.servlet.Filter 接口的类,并实现其中的 init(FilterConfig)、doFilter(ServletRequest, ServletResponse, FilterChain) 和 destroy() 方法。
- 部署和映射:在 web.xml 配置文件中部署过滤器,并定义它应该拦截的请求模式和URL路径。
- 链式处理:过滤器可以按照在 web.xml 中定义的顺序组成一个链,请求会依次通过这个链中的每个过滤器。
总的来说,Servlet 过滤器提供了一种强大且灵活的方式来处理Web应用中的请求和响应,它使得开发人员能够以模块化的方式增强应用程序的功能,而无需修改核心的业务逻辑代码。
四、简单实验
1.编写登录界面。使用 from
表单,在 WEB-INF
创建
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
</head>
<body>
<div>
<h3>登录</h3>
<form action="login" method="post">
用户名: <input name="uname"><span style="color:red">${msg }</span><br>
密 码:
<input name="password" type="password"><br>
<input type="submit" value="登录">
</form>
</div>
</body>
</html>
2.在编写一个 index.html
文件用于登录进去
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
welcome,${uname}! <a href="logout">退出登录</a>
3.开始编写Servelt类,首先需要在 src/mian/java
中创建一个包,包名无限制,如何在包内创建一个一个 login
类
package com.woniu.servlet;
import java.io.IOException;
import java.rmi.ServerException;
import javax.security.auth.login.LoginContext;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class LoginServlet extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public void service(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{
String uname = req.getParameter("uname");
String password = req.getParameter("password");
HttpSession session = req.getSession(); //创建session对象
Cookie cookie = new Cookie("SESSIONID", session.getId());
cookie.setPath(password);
cookie.setMaxAge(0);
resp.addCookie(cookie);
if("tc".equals(uname)) {
if("000000".equals(password)) {
session.setAttribute("uname",uname); //将数据存储到session对象中
resp.sendRedirect("index.jsp"); //Redirect 转发
return;
}
}
else {
session.setAttribute("msg", "用户名或密码错误");
resp.sendRedirect("login.jsp"); //转发
}
}
}
4.在创建一个 logou
的类
package com.woniu.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class LogoutServlet extends HttpServlet{
/**
*
*/
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException {
HttpSession session = req.getSession();
session.invalidate();
resp.sendRedirect("login.jsp");
}
}
5.编写限制登录策略
package com.woniu.servlet;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class LoginFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse resp = (HttpServletResponse)response;
String uri = req.getRequestURI();
uri = uri.substring(1);
uri = uri.substring(uri.indexOf('/')+1);
if("login".equals(uri) || "login.jsp".equals(uri)) {
chain.doFilter(req, resp);
return;
}
HttpSession session = req.getSession();
String uname = (String)session.getAttribute("uname");
if(uname != null &&!"".equals(uname)) {
chain.doFilter(req, resp);
return;
}
resp.sendRedirect("login.jsp");
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
}
6.访问次数策略
package com.woniu.servlet;
import java.io.IOException;
import java.net.URL;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.swing.plaf.synth.Region;
public class CountFilter implements Filter {
int count_login = 0;
int count_index = 0;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("开始统计人数");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)request;
String uri = req.getRequestURI();
System.out.println("访问页面为:"+uri);
uri = uri.substring(1);
uri = uri.substring(uri.indexOf('/')+1);
if(uri.equals("login.jsp")){
//收到请求访问人数就+1
count_login++;
System.out.println("当前页面访问次数为:"+count_login);
chain.doFilter(request, response);
return;
}else if (uri.equals("index.jsp")) {
count_index++;
System.out.println("当前页面访问次数为:"+count_index);
chain.doFilter(request, response);
return;
}else {
chain.doFilter(request, response);
}
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
}
5.编写 web.xml
代码
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name>servlet2</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.woniu.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<!-- login访问路径 -->
<url-pattern>/login</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>logout</servlet-name>
<servlet-class>com.woniu.servlet.LogoutServlet</servlet-class>
<!-- 自动启动 -->
<load-on-startup>1</load-on-startup>
<!-- 配置初始化信息 -->
</servlet>
<servlet-mapping>
<servlet-name>logout</servlet-name>
<!-- logout访问路径 -->
<url-pattern>/logout</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>jstl</servlet-name>
<servlet-class>com.tc.entiy.JstlServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>jstl</servlet-name>
<!-- jstl访问路径 -->
<url-pattern>/jstl</url-pattern>
</servlet-mapping>
<filter>
<filter-name>login</filter-name>
<filter-class>com.woniu.servlet.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>login</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>count</filter-name>
<filter-class>com.woniu.servlet.CountFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>count</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>