JavaWeb

引言

相信小伙伴们大学实训的时候,会有过javaweb实训吧,反正我们那是,在没学习各大框架之前,我们都是学习javaweb的原生操作,相信原生基础好了,后面框架无非是提供便利,所以这里对javaweb的知识做一个个人小总结,这里就开始分段去更新了,希望小伙伴可以跟上,只要跟上了,那就可以说可以了,趋于保姆级教程了,所以希望对你有帮助,那看到这里先给博主点个赞吧,看完你再决定关不关注下博主;

目录结构:

介绍

来自百度百科:

javaweb就是写服务端小程序嘛,我们知道前台没办法写java,那么很多逻辑处理就没办法,就需要与后端交互,交互的同时我们还要保存数据,好像一个桥梁,只是在其中做了逻辑处理,然后拿到数据库数据与前台人员进行交互,那这其实也是mvc的概念,M(model模型,数据层) 、V(view视图,交互层)、C(controller控制,逻辑处理层),后面我们再理解下这个概念;

环境准备

Tomcat

下载安装

官网:https://tomcat.apache.org/,apache下开源产品;这里我们使用tomcat9

解压安装即可;

认识tomcat

我这里已经解压了,一个是源码文件,一个是运行文件,这里就不看源码了

认识一下tomcat结构

修改端口:进入conf目录,里面server.xml,默认8080,我这里修改成了8081

启动

进入tomcat的bin目录,输入startup.bat,即可启动tomcat

这时候我们浏览器访问:http://localhost:8081/,ok访问成功

Eclipse

下载安装

官网:http://www.eclipse.org/downloads/

不过多细说了,安装很简单,同样解压即可使用,如果还是不会的可以去搜一下图文教程,这里我们主要使用;

还有jdk,如果没有装jdk,那也赶紧先下载一个jdk安装上;

环境准备

Eclipse配置tomcat

导航栏windows——》 preferences :

选择自己的tomcat版本:

Finish完成添加:

找到控制台server

如果没有server,这样找到server

选择other,server –> ok即可:

双击server,设置完一定要ctrl+s保存下:

**eclipse启动tomcat:**右键运行start

配置完成

这时候我们浏览器访问:http://localhost:8081/,ok访问成功

新建web项目

安装好eclipes,后双击打开,

设置下编码为utf-8:

右键新建一个web项目,这里没有我们选择other

接下来两次next

到这里一个项目就新建好了,检查下,是否使用的是你自己的jdk和tomcat,这样我们就新建好一个web项目了

HelloWorld

这里我们新建一个jsp页面,里面输入HelloWorld

点到项目,右键运行:

测试成功,这样我们就可以在目录下编写代码了:

mysql

官网:https://www.mysql.com/

不过多介绍了,看下百度百科的介绍吧:

下载安装

我们使用mysql8

选择安装包:

这里就不带着大家安装了,网上教程很多,安装一个软件嘛,不过这里还是看着别人的图文教程一步步走比较好,现在马上去搜索一个安装教程,安装完后马上回来哦!

再说一下,万事开头配置难,配好一个环境对开发很重要,并且在配置环境的时候可能会出各种错,如果解决不了,大家换mysql版本,多重装几次,一定可以的

navicat

navicat是用来管理数据的一个可视化工具:我们不想用命令行一直在操作mysql,所以我们使用一个可视化工具更方便管理数据库;

当然这个软件是收费的,我们可以破解一下,这里大家也可以使用别的可视化工具,sqlyog都可以;

这里还是不带着大家安装了,教程很多,很简单大家快去安装上,这里给大家方便,随便找了一个教程,还是那句话,都不难很简单,快去安装完回来:http://t.zoukankan.com/yudx-p-13522514.html

JDBC

你回来了,那么我们就正式进入JDBC的学习了,什么是JDBC,来自百度百科:

其实就是java操作数据库的规范,我们知道关系型数据库有很,比如sqlserver 、mysql等等,但是不同的数据库我们不能去学很多种操作吧,这个时候为方便就可以规定了jdbc协议,我们使用不同的数据库,只需要切换数据源就可以,操作规范都是一样的,当然就省事了;

那对于Jdbc我们学习这么几个,连接数据库,操作数据库,断开数据库,直接上代码,连接数据库:

环境准备

在使用jdbc之前我们首先引入mysql驱动依赖:

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.28</version>
</dependency>

数据库表,我这里创建了一张货物表(Good):

/*
Navicat MySQL Data TransferSource Server         : 本机
Source Server Version : 80011
Source Host           : localhost:3306
Source Database       : huanyingTarget Server Type    : MYSQL
Target Server Version : 80011
File Encoding         : 65001Date: 2022-04-20 17:36:09
*/SET FOREIGN_KEY_CHECKS=0;-- ----------------------------
-- Table structure for good
-- ----------------------------
DROP TABLE IF EXISTS `good`;
CREATE TABLE `good` (`goodid` int(20) NOT NULL,`goodname` varchar(20) NOT NULL,`surplus` int(20) NOT NULL,`goodprice` int(20) NOT NULL,PRIMARY KEY (`goodid`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8;-- ----------------------------
-- Records of good
-- ----------------------------
INSERT INTO `good` VALUES ('1', '黑色森林', '2', '15');
INSERT INTO `good` VALUES ('2', '奶油蛋糕', '3', '13');
INSERT INTO `good` VALUES ('3', '水果蛋糕', '2', '11');
INSERT INTO `good` VALUES ('4', '冰淇凌蛋糕', '5', '13');
INSERT INTO `good` VALUES ('9', '牛奶蛋糕', '34', '9');
INSERT INTO `good` VALUES ('11', '肉松蛋糕', '13', '13');

查询操作

package dao;import java.sql.*;public class TesterDao {public static void main(String[] args) {// 四大属性String DRIVER = "com.mysql.jdbc.Driver";String URL = "jdbc:mysql://localhost:3306/huanying?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=utf-8";String NAME = "root";String PASSWORD = "root";// 三大对象Connection con = null; // 连接对象PreparedStatement ps = null; // sql语句编译对象ResultSet rs = null; // 返回结果集,查询对象// 连接mysqltry {Class.forName(DRIVER);con = DriverManager.getConnection(URL, NAME, PASSWORD);} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();}// 编译sqly语句,String sql = "select * from good";try {//con.createStatement()  这个不安全,不使用// 从数据库连接中获取sql语句ps = con.prepareStatement(sql);// 执行sql,并返回结果集,查询使用executeQuery,增删改使用executeUpdaters = ps.executeQuery();// 便利取出结果集内容while (rs.next()) {System.out.println(rs.getInt(1)); // 从第一列返回System.out.println(rs.getString(2)); // 从第二列返回System.out.println(rs.getInt(3)); // 从第三列返回System.out.println(rs.getInt(4)); // 从第四列返回}} catch (Exception e) {e.printStackTrace();}// 最后关闭连接,从123=》321这个顺序关闭try {if (rs != null) {rs.close();}if (ps != null) {ps.close();}if (con != null) {con.close();}} catch (Exception e) {}}
}

结果

增删改操作

修改我们只需要改变一个地方就可以,1、连接数据库,2、执行sql,返回结果,3、关闭连接,这里我们主要做第三步

package dao;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class Test02Dao {public static void main(String[] args) {// 四大属性String DRIVER = "com.mysql.jdbc.Driver";String URL = "jdbc:mysql://localhost:3306/huanying?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=utf-8";String NAME = "root";String PASSWORD = "root";// 三大对象Connection con = null; // 连接对象PreparedStatement ps = null; // sql语句编译对象ResultSet rs = null; // 返回结果集,查询对象// 连接mysqltry {Class.forName(DRIVER);con = DriverManager.getConnection(URL, NAME, PASSWORD);} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();}// 编译sql语句,添加一条数据String sql = "insert into good values(12,'草莓蛋糕',22,23)";try {// 从数据库连接中获取sql语句ps = con.prepareStatement(sql);// 执行sql,并返回结果集,查询使用executeQuery,增删改使用executeUpdate//增删改只返回影响数据库行数,int类型//删改都一样,尝试下int result = ps.executeUpdate();if (result==1) {System.out.println("添加数据成功");}} catch (Exception e) {e.printStackTrace();}// 最后关闭连接,从123=》321这个顺序关闭try {if (rs != null) {rs.close();}if (ps != null) {ps.close();}if (con != null) {con.close();}} catch (Exception e) {}}
}

运行结果

sql预编译

那我们知道,这样写的sql语句是死的,但是如果靠字符串拼接,那就很不安全,这里我们可以实现sql预编译,通过?去充当占位符那样,这里我们使用修改尝试下

package dao;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class Testr03Dao {public static void main(String[] args) {// 四大属性String DRIVER = "com.mysql.jdbc.Driver";String URL = "jdbc:mysql://localhost:3306/huanying?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=utf-8";String NAME = "root";String PASSWORD = "root";// 三大对象Connection con = null; // 连接对象PreparedStatement ps = null; // sql语句编译对象ResultSet rs = null; // 返回结果集,查询对象// 连接mysqltry {Class.forName(DRIVER);con = DriverManager.getConnection(URL, NAME, PASSWORD);} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();}// 编译sql语句,添加一条数据String sql = "update good set surplus=? where goodid=?";//两个从前台获取的值int surplus=99;int goodid=12;try {// 从数据库连接中获取sql语句ps = con.prepareStatement(sql);//补充完sql ps.setObject(1, surplus);   //点一下,有很多set类型的方法object更好用,两个参数:从左开始第几个?,填充什么值ps.setObject(2, goodid);// 执行sql,并返回结果集,查询使用executeQuery,增删改使用executeUpdate//增删改只返回影响数据库行数,int类型int result = ps.executeUpdate();if (result==1) {System.out.println("修改数据成功");}} catch (Exception e) {e.printStackTrace();}// 最后关闭连接,从123=》321这个顺序关闭try {if (rs != null) {rs.close();}if (ps != null) {ps.close();}if (con != null) {con.close();}} catch (Exception e) {}}
}

运行结果

DBCP

介绍

来自百度百科:

dbcp大家不要多想就是一个池化概念,什么操作都没有,就是在jdbc的基础上多了些配置;

池化技术,百度百科介绍的很清楚,这里我在给大家比喻一下,好比你从一个房间进出,你需要不停的开关门,进出很多次是不是很烦,麻烦对不对,这个时候如果我们一直把门打开这,这样进出不就很方便,门卫,对吧,他会自己去管理这门什么时候关什么时候一直开着,所以就很方便,不理解没关系,不妨碍我们使用;

环境改变

想要使用dbcp需要导入dbcp的三个jar包:

commons-pool2-2.4.2.jar,commons-logging-1.2.jar,commons-dbcp2-2.1.1.jar

maven依赖:

<dependency><groupId>org.apache.commons</groupId><artifactId>commons-dbcp2</artifactId><version>${dbcp.version}</version>
</dependency>

创建一个配置文件,db.properties文件用来放置配置文件,这个是在网上找的比较全点

#全部的参数参考,org.apache.commons.dbcp2.BasicDataSourceFactory里的ALL_PROPERTIES
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/huanying?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=utf-8
username=root
password=#<!-- 初始化连接 -->
initialSize=10
#最大连接数量
maxActive=50
#<!-- 最大空闲连接 -->
maxIdle=20
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;]
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=gbk;serverTimezone=UTC
#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true
#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED

创建DBCPUtil工具类:

package dao;import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;import javax.sql.DataSource;import org.apache.commons.dbcp.BasicDataSourceFactory;// 封装Dbcp连接池的工具类
// 该类中提供了获取连接和关闭连接的通用方法
public class DbcpUtil {// 使用ThreadLocal来解决线程同步问题.让每个线程都使用各自的连接对象// ThreadLocal<Connection> 可以被其中的Connection做成多份拷贝,让不同的线程对象使用private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();private static DataSource ds;// 静态代码块会在程序执行之前,被自动的执行static {InputStream in = DbcpUtil.class.getResourceAsStream("db.properties");Properties pro = new Properties();try {pro.load(in);ds = BasicDataSourceFactory.createDataSource(pro);} catch (IOException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}}// 获取连接的时候,把方法中遇到的异常通过throws抛出去,抛给调用者// 通过异常在方法和方法之间传递信息public static Connection getConnectio() throws SQLException {Connection conn = threadLocal.get();// 如果conn等于null 或者conn已经关闭if (conn == null || conn.isClosed()) {conn = ds.getConnection();threadLocal.set(conn);}return conn;}public static void closeConnection() {Connection conn = threadLocal.get();try {// 如果conn不等于null 并且没有关闭if (conn != null && !conn.isClosed()) {conn.close();}} catch (SQLException e) {e.printStackTrace();} finally {threadLocal.set(null);}}}

查询数据库

package dao;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class DBCPTester01 {public static void main(String[] args) {// 三大对象Connection con = null; // 连接对象PreparedStatement ps = null; // sql语句编译对象ResultSet rs = null; // 返回结果集,查询对象try {// 1、获取连接对象,改变了con = DbcpUtil.getConnectio();// 2、执行sql语句// 编译sql语句,String sql = "select * from good";// 从数据库连接中获取sql语句ps = con.prepareStatement(sql);// 执行sql,并返回结果集,查询使用executeQuery,增删改使用executeUpdaters = ps.executeQuery();// 便利取出结果集内容while (rs.next()) {System.out.println(rs.getInt(1)); // 从第一列返回System.out.println(rs.getString(2)); // 从第二列返回System.out.println(rs.getInt(3)); // 从第三列返回System.out.println(rs.getInt(4)); // 从第四列返回}} catch (Exception e) {e.printStackTrace();}finally {//最后关闭连接,这里的关闭不是像jdbc直接关闭了连接,而是放回来连接池DbcpUtil.closeConnection();}}
}

运行结果

我们发现知识配置一下,知识获得连接和关闭连接的方式变了,其他都没变,很简单吧,主要就是理解其中的概念;

BaseDao

我们发现是不是操作数据库总共分三步:1、连接mysql 2、执行sql语句 3、关闭数据库,我们发现其实只有第二步是我们一直使用在改变的,第一步和第三步,完全没有必要每次写那么多代码,我们都是学过面向对象的人了,那我们就可以对这个进行下简单的封装;

对于增删改方法,我们发现PreparedStatement对象都是执行的executeUpdate方法,那就简单了,增删改我们封装到一个方法里:

public int executeUpdate(String sql, Object... param) {int result = 0;try {// 通过DBCP获取连接con = DbcpUtil.getConnectio();ps = con.prepareStatement(sql);for (int i = 0; i < param.length; i++) {ps.setObject(i, param[i]);}result = ps.executeUpdate();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {DbcpUtil.closeConnection();}return result;
}

但是对于查询方法的封装,对于每张表都不一样,通过sql查询的结果也都不一样,所以我们封装到sql执行把ResultSet结果集对象交出给自定义处理:

public ResultSet executeQuery(String sql, Object... param) {try {con = DbcpUtil.getConnectio();ps = con.prepareStatement(sql);if (param != null) {for (int i = 0; i < param.length; i++) {ps.setObject(i++, param[i]);}}rs = ps.executeQuery();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}return rs;}

为什么这里我没有关闭连接呢,你尝试下,是不是就报错了,因为数据都在ResultSet对象里,如果我们关闭连接就是ResultSet关闭,当然会报错,并且数据取不出来;

最后完整的BaseDao,我这里只是做了下简单的封装,并且可能也封装的不好,大家根据自己的业务,到时候会有更好的封装,方便使用:

package Dao;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class BaseDao {// 三大对象Connection con = null; // 连接对象PreparedStatement ps = null; // sql语句编译对象ResultSet rs = null; // 返回结果集,查询对象public int executeUpdate(String sql, Object... param) {int result = 0;try {// 通过DBCP获取连接con = DbcpUtil.getConnectio();ps = con.prepareStatement(sql);for (int i = 0; i < param.length; i++) {ps.setObject(i+1, param[i]);}result = ps.executeUpdate();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {DbcpUtil.closeConnection();}return result;}public ResultSet executeQuery(String sql, Object... param) {try {con = DbcpUtil.getConnectio();ps = con.prepareStatement(sql);if (param != null) {for (int i = 0; i < param.length; i++) {ps.setObject(i++, param[i]);}}rs = ps.executeQuery();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}return rs;}}

测试

package Dao;import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;public class Test01Dao extends BaseDao {// 修改一个good的名字public int updateTest(String sql, String goodName, int goodId) {return this.executeUpdate(sql, goodName, goodId);}// 查询allpublic void queryTest(String sql) {this.executeQuery(sql);try {while (rs.next()) {System.out.println(rs.getInt(1)); // 从第一列返回System.out.println(rs.getString(2)); // 从第二列返回System.out.println(rs.getInt(3)); // 从第三列返回System.out.println(rs.getInt(4)); // 从第四列返回}} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{DbcpUtil.closeConnection();}}public static void main(String[] args) {Test01Dao test01Dao = new Test01Dao();// test01Dao.queryTest("select * from good");int res = test01Dao.updateTest("update good set goodname=? where goodid=?", "hello", 17);if (res == 1) {System.out.println("修改成功");}}}

查询全部结果,测试成功:

执行修改,这里只是执行了修改,删除和增加还用演示吗,不用了吧:

结果,测试成功:

MVC

介绍

mvc同样也是一种概念,来自百度百科:

其实就是下面的逻辑图

在编码上我们将自己的代码也做成了这层;

Servlet

介绍,来自百度百科:

服务器程序,servlet只是一直接口,凡是继承了这个接口的都是servlet,但是我们一般只使用httpServlet进行http请求,所以现在一般说的servlet指的是继承了httpServlet的类,我们可以写程序通过servlet映射出去可以访问;

下面我们来了解下servlet;

生命周期

首先就是servlet生命周期:

三个生命周期,init()、service()、destroy();

init() 方法

init 方法被设计成只调用一次。它在第一次创建 Servlet 时被调用,在后续每次用户请求时不再调用。因此,它是用于一次性初始化,就像 Applet 的 init 方法一样。

service() 方法

service() 方法是执行实际任务的主要方法。Servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。

destroy() 方法

destroy() 方法只会被调用一次,在 Servlet 生命周期结束时被调用。destroy() 方法可以让您的 Servlet 关闭数据库连接、停止后台线程、把 Cookie 列表或点击计数器写入到磁盘,并执行其他类似的清理活动。

在调用 destroy() 方法之后,servlet 对象被标记为垃圾回收。destroy 方法定义如下所示:

  public void destroy() {// 终止化代码...}

那这里我们主要使用service(),但是我们不去实现这个方法,而是通过service() 方法由容器调用,service 方法在适当的时候调用 doGet、doPost、doPut、doDelete 等方法。所以,您不用对 service() 方法做任何动作,您只需要根据来自客户端的请求类型来重写 doGet() 或 doPost() 即可。

我们主要实现doGet和doPos方法体,接收用户请求;

快速上手

我们来快速新建一个servlet来看看,右键新建servlet:

那一个servlet我们就创建好了,这是代码自己生成的,我们来看下他给我们创建的都是什么代码以及怎么使用:

package servlet;import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** Servlet implementation class HelloServlet* 这里的注解,就是我们的请求路径*/
@WebServlet("/HelloServlet")
//继承HttpServlet ,而HttpServlet实现了servlet接口
public class HelloServlet extends HttpServlet {//序列化时为了保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性。private static final long serialVersionUID = 1L;/*** @see HttpServlet#HttpServlet()*/public HelloServlet() {//构造方法super();}/*** @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)* doGet方法体*/protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// TODO Auto-generated method stub//默认给请求的响应,这里我们注释了,写我们自己的响应//response.getWriter().append("Served at: ").append(request.getContextPath());response.getWriter().print("hello World");}/*** @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)* doPost方法体*/protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// TODO Auto-generated method stub//调用了doGet方法,这里我们可以这么使用,这样我们都使用doPostdoGet(request, response);}}

我们运行项目并访问HelloServlet请求,ok测试成功:

这是注解的方式配置请求路径,我们可以通过web.xml配置请求路径:

我们新建项目时的web.xml

打开,我们可以通过xml配置请求路径:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://xmlns.jcp.org/xml/ns/javaee"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"id="WebApp_ID" version="3.1"><display-name>xuexiriji</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的配置 --><servlet>   <!-- servlet的内部名称,自定义。尽量有意义 --><servlet-name>HelloServlet</servlet-name>   <!-- servlet的类全名: 包名+简单类名 --><servlet-class>servlet.HelloServlet</servlet-class></servlet>      <!-- servlet的映射配置 --><servlet-mapping>      <!-- servlet的内部名称,一定要和上面的内部名称保持一致!! --><servlet-name>HelloServlet</servlet-name>     <!-- servlet的映射路径(访问servlet的名称) --><url-pattern>/hello</url-pattern></servlet-mapping></web-app>

我们把WebServlet注解注释掉,再次运行,访问配置的hello路径,访问成功:

四大作用域

优先级从小到大

  • PageContext : 页面作用域范围有效,jsp页面内置对象
  • Requset : 一次请求作用域范围有效
  • Session :一次会话作用域范围有效
  • ServletContext :一次服务作用域,web应用加载起来,就一直在,管理多个servlet

下面总结使用方法:

其实四大作用域不管哪个对象最常用的,90%都是这三个getAttribute()、setAttribute()、removeAttribute()

PageContext

pageContext对象是javax.servlet.jsp.PageContext类的实例对象,用来代表整个JSP页面。它代表页面上下文,该对象主要用于访问 JSP 之间的共享数据,使用pageContext可以访问page、request、session、application范围的变量。

方 法 说 明
forward(java.lang.String.relativeUtlpath) 把页面转发到另一个页面
getAttribute(String name) 获取参数值
getAttributeNames(int scope) 获取某范围的参数名称的集合,返回值为java.util.Enumeration对象
getException() 返回exception对象
getRequest() 返回request对象
getResponse() 返回response对象
getSession() 返回session对象
getOut() 返回out对象
getApplication() 返回application对象
setAttribute() 为指定范围内的属性设置属性值
removeAttribute() 删除指定范围内的指定属性

在页面使用中我们很少使用,在jsp中我们再使用几次;

HttpRequest

//设置请求编码格式
requset.setCharaterEncoding("utf-8");//获取请求参数
requset.getParameter();//获取属性
request.getAttribute();//设置属性
request.setAttribute();//请求转发
request.getRequestDispatcher("/login.jsp").forward(request, response);

HttpRespones

//设置响应编码
response.setContentType( "text/ html; charset=utf-8");//设置响应状态重定向,一般不这么用
response.setStatus(response.SC_MOVED_TEMPORARILY);
response.setHeader("Location", site);    //我们通常使用这个进行重定向
response.sendRedirect()// 设置刷新自动加载的事件间隔为 5 秒
response.setIntHeader("Refresh", 5);//获得网页写对象
PrintWriter out = response.getWriter();
out.print()  //像屏幕输出数据,一般不这么用,我们后面直接用jsp

这里需要注意:

一般情况下的页面跳转就用sendRedirect , 用的不是同个request对象,而另一个则是

request.getRequestDispatcher()是请求转发,前后页面共享一个request ;
response.sendRedirect()是重新定向,前后页面不是一个request。request.getRequestDispather();返回的是一个RequestDispatcher对象。RequestDispatcher.forward()是在服务器端运行;
HttpServletResponse.sendRedirect()是通过向客户浏览器发送命令来完成.
所以RequestDispatcher.forward()对于浏览器来说是“透明的”;
而HttpServletResponse.sendRedirect()则不是。

ServletContext

servletContext,是Servlet中最大的一个接口,呈现了web应用的Servlet视图。

ServletContext实例是通过 getServletContext()方法获得的,由于HttpServlet继承GenericServlet的关系,GenericServlet类和HttpServlet类同时具有该方法。

没有太多东西,主要是还是这三个:getAttribute()、setAttribute()、removeAttribute()

Cookie

前言

因为cookie、session、token本身就是很容易混淆的东西,这里不放在一块了,所以我们先来理解下cookie是什么,怎么去简单的使用下, 看前点个赞,养成好习惯;

看完这一篇你还不会JavaWeb吗相关推荐

  1. Tkinter超市收银小程序(附源码),看完这一篇你还不会Tkinter吗,快来试试吧

    Tkinter超市收银小程序 引言 超市收银小程序,一个小例子快速上手Tkiner使用,虽然最近有好多实验报告要写,但是我还是给大家写一个小例子,之前就用C.C++,java.特别是C#最好用,做过图 ...

  2. 看了这一篇你还不理解什么是闭包——我直播吃翔!

    看了这一篇你还不理解什么是闭包--我直播吃翔! 一. 前言 许多刚刚接触JavaScript的小伙伴可能对闭包一脸懵逼,难于理解.对于那些有一点JavaScript使用经验但未真正理解闭包的人来说,理 ...

  3. 别在问PMP和ACP哪个更有用了,看完这一篇你就知道!

    别在问PMP和ACP哪个更有用了,看完这一篇你就知道. 老原很多粉丝和学员在我的后台问我: 要不要考PMP和ACP? PMP和ACP的区别是啥? PMP.ACP证书考哪个更有用?还是两个都考? PMP ...

  4. 分享一波关于做Kaggle比赛,Jdata,天池的经验,看完我这篇就够了。

    @Author : Jasperyang @School : BUPT 这篇文章同时在知乎里放着- 写在前面 Kaggle的数据挖掘比赛近年来很火,以至于中国兴起了很多很多类似的比赛,做了两个这种类型 ...

  5. 计算机进制转换(看完这一篇你就全懂了)—基础篇

    我相信很多人都学过进制的转换,但是总是转不过来,你只需要看完这一篇,你对进制的理解与转换一定会很熟练. 众所周知计算机只能识别0和1,其他的文字.数字.字符只能通过转换成进制,然后让计算机识别,并显示 ...

  6. 分享九种Python制作的圣诞树,看完长津湖你还想过圣诞吗?可是圣诞不是哪个国家的专属节日呀~

    导语:看完长津湖你还想过圣诞节? 近日,随着圣诞节的到来,长津湖圣诞节词条冲上热搜.网友们热议"长津之后再无圣诞""我们的平安是中国军人守护来的,而不是圣诞节" ...

  7. Android Studio Lint 工具看完这一篇还不够

    前言 以前对下面的问题,我的态度是,不报错就是没问题,报错就用快捷键,根据Android Studio提示修复问题,从来不去问个为什么?现在代码洁癖症越来越严重的我,忍不住想看清什么东西在搞鬼. 认真 ...

  8. 网络安全工程师入门教程(非常详细)从零基础入门到精通,看完这一篇就够了

    前言 想要成为网络安全工程师,却苦于没有方向,不知道从何学起的话,下面这篇 网络安全入门 教程可以帮你实现自己的网络安全工程师梦想,如果想学,可以继续看下去,文章有点长,希望你可以耐心看到最后! 1. ...

  9. 当下最火的中台到底是个什么鬼,看完这一篇最通俗易懂的文章后,你就会彻底明白了!...

    公众号关注 「奇妙的 Linux 世界」 设为「星标」,每天带你提升技术视野! 背景 自从阿里巴巴现任CEO逍遥子在2015年提出"大中台,小前台"战略以来,关于"什么是 ...

最新文章

  1. 让你的网站提速:图片优化网站推荐
  2. (转)android 在电脑上显示真机屏幕
  3. Linux下cron周期性计划任务
  4. 怎么做mysql查询系统_mysql数据库系统学习(一)---一条SQL查询语句是如何执行的?...
  5. Apache JMeter教程
  6. springboot整合minio最新版
  7. 如果孩子早恋是支持还是反对?
  8. 五子棋人机对战_10.带人机对战的五子棋程序
  9. Qt TextEdit 不自动换行 取消换行
  10. 单片机和嵌入式的区别
  11. 【java模板引擎】-beetl
  12. 安卓6.0获取相机权限
  13. 黄河金岸诗词赋联大赛获奖名单
  14. Http 请求头中 X-Requested-With 的含义
  15. [推荐]《人一生要读的60本书》
  16. 个人公众号,用于开发经验分享
  17. 关于PHP中如何跟踪报错的手段
  18. 如何理解同震、震后、震间的含义
  19. 【直达本质讲运放】运放的“第一原理”式定量分析法
  20. 网络编程经典好书推荐

热门文章

  1. 最小二乘法的最简单的几何解释,非常直观!
  2. html与CSS的学习笔记
  3. 1009: 求平均分 C语言
  4. 计算机系统软件最核心软件是,华为鸿蒙操作系统HarmonyOS全景研究与解构
  5. 闲鱼副业怎么玩?闲鱼赚钱的方法有几种?
  6. gps周 python_基于Python的UTC时间到GPS时间转换器
  7. Ubuntu 安装 anaconda
  8. 微信正测试新功能:同一个手机号可注册两个微信号
  9. js判断字符串真实长度并切分
  10. 获取当前PHP运行环境是否cli模式