一、基本概念
1.1、前言
web开发:
1. web,网络的意思
2. 静态web:eg:html、css 提供给所有人的页面都不会发生变化
3. 动态web:eg:几乎所有的网站
在java中,动态web资源开发的技术统称为javaweb
1.2、web应用程序
web应用程序:可以提供浏览器的访问的程序;
- a.html、b.html。。。。多个资源,这些web资源都可以被外界访问,对外界提供服务
- 我们能访问到的任何一个页面或者资源,都存在与这个世界的某一个角落的计算机上
- 这个统一的web资源服务器都被放在同一个文件夹下,web应用程序:eg:tomcat服务器
- 一个web服务器应该由多个部分组成(静态web,动态web)
-html,css,js
-jsp,servlet
-java程序
-jar 包
-配置文件(properties)
web写完之后,若是想让外界可以访问,需要将它发布在服务器上
1.3、静态web
- .htm,.html 这些都是网页的后缀,如果服务器上一直存在这些东西,我们可以直接进行读取。
- 静态web存在的缺点
1、web页面无法动态更新,所有的用户看到的都是同一个页面
①轮播图,点击特效:伪动态
②JavaScript [实际开发中使用最多]
③VBScript 类似js
2、他无法和数据库进行交互(数据无法持久化,用户无法交互)
1、4 动态web
页面会动态展示:web的页面的展示效果会因人而异
缺点:
加入服务器的动态web资源出现了问题,我们需要重新编写后台代码,重新发布
。停机维护
优点:
1、web页面可以动态更新,所有的用户看到的都不是同一个页面
2、他可以和数据库进行交互(数据持久化,用户交互)
二、web服务器
2.1技术讲解
ASP:
-
微软:国内最早流行的就是ASP
-
在HTML中嵌入了VB的脚本 ASP + COM
-
在ASP开发中,基本一个页面就是几千行代码,页面极其混乱(在HTML中也要写业务逻辑代码)
-
维护成本高
-
C#
PHP: -
PHP开发速度快,功能强大,跨平台,代码简单
-
无法承载大访问量的情况(局限性)
JSP/Servlet
B/S:浏览器和服务器
C/S:客户端和服务器
- sun公司主推的B/S架构
- 给予java语言的(所有大公司,或者一些开源的组件,都是由java写的)
- 可以承受三高问题(高并发、高可用、高性能)
- 语法像ASP,ASP---->JSP,加强市场强度
2.2、web服务器
服务器是一种被动操作,用来处理用户的一些请求和给用户的一些响应信息
IIS
微软的:ASP…,Windows自带的
TomCat:另一篇博文中有详细记载
三、Tomcat的配置
Tomcat官网:http://tomcat.apache.org/
可以启动配置的端口号
都是可以手动修改的
- tomcat的默认端口号为:8080
- mysql的默认端口号为:3306
- http的默认端口号:80
- https的默认的端口号:443
<Connector port="8081" protocol ="HTTP/1.1"
connectionTimeout = "20000"
redirectPort = "8443"/>
较难面试题:
请你谈谈网站是如何进行访问的?
- 输入一个域名:回车
- 检查本机的C:\Windows\System32\drivers\etc\hosts配置文件下是否有这个域名映射
①有:直接返回对应的IP地址
②没有:去DNS服务器上寻找,找到就返回,没有找到就返回没有找到
四、Http
4.1、什么是HTTP
http(超文本传输协议)是一个简单的请求-响应协议,它通常运行在tcp上
- 文本:HTML,字符串,~。。。
- 超文本:图片,音乐视频,定位,地图。。。。
4.2、两个时代
- http1.0
http/1.0:客户端可以与web服务器连接后,只能获得一个web资源,断开连接 - http2.0
http/1.1 客户端与web连接后,可以获得多个web资源
4.3、Http请求
4.4、Http响应
五、Servlet
5.1 servlet简介
- servlet就是sun公司开发动态web的一门技术
- sun公司在API中提供一个接口叫做:Servlet:你如果想要开发一个servlet小程序,需要有以下的两个步骤:
编写一个类实现了servlet接口
把开发好的java类部署到web服务器上
把实现了servlet的程序叫做 :servlet
5.2 HelloServlet
- 构建一个普通的maven项目,删除掉里面的src目录,在里面重新建立一个Moudel,这个空项目里面进行学习
- 关于maven父子工程的理解
父项目中会有
<modules>
<module>servlet-01-hello</module>
</modules>
子项目中会有
<parent>
<artifactId>javaweb-02-maven</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
- maven优化:将maven环境改为最新的
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">
- 编写hello的类,使之实现servlet类,继承Httpservlet类
public class hello extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("进入了doGet方法");
PrintWriter writer = resp.getWriter();
writer.write("hello servlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
- 编写servlet的类
为什么要映射?我们书写的是Java类,但是需要通过浏览器访问,浏览器需要访问服务器
所以我们需要给他分别注册一个服务器可以访问到的地址和浏览器可以访问到的URL地址
<!--服务器访问的注册的id-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.kuang.servlet.hello</servlet-class>
</servlet>
<!-- 浏览器访问的地址-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
- 配置tomcat
配置项目发布的路径 - 发布
5.3 servlet原理
5.4 Mapping问题
- 一个Mapping可以映射一个路径
<!--服务器访问的注册的id-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.kuang.servlet.hello</servlet-class>
</servlet>
<!-- 浏览器访问的地址-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
- 一个Mapping可以映射多个路径
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello1</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello2</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello3</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello4</url-pattern>
</servlet-mapping>
- 一个Mapping可以映射一个使用通配符的路径路径
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
当访问服务器的时候会默认进入使用了通配符的路径(不建议这样使用)
- Mapping中的优先级
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello1</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>*</url-pattern>
</servlet-mapping>
当这两种mapping同时存在的时候,无果输入hello1的路径的时候,会进入到hello所对应得界面中
5. Mapping中的前后缀
这样使用的时候,会将结尾为hsh的路径转入到hello中
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>*.hsh</url-pattern>
</servlet-mapping>
eg:
5.5 servletContext
web容器在启动的时候,会自动的创建一个servletContext的对象,类似于全局变量,它代表了当前的web容器
1. 共享数据,在一个servlet中的对象,可以在另一个servleth中获取到
1、获取共享数据
- 创建一个hello类继承HttpServlet,使用这个类将数据写入到servletContext中
package com.kuang.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class hello extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//将数据写入到ServletContext中,可以将ServletContext理解为一个全局变量,
// 在每一个servlet中都可以根据this.getServletContext获得ServletContext对象,
// 对其进行赋值和和获取
ServletContext servletContext = this.getServletContext();
String userName = "小海";
//将数据传输到了servletContext中
// servletContext.setResponseCharacterEncoding("utf-8");
servletContext.setAttribute("userName",userName);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp);
}
}
- 书写获取userName的类getName
这里需要注意的需要将输出格式修改为text/html
并且将编码格式修改为: utf-8 否则将输出乱码
package com.kuang.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class GetName extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
//获取到hello中传入的名字
String userName = (String) servletContext.getAttribute("userName");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().println("名字" + userName);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp);
}
}
- 配置所需要的路径
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.kuang.servlet.hello</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>getName</servlet-name>
<servlet-class>com.kuang.servlet.GetName</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getName</servlet-name>
<url-pattern>/getName</url-pattern>
</servlet-mapping>
访问测试结果:
2、获取初始化参数
获取步骤
- 在web.xml配置初始化的参数
<!-- 初始化资源-->
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/dbSpring</param-value>
</context-param>
- 写获取参数的类
package com.kuang.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Set;
public class ServletDemo03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
//括号内书写在xml中配置好的数据的名称
String url = servletContext.getInitParameter("url");
resp.getWriter().print(url);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp);
}
}
- 添加URL地址
<!-- demo03-->
<servlet>
<servlet-name>sd03</servlet-name>
<servlet-class>com.kuang.servlet.ServletDemo03</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sd03</servlet-name>
<url-pattern>/sd03</url-pattern>
</servlet-mapping>
3、请求转发
使用步骤:
- 书写所使用的类
package com.kuang.servlet;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Set;
public class ServletDemo04 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
// 括号中写入的是存在的URL地址,一定要加 /
// RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher("/sd03");
// requestDispatcher.forward(req, resp);
servletContext.getRequestDispatcher("/sd03").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp);
}
}
- 添加url
<!-- demo04-->
<servlet>
<servlet-name>sd04</servlet-name>
<servlet-class>com.kuang.servlet.ServletDemo04</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sd04</servlet-name>
<url-pattern>/sd04</url-pattern>
</servlet-mapping>
4、读取资源文件
步骤
- 编写获取的类
package com.kuang.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class ServletDemo05 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
//括号内为;连接资源文件所在的位置
InputStream is = servletContext.getResourceAsStream("/WEB-INF/classes/mysql.properties");
Properties prop = new Properties();
//加载数据流
prop.load(is);
//取得数据
String username = prop.getProperty("username");
String password = prop.getProperty("password");
resp.getWriter().println(username +":" + password);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp);
}
}
- 加入url
<!-- demo05-->
<servlet>
<servlet-name>sd05</servlet-name>
<servlet-class>com.kuang.servlet.ServletDemo05</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sd05</servlet-name>
<url-pattern>/sd05</url-pattern>
</servlet-mapping>
5.6、HttpServletResponse
简单使用:1、简单分类 2、下载文件 3、验证码功能 4、实现重定向
只有重定向才需要重点掌握。
package com.kuang.Response;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 关于重定向的实现
*/
public class Response extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//是使用resq的方法跳转页面
resp.sendRedirect("/s2/sd03");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
5.7、HttpServletResquest
1、获取前段参数并且请求转发
package com.kuang.RequestDemo;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
public class Resuest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置接受和响应的编码格式,用来解决乱码问题
req.setCharacterEncoding("uft-8");
resp.setCharacterEncoding("utf-8");
//接受页面上的参数
String username = req.getParameter("username");
String password = req.getParameter("password");
//接受一个字符串数组
String[] hobbies = req.getParameterValues("hobbies");
//在本地输出
resp.getWriter().println(username);
resp.getWriter().println(password);
resp.getWriter().println(Arrays.toString(hobbies));
//请求转发
req.getRequestDispatcher("/success").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
六、cookies、session
6.1、会话
一个网站,如何证明你是来过的?比如在网站上登录过一次之后,怎么使得第二次不用使用账号密码就登陆
客户端 服务端
1、服务端给客户端一个信件,客户端下次来访问的时候带上这个信件:cookie
2、服务器登录你来过了,下次来的时候来匹配你:seesion
6.2、保存会话的两种技术
cookie:客户端技术(请求、响应)
session:服务端技术,利用这个技术可以报存用户的会话信息
6.3、cookie实现(了解即可)
package com.kuang.cookies;
import com.sun.deploy.net.URLEncoder;
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 java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
public class Demo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
//获得cookie
Cookie[] cookies = req.getCookies();
//取得输出的对象
PrintWriter out = resp.getWriter();
if (cookies != null) {
// out.write(URLEncoder.encode("utf-8","上次访问为的时间"));
out.write("lastTime ");
for (int i = 0; i < cookies.length; i++) {
if (cookies[i].getName().equals("time")) {
String value = cookies[i].getValue();
Date date = new Date(Long.parseLong(value));
String toLocaleString = date.toLocaleString();
// System.out.println(toLocaleString);
out.write(toLocaleString);
}
}
}else {
out.write("这是您第一次访问");
}
Cookie time = new Cookie("time", System.currentTimeMillis() + "");
resp.addCookie(time);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
7.5、session(重点)
1.什么是session:
- 服务器会给每一个用户(浏览器)创建一个session对象
- 一个session独占一个浏览器,浏览器不关闭,session会一直存在
- 用户登录之后,session整个网站都可以访问到
2.session和cookie的区别
- cookie是将数据发送给客户端,让客户端(浏览器)保存
- session是将数据写到每一个客户端的session(重要信息的保存,减少服务端资源浪费)
- session由服务器对象创建
3.代码实现各种具体业务
以下代码中包括,有关于session的获取浏览器id,向session中写入数据(Person,Java声明的对象)
package com.kuang.session;
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;
import java.io.PrintWriter;
public class Sessiondemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决乱码问题
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
//创建输出的容器
PrintWriter out = resp.getWriter();
out.write("session为");
HttpSession session = req.getSession();
//获取每一个浏览器对应的唯一session
String jsessionid = session.getId();
//输出得到的session对象
// System.out.println("jsessionid = " + jsessionid);
out.write(jsessionid);
//给session中存入东西
//此处存入了一个proson对象,存入了一个对象,然后在另外一个servlet中获取
session.setAttribute("name",new Person("zhangsan","男"));
String name = (String) session.getAttribute("name");
System.out.println("name = " + name);
//手动删除自己的session,是登录账号注销的原理
session.removeAttribute("name");
//手动注销浏览器存在的session
session.invalidate();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
以下是Person对象的代码
package com.kuang.session;
public class Person {
private String name;
private String sex;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Person(String name, String sex) {
this.name = name;
this.sex = sex;
}
public Person() {
}
}
在另一个servlet中获取person
package com.kuang.session;
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 GetPerson extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决乱码
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
HttpSession session = req.getSession();
Person name = (Person) session.getAttribute("name");
System.out.println("name = " + name);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
配置的web.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">
<servlet>
<servlet-name>c1</servlet-name>
<servlet-class>com.kuang.cookies.Demo01</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>c1</servlet-name>
<url-pattern>/c1</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>c2</servlet-name>
<servlet-class>com.kuang.session.Sessiondemo01</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>c2</servlet-name>
<url-pattern>/c2</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>c3</servlet-name>
<servlet-class>com.kuang.session.GetPerson</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>c3</servlet-name>
<url-pattern>/c3</url-pattern>
</servlet-mapping>
<session-config>
<!-- 这是设置session存在多久的方式。默认为关闭浏览器就消失了,
此处的关闭浏览器不影响单位是min
-->
<session-timeout>15</session-timeout>
</session-config>
</web-app>