javaweb基础知识整理
1、项目基本结构
代码分层:
1.1、entity层(model层,domain层)
简称实体层用于存放我们的实体类,类中定义了多个类属性,并与数据库表的字段保持一致,一张表对应一个类。
1.2、mapper层(dao层)
介绍: 数据持久层,先设计接口,然后在配置文件中进行配置其实现的关联。对数据库进行数据持久化操作,他的方法语句是直接针对数据库操作的。
作用:该层的作用为访问数据库,向数据库发送sql语句,完成数据的增删改查任务。
持久化操作: 数据持久化操作就是指,把数据放到持久化的介质中,同时提供增删改查操作。
1.3、Service层
用来存放业务逻辑处理,也是一些关于数据库处理的操作,但不是直接和数据库打交道
可以在Service层调用dao层的接口进行业务逻辑应用的处理。
1.4、until层
工具层,此项目把链接数据库的操作放在此处,如图
2、Tomcat的使用
转载:https://blog.youkuaiyun.com/qq_42146402/article/details/127584276
2.1 web服务器
Web服务器一般指网站服务器,是指驻留于因特网上某种类型计算机的程序,可以处理浏览器等Web客户端的请求并返回相应响应,也可以放置网站文件,让全世界浏览;可以放置数据文件,让全世界下载。最主流的三个Web服务器是Apache、 Nginx 、IIS。
2.2 Tomcat
Tomcat 是一个Web应用服务器,Tomcat是Apache 服务器的扩展,当配置正确时,Apache 为HTML页面服务,而Tomcat 实际上运行JSP 页面和Servlet。
2.3 Tomcat目录结构
Tomcat目录介绍:
- bin:专门用来存放 Tomcat 服务器的可执行程序
- conf:专门用来存放 Tocmat 服务器的配置文件
- lib:专门用来存放 Tomcat 服务器的 jar 包
- logs:专门用来存放 Tomcat 服务器运行时输出的日记信息
- temp:专门用来存放 Tomcdat 运行时产生的临时数据
- webapps:专门用来存放部署的 Web 工程。
- work:是 Tomcat工作时的目录,用来存放 Tomcat 运行时 jsp 翻译为 Servlet 的源码,和 Session 钝化的目录
2.4、修改Tomcat的端口号和主机名称
Tomcat 默认的端口号是:8080,要想修改Tomcat的端口号,找到 Tomcat 目录下的 conf 目录,再找到 server.xml 配置文件:
找到如下位置修改port值(端口号):
找到如下位置修改主机名称:
2.5、在idea配置Tomcat
- (1)打开IDEA,创建一个Web项目
- (2) 配置Tomcat服务器
- (3) 点击启动按钮启动Tomcat服务器,在浏览器中输入网址http://localhost:8080/即可在开发阶段访问网站
3、数据库链接(JDBC)
3.1、数据库驱动
我们安装好数据库之后,我们的应用程序也是不能直接使用数据库的,必须要通过相应的数据库驱动程序,通过驱动程序去和数据库打交道。
3.2、JDBC简介
SUN公司为了简化、统一对数据库的操作,定义了一套Java操作数据库的规范(接口),称之为JDBC。这套接口由数据库厂商去实现,这样,开发人员只需要学习jdbc接口,并通过jdbc加载具体的驱动,就可以操作数据库。
3.3、异常处理
1)、什么是异常
错误产生于没有实现预料到的各种情况,或是超过了程序员可控制范围的环境因素。
常见的异常:算术异常、数组越界、空指针
2)、如何捕获异常
try{
// 可能产生异常错误的语句
}catch( ExceptionTypeOne e){
// 对异常 ExceptionTypeOne 的处理语句
}catch ( ExceptionTypeTwo e) {
// 对ExceptionTypeTwo 的处理语句
}
...........
finally {
// 语句块
}
- finally为异常处理的最后执行部分,无论前面的catch是否被捕捉,finally语句都会被执行
3)、常见的异常
java内部提供了一些异常,用来描述经常发生的错误,其中,有的需要程序员极性捕捉处理或声明抛出。有的是由java虚拟机自动进行捕捉
java常见的异常类如表:
4)、运行时异常
java类库的每个包中都定义了异常类,所有的类都是Throwable的子类,Throwable派生出两个子类,分别是Exception 和 Error 类。 Error 类及其子类用来描述java运行系统中的内部错误以及资源消耗的错误。
Exception类异常通过捕捉后程序可以继续正常执行。
Throwable 是异常处理体系的顶层类,派生除了Error 和 Exception 两个重要的子类。Error 指的是java虚拟机无法解决的严重问题,例如jvm内部错误,资源耗尽等等,其代表为: StackOverflowError 和 OutOfMemoryError。
Exception 异常类为程序员可以正常捕捉并处理的异常。
5)、异常处理流程
(1)程序先执行 try 中的代码 如果 try 中的代码出现异常 , 就会结束 try 中的代码 , 看和 catch 中的异常类型是否匹配 . 如果找到匹配的异常类型, 就会执行 catch 中的代码 如果没有找到匹配的异常类型, 就会将异常向上传递到上层调用者 .
(2)无论是否找到匹配的异常类型, finally 中的代码都会被执行到 ( 在该方法结束之前执行 ).
(3)如果上层调用者也没有处理的了异常, 就继续向上传递 . 一直到 main 方法也没有合适的代码处理异常 , 就会交给 JVM 来进行处理 , 此时程序就会异常终止。
3.4、jdbc程序示例
(简要概括: Properties类是 键和值均为字符串的可以永久存储到文件中的key-value集合
java.util.Properties类表示一组持久的属性,是Hashtable的子类。 Properties可以保存到流中或从流中加载,可以保存到后缀名为properties的文件中。 属性列表中的每个键及其对应的值都是一个字符串。 即键和值都是String类型。)
database.properties如下
dirver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/edudb
user = root
password = 123456
DbUtil类:
package com.itdj.edu.Util;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class DbUtil {
private static String dirver;
private static String url;
private static String user;
private static String password;
public Connection connection = null;
static {
try {
Properties properties = new Properties();
/*类加载器来进行配置文件的载入*/
InputStream inputStream = DbUtil.class.getClassLoader().getResourceAsStream("database.properties");
properties.load(inputStream);
/*获取驱动、url等*/
dirver = properties.getProperty("dirver");
url = properties.getProperty("url");
user = properties.getProperty("user");
password = properties.getProperty("password");
} catch (IOException e) { //输入输出异常
throw new RuntimeException(e); //抛出运行时异常,程序可以正常捕捉并处理的异常
}
}
//获取链接对象
public Connection getConnection() {
Connection connection = null;
try {
//1.注册驱动
Class.forName(dirver);
//2、获取数据库连接对象connection
connection = DriverManager.getConnection(url, user, password);
} catch (ClassNotFoundException e) { //未找到相应的类异常
throw new RuntimeException(e);//抛出运行时异常,程序可以正常捕捉并处理的异常
} catch (SQLException e) { //操作数据库异常类
throw new RuntimeException(e);//抛出运行时异常,程序可以正常捕捉并处理的异常
}
return connection;
}
//释放资源
public void closeAll(Connection connection, Statement statement, ResultSet resultSet){
try {
if (resultSet != null) {
resultSet.close();
}
if (statement != null) {
statement.close();
}
if(connection != null) {
connection.close();
}
} catch (SQLException e) { //操作数据库异常类
throw new RuntimeException(e);//抛出运行时异常,程序可以正常捕捉并处理的异常
}
}
public int executeUpdate( String sql, Object[] params){//sql为执行语句,params为填充参数
/*PreperedStatement是Statement的子类,相对于Statement对象而言:PreperedStatement可以避免SQL注入的问题。*/
PreparedStatement preparedStatement = null;
int num = 0;
try {
connection = getConnection();
preparedStatement = connection.prepareStatement(sql);//1、获取preparedStatement
for (int i = 0; i < params.length; i++) {
preparedStatement.setObject(i+1,params[i]);//2、设置参数
}
num = preparedStatement.executeUpdate();//3、执行sql语句
} catch (SQLException e) {//操作数据库异常类
throw new RuntimeException(e);//抛出运行时异常,程序可以正常捕捉并处理的异常
} finally { //无论是否发现异常此处都会执行,释放资源
closeAll(connection, preparedStatement, null);
}
return num;
}
}
3.5、Druid连接池
Druid(德鲁伊)是阿里巴巴开发的号称为监控而生的数据库连接池,Druid是目前最好的数据库连接池。在功能、性能、扩展性方面,都超过其他数据库连接池,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况。
要使用Druid连接池,首先把jar包导入项目,通过druid.properties配置文件进行配置,常用的参数如下
db.properties如下
dirver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/edudb
user = root
password = 123456
initalSize=5
maxActive=10
maxWait=5000
DsUtil类:
package com.itdj.edu.Util;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class DsUtil {
public Connection connection = null;
private static DataSource dataSource;
static {
try {
Properties properties = new Properties();
/*类加载器来进行配置文件的载入*/
InputStream inputStream = DsUtil.class.getClassLoader().getResourceAsStream("ds.properties");
properties.load(inputStream);
/*获取连接池对象*/
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//获取链接对象
public Connection getConnection() {
try {
/*数据源(DataSource)即数据来源,调用DataSource.getConnection(),即可获取一个连接,而无需关心连到哪个数据库,用户名/密码是什么.*/
dataSource.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
return connection;
}
//释放资源
public void closeAll(Connection connection, Statement statement, ResultSet resultSet){
try {
if (resultSet != null) {
resultSet.close();
}
if (statement != null) {
statement.close();
}
if(connection != null) {
connection.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public int executeUpdate( String sql, Object[] params){
PreparedStatement preparedStatement = null;
int num = 0;
try {
connection = getConnection();
preparedStatement = connection.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
preparedStatement.setObject(i+1,params[i]);
}
num = preparedStatement.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
closeAll(connection, preparedStatement, null);
}
return num;
}
}
3.6、操作数据库增删改查
package com.itbbj.bbs.dao.impl;
import com.itbbj.bbs.dao.UserDao;
import com.itbbj.bbs.domain.User;
import com.itbbj.bbs.util.DbUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class UserDaoImpl implements UserDao {
private DbUtil dbUtil = new DbUtil();
@Override
public int insert(User user) {
String sql = "INSERT INTO USER(userName,PASSWORD,email) VALUES (?,?,?)";
Object[] params = {user.getUserName(),user.getPassword(),user.getEmail()};
int num = dbUtil.executeUpdate(sql, params);
return num;
}
@Override
public int update(User user) {
String sql = "UPDATE USER SET userName = ?,PASSWORD = ?,email = ? WHERE id = ?";
Object[] params = {user.getUserName(),user.getPassword(),user.getEmail(),user.getId()};
int num = dbUtil.executeUpdate(sql, params);
return num;
}
@Override
public int delete(int id) {
String sql = "DELETE FROM USER WHERE id = ?";
Object[] params = {id};
int num = dbUtil.executeUpdate(sql, params);
return num;
}
@Override
public List<User> getUserList() {
Connection connection = dbUtil.getConnection();
PreparedStatement preparedStatement = null;
ResultSet rs = null;
List<User> userList = null;
try {
String sql = "select * from user";
preparedStatement = connection.prepareStatement(sql);
rs = preparedStatement.executeQuery();
userList = null;
userList = new ArrayList<>();
User user = null;
while (rs.next())
{
int id = rs.getInt(1);
String userName = rs.getString("userName");
String password = rs.getString("password");
String email = rs.getString("email");
user = new User(id, userName, password,email);
userList.add(user);
}
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
dbUtil.closeAll(connection,preparedStatement,rs);
}
return userList;
}
4、HTML
4.1、什么是HTTP
HTTP(超文本传输协议)是一个基于请求与响应,无状态的,应用层的协议,常基于TCP/IP协议传输数据,互联网上应用最为广泛的一种网络协议,所有的WWW文件都必须遵守这个标准。设计HTTP的初衷是为了提供一种发布和接收HTML页面的方法。
HTTPS是一种通过计算机网络进行安全通信的传输协议,经由HTTP进行通信,利用SSL/TLS建立全信道,加密数据包。HTTPS使用的主要目的是提供对网站服务器的身份认证,同时保护交换数据的隐私与完整性。
4.2、Http请求
客户端——>发请求——>服务器
一个HTTP请求报文由3个部分组成:
- 请求行(request line)
- 请求头部(headers)
- 请求体(request body)
1.请求行
以访问百度为例:
Request URL:请求地址
Request Method:请求方式,一般是GET/POST
Status Code:状态码:200表示成功,404表示没有找到资源,500表示服务器错误....
Remote Address:远程地址
- 请求行中的请求方式:GET
- 请求方式:GET,POST,HEAD,DELETE,PUT,TRACT…
GET:请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但是高效
POST:请求能够携带的参数没有限制,大小没有限制,不会在浏览器的URL地址栏显示数据内容,安全,但是不高效
2、请求头部
Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码格式 GBK UTF-8 GB2312 ISO8859-1
Accept-Language:告诉浏览器,它的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
HOST:主机
…
3、请求体
请求体是将一个页面表单中的组件值通过param1=value1¶m2=value2的键值对形式编码成一个格式化串,它承载多个请求参数的数据。不但报文体可以传递请求参数,请求URL也可以通过类似于“/chapter15/user.html? param1=value1¶m2=value2”的方式传递请求参数。
4.3、HTML基础语法
4.4、CSS样式
4.5、javaScript
5、Servlet
5.1、什么是Servlet
- Servlet是sun公司开发动态web的一门技术
- Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。
下图显示了 Servlet 在 Web 应用程序中的位置。
5.2、Servlet作用
- 接收用户端发来的请求
- 调用其他java程序来处理请求
- 将处理结果,返回到服务器中
5.3、servlet的使用
1)、web.xml注册
我们写的是Java程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务中注册我们写的Servlet,还需给他一个浏览器能够访问的路径。
<!-- 注册servlet-->
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.itdj.news.servlet.LoginServlet</servlet-class>
</servlet>
<!-- servlet的请求路径-->
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
2)、注解
Servlet3.0提供了注解(annotation),我们可以不用再web.xml里面配置servlet,只需要加上@WebServlet注解就可以修改该servlet的属性了。web.xml可以配置的servlet属性,在@WebServlet中都可以配置。
@WebServlet 注解的属性,如下
使用 @WebServlet 注解
@WebServlet(urlPatterns = “/MyServlet”)。
@WebServlet(“/MyServlet”) 省略了 urlPatterns 属性名
3)、@WebServlet 注解 和 web.xml 的区别
使用 web.xml 或 @WebServlet 注解都可以配置 Servlet
@WebServlet 注解配置 Servlet
优点:@WebServlet 直接在 Servlet 类中使用,代码量少,配置简单。每个类只关注自身业务逻辑,与其他 Servlet 类互不干扰,适合多人同时开发。
缺点:Servlet 较多时,每个 Servlet 的配置分布在各自的类中,不便于查找和修改。
web.xml 配置文件配置 Servlet
优点:集中管理 Servlet 的配置,便于查找和修改。
缺点:代码较繁琐,可读性不强,不易于理解。
4)、servlet实例
Servlet 是服务 HTTP 请求并实现 javax.servlet.Servlet 接口的 Java 类。Web 应用程序开发人员通常编写 Servlet 来扩展 javax.servlet.http.HttpServlet,并实现 Servlet 接口的抽象类专门用来处理 HTTP 请求。
// 导入必需的 java 库
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
@WebServlet( value = "/helloWorld")
// 扩展 HttpServlet 类
public class HelloWorld extends HttpServlet {
private String message;
public void init() throws ServletException
{
// 执行必需的初始化
message = "Hello World";
}
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
// 设置响应内容类型
response.setContentType("text/html");
// 实际的逻辑是在这里
PrintWriter out = response.getWriter();
out.println("<h1>" + message + "</h1>");
}
public void destroy()
{
// 什么也不做
}
}
*servlet生命周期
原文链接
Servlet 生命周期
Servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 Servlet 遵循的过程:
- Servlet 初始化后调用 init () 方法。
- Servlet 调用 service() 方法来处理客户端的请求。
- Servlet 销毁前调用 destroy() 方法。
- 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。
service() 方法
service() 方法是执行实际任务的主要方法。Servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。
每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut,doDelete 等方法。
下面是该方法的特征:
public void service(ServletRequest request,
ServletResponse response)
throws ServletException, IOException{
}
service() 方法由容器调用,service 方法在适当的时候调用 doGet、doPost、doPut、doDelete 等方法。所以,您不用对 service() 方法做任何动作,您只需要根据来自客户端的请求类型来重写 doGet() 或 doPost() 即可。
doGet() 和 doPost() 方法是每次服务请求中最常用的方法。下面是这两种方法的特征。
doGet() 方法
GET 请求来自于一个 URL 的正常请求,或者来自于一个未指定 METHOD 的 HTML 表单,它由 doGet() 方法处理。
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// Servlet 代码
}
doPost() 方法
POST 请求来自于一个特别指定了 METHOD 为 POST 的 HTML 表单,它由 doPost() 方法处理。
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// Servlet 代码
}
*认识HttpServletRequest
HttpServletRequest的核心方法
**认识部分方法
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
/**
* Created with IntelliJ IDEA.
* Description:
* User: WHY
* Date: 2023-06-09
* Time: 16:57
*/
@WebServlet("/showRequest")
public class ShowRequest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
StringBuilder result=new StringBuilder();
result.append(req.getProtocol());
result.append("<br>");
result.append(req.getMethod());
result.append("<br>");
result.append(req.getRequestURI());
result.append("<br>");
result.append(req.getQueryString());
result.append("<br>");
result.append(req.getContextPath());
result.append("<br>");
result.append("=============================");
/* Enumeration<String> headerNames=req.getHeaderNames();
while(headerNames.hasMoreElements()){
String headerName=headerNames.nextElement();
String headerValue=req.getHeader(headerName);
result.append(headerName+":"+headerValue+"<br>");
}*/
//设置响应格式便于让浏览器解析
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write(result.toString());//转换成字符串的形式
}
}
运行截图
**使用 Servlet 读取表单数据
原文链接
Servlet 处理表单数据,这些数据会根据不同的情况使用不同的方法自动解析:
- getParameter():您可以调用 request.getParameter() 方法来获取表单参数的值。
- getParameterValues():如果参数出现一次以上,则调用该方法,并返回多个值,例如复选框。
- getParameterNames():如果您想要得到当前请求中的所有参数的完整列表,则调用该方法。
简单实例(getParameter)
login.jsp
由表单的method可以看出这是post请求
<form method="post" action="<%= request.getContextPath()%>/Login">
<table border="0" align="center">
<tr>
<td>用户名: </td>
<td><input type="text" name="userName"></td>
</tr>
<tr>
<td>密码: </td>
<td><input type="text" name="pwd"></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="POST请求">
</tr>
</table>
</form>
LoginServlet
package com.itdj.news.servlet;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet( value = "/Login")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Demo1Servlet::Post请求");
request.setCharacterEncoding("UTF-8");
String userName = request.getParameter("userName");//获取页面userName的值
String pwd = request.getParameter("pwd");//获取页面pwd的值
if("sa".equals(userName) && "sa".equals(pwd)){ //判断是否等于字符串"sa"
Cookie cookieUserName = new Cookie("userName", "sa");
cookieUserName.setMaxAge(6);
response.addCookie(cookieUserName);
response.sendRedirect("d1/welcome.jsp");
}else{
response.sendRedirect("d1/login.jsp");
}
}
}
*认识HttpServletResponse
核心方法
**认识部分方法
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Created with IntelliJ IDEA.
* Description:
* User: WHY
* Date: 2023-06-09
* Time: 20:46
*/
@WebServlet("/status")
public class StatusServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setStatus(200);//为响应设置状态
resp.setContentType("text/html charset=utf8");//设置发送到客户端的响应的内容类型
resp.getWriter().write("返回200响应");//往body写入文本格式数据
resp.setHeader("Refresh","1");//设置每秒刷新一次
resp.getWriter().write("time="+System.currentTimeMillis());//往body写入文本格式数据
resp.sendRedirect("https://www.bidu.com");//重定向
}
}
*请求转发和重定向(Web开发中用来处理页面跳转的方式)
原文链接
转发(Forward)内部流程
第一个ServletA接收到了浏览器端的请求,进行了一定的处理,然后没有立即对请求进行响应,而是将请求“交给下一个ServletB”继续处理,下一个ServletB处理完成之后对浏览器进行了响应。在服务器内部将请求“交给”其它组件继续处理就是请求的转发。
protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletExceptio ,IOException {
//1.使用RequestDispatcher对象封装目标资源的虚拟路径
RequestDispatcher dispatcher = request.getRequestDispatcher("/index.html");
//2.调用RequestDispatcher对象的forward()方法“前往”目标资源
//[注意:传入的参数必须是传递给当前Servlet的service方法的
//那两个ServletRequest和ServletResponse对象]
dispatcher.forward(request,response);}
重定向(Redirect)内部执行流程
第一个ServletA接收到了浏览器端的请求,进行了一定的处理,然后给浏览器一个特殊的响应消息,这个特殊的响应消息会通知浏览器去发送一个请求request2,去访问另外一个资源ServletB,这个动作是服务器和浏览器自动完成的,最终由ServletB做出响应。
response.sendRedirect(“success.html”);
*HTTP状态码
HTTP状态码可以分为五大类,它们分别是:
一、100-199,信息状态码。
此类状态码一般不会直接展示给用户(对用户透明)。
目前已定义的成功状态码有100、101。
二、200-299,成功状态码。
此类状态码一般不会直接展示给用户。如果我们在访问网站时收到成功状态码,则将看到网站的具体内容。
目前已定义的成功状态码有200、201、202、203、204、205、206。
三、300-399,重定向状态码。
此类状态码一般不会直接展示给用户,但用户可能看到网址自动发生改变。
目前已定义的重定向状态码有300、301、302、303、304、305、306、307。
四、400-499,客户端错误状态码。
此类状态码一般直接或者以友好的方式展示给用户,出现该状态码则意味着用户的操作存在错误。
目前已定义的客户端错误状态码有400、401、403、404、405、406、407、408、409、410、411、412、413、414、415、416、417。
五、500-599,服务器错误状态码。
此类状态码一般直接或者以友好的方式展示给用户,出现该状态码则意味着服务器发生错误。
目前已定义的服务器错误状态码有500、501、502、503、504、505。
其中,状态码404尤为常见,值得我们重点了解。
状态码404,一般显示为404 Not Found,表示无法在服务器上找到相应的资源。此状态码出现的原因主要有用户输入了错误的网址、服务器管理员移动或者删除了相关的资源。目前,很多网站对该状态码的显示网页进行了特殊设计,使得用户获得了更好的体验。
示例:
// 导入必需的 java 库
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
import javax.servlet.annotation.WebServlet;
@WebServlet("/showError")
// 扩展 HttpServlet 类
public class showError extends HttpServlet {
// 处理 GET 方法请求的方法
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
// 设置错误代码和原因
response.sendError(407, "Need authentication!!!" );
}
// 处理 POST 方法请求的方法
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
*Cookie & Session
**关于 Http 无状态的理解
什么 Http 无状态:
- 服务器不会保留客户端交易的任何状态和数据,一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接,这就意味着服务器无法从连接上跟踪会话。也就是指用户每次发起的请求之间是没有相关性的,每次的请求结束就结束了,不会在做任何数据的存储。
Http 请求的无状态带来的问题和影响:
- 比如用户登录以后切换到别的界面进行操作,服务器端根本无法判别是哪个用户登录的,每次进行页面跳转的时候都要重新登录。
如何解决 Http 请求的无状态的问题:
- 1:Session(服务器端)
- 2:Cookie(客户端)
**Cookie & Session的工作原理
- Session 原理: 其实是一种服务端的数据存储技术,存储在 StandardSession 类的 ConcurrentHashMap 集合中。为了维护每个请求的数据关系,会生成一个 jsessionid 并通过 Cookie写入客户端。后面在浏览器的每个请求的过程中都会比较请求的域和 Cookie 的域是否相同,如果相同,浏览器会把所有 Cookie 中存放的key 一起打包,放入到请求头中,发送给服务器。然后服务器会根据 request 对象解析请求头中 Cookie,如果该数据信息 jsessionid 和请求头中 Cookie 里 jsessionid 名字且值都相同,就直接返回一个 Session对象,如果找不到,说明会话已经失效。
- Cookie 原理: 其实是一种客户端的数据存储技术,它会把数据写入到浏览器中,不会占用服务器的内存,所以在很多时候,如果仅仅只是临时的保存一些数据信息,但是又不想存储数据库表,那么可以考虑使用Cookie 技术。其实 JavaScript 也可以操作 Cookie。比如用户登录记录登录状态,就可以考虑使用Cookie。比如视频网站播放的时候,记录当前播放进度或者音量等等,也可以考虑使用 Cookie。
- Session与Cookie的区别: Session存储数据在服务器端,Cookie在客户端;Session没有数据类型大小限制,Cookie有数据类型限制,仅限String类型,<=4KB;Session数据安全,Cookie相对于不安全。
详情见原文
6、JSTL标签
1、什么是JSTL
- JSP标准标识库,使用JSTL可实现JSP页面的逻辑处理; 可用于编写各种动态JSP页面
- JSTL(Java server pages standarded tag library,即JSP标准标签库)是由JCP(Java community Proces)所制定的标准规范,它主要提供给JavaWeb开发人员一个标准通用的标签库,并由Apache的Jakarta小组来维护。
- 开发人员可以利用JSTL标签取代JSP页面上的Java代码,从而提高程序的可读性,降低程序的维护难度。
2.JSTL环境搭建
导入jar包文件
jstl-x.x.jar
在jsp页面添加taglib指令
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
- 这里的uri 标识符指向jar包的tld文件,prefix为前缀,可以自定义,一般定义为c;也称为c标签
使用JSTL标签
- 刚才用c作为前缀的,那么直接写<c:标签 , 标签属性>内容</c:标签> 即可
3、条件标签 —if
if标签的几个属性:
- test:Boolean类型;决定是否处理标签体的内容,即条件判断
- var:String类型;指定变量名,保存test属性的判断结果
- scope:String类型;指定var值的作用域范围,默认为page,可选值:page,request,session,application
代码示例:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--使用tablib指令指向jstl标签库,定义前缀名prefix--%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--
在test中可写入条件判断(仅有test支持使用el标签),
var定义属性名,scope声明作用范围(默认为page,即PageContext域对象);
将该标签的test返回结果自动赋值给var,再由scope决定哪个域对象可以调用;--%>
<c:if test="${10<20}" var="qwe" scope="application">
test判断为true:内容可显示!<br/>
</c:if>
scope指定了作用域,其他域对象获取不到==>
${pageScope.qwe}<br/>
上面指定的是application应用程序域对象==>
${qwe}
</body>
</html>
运行结果
4、迭代标签 —forEach
orEach对Java中的集合与数组进行遍历
forEach标签的几个属性:
- (1)items : 获取需要迭代的集合或数组,支持EL表达式;类型为数组,字符串,集合;
- (2)var : 定义一个变量,接收循环中获取的数据;不支持EL表达式,类型为String;
- (3)varStatus : 获取循环的状态信息,不支持 EL表达式,类型为String;varStatus调用的几个参数:常用index,count
- (4)step : 设置迭代的步长,默认为1; 支持EL表达式,类型为int;
- (5)end : 设置迭代的结束索引 ,支持EL表达式,类型为int;若指定end属性,则在items的下标到指定end的位置就会结束迭代,若不指定,就全部迭代
- (6)begin : 设置迭代的开始索引,支持EL表达式,类型为int;若指定begin属性,则从items的下标为begin的位置开始迭代,若不指定,则全部迭代
示例代码:
<%
ArrayList<String> people = new ArrayList<>();
people.add(0, "张三");
people.add(1, "李四");
people.add(2, "王五");
people.add(3, "赵六");
people.add(4, "丁一");
people.add(5, "胡二");
request.setAttribute("list", people);
%>
<%--
var,每一次遍历出来的变量
items,要遍历的对象
begin, 开始位置
end, 结束位置
step, 步长
--%>
<c:forEach var="people" items="${list}">
<c:out value="${people}"/>
<br>
</c:forEach>
<hr>
<c:forEach var="people" items="${list}" begin="1" end="3" step="2">
<c:out value="${people}"/>
<br>
</c:forEach>
7、EL表达式
1、EL表达式简介
- EL表达式全称:Expression Language,即表达式语言
- EL表达式作用:代替JSP页面中表达式脚本进行数据的输出
- EL表达式比JSP的表达式脚本简洁很多
- EL表达式的格式是:${表达式} ,注:EL表达式写在jsp页面中,表达式一般是域对象的key
2、EL表达式搜索域数据的顺序
- EL表达式主要是输出域对象中的数据,当四个域对象都有同一个key的值时,EL表达式会按照四个域对象的范围从小到大进行搜索,找到就输出,与四个域对象声明的先后顺序无关
<body>
<%
//向四个域对象中都保存相同key的值
request.setAttribute("key", "request");
session.setAttribute("key", "session");
application.setAttribute("key", "application");
pageContext.setAttribute("key", "pageContext");
%>
<%-- 使用EL表达式输出key的值 --%>
${key}
</body>
启动服务器,页面显示:
pageContext
3、EL表达式输出Java类的属性
session域内设置msgList
<%--EL表达式根据key值msgList获取数据,然后进行遍历--%>
<c:forEach items="${msgList}" var="msg">
<c:if test="${msg.state == 0}">
<li class="unReaded">
</c:if>
<c:if test="${msg.state == 1}">
<li >
</c:if>
<em>${msg.createDate}</em>
<em><a href="${pageContext.request.contextPath}/msg/returnMsg?id=${msg.id}">回信</a></em>
<em><a href="">删除</a></em>
<em>发送方:${msg.sender}</em>
<p>
<strong><a href="${pageContext.request.contextPath}/msg/readMsg?id=${msg.id}">${msg.title}</a></strong>
</p>
</li>
</c:forEach>
4、pageContext对象的使用
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%-- 先通过pageContext对象获取request、session对象,再获取以下内容 --%>
<%--
获取请求的协议:request.getScheme()
获取请求的服务器ip或域名:request.getServerName()
获取请求的服务器端口号:request.getServerPort()
获取当前工程路径:request.getContextPath()
获取请求的方式:request.getMethod()
获取客户端的ip地址:request.getRemoteHost()
获取会话的唯一标识:session.getId()
--%>
1.协议: ${ pageContext.request.scheme }<br>
2.服务器ip:${ pageContext.request.serverName }<br>
3.服务器端口:${ pageContext.request.serverPort }<br>
4.获取工程路径:${ pageContext.request.contextPath }<br>
5.获取请求方法:${ pageContext.request.method }<br>
6.获取客户端ip地址:${ pageContext.request.remoteHost }<br>
7.获取会话的id编号:${ pageContext.session.id}<br>
</body>
</html>
运行结果:
5、param、paramValues对象的使用
<body>
获取请求参数username的值:${ param.username } <br>
获取请求参数password的值:${ param.password } <br>
获取请求参数中第一个hobby的值:${ paramValues.hobby[0] } <br>
获取请求参数中第二个hobby的值:${ paramValues.hobby[1] } <br>
<%-- 有多个同名的key时使用paramValues的索引值决定获取哪一个,使用param只可获取第一个 --%>
使用param获取hobby的值:${ param.hobby } <br>
</body>
运行结果:
浏览器地址栏输入:http://localhost:8080/MyTest/Test.jsp?username=Jaychou&password=123&hobby=sing&hobby=dance
6、initParam对象的使用
在web.xml中写参数 (修改了web.xml中内容之后,需要重启服务才可生效):
<context-param>
<param-name>username</param-name>
<param-value>root</param-value>
</context-param>
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql:///test</param-value>
</context-param>
test.jsp
<body>
输出<Context-param>username的值:${ initParam.username } <br>
输出<Context-param>url的值:${ initParam.url } <br>
</body>