目录
Gitee仓库:https://gitee.com/inandout/mad-god-java-web/tree/dev/
一、Web开发概述
1、WEB资源介绍
静态资源:源代码不变,展示效果不变(html/css/js 图片 视频)
动态资源:展示内容会根据数据的改变而改变(由程序来控制) servlet 、jsp
在java中,动态web资源开发的技术统称为JavaWeb
2、软件架构
目前市场上有两种流行的软件架构:
C/S架构:Client/Server 客户端/服务器。要求用户安装一个客户端程序。
常见应用:qq音乐、王者荣耀、网易云、消消乐、抖音、快手、头条
优点:
1.用户体验好,效果炫
2.对信息安全的控制较强
3.应用服务器运行数据负荷较轻,部分计算功能在客户端完成。
缺点(客户端程序上):
1.占用硬盘空间
2.维护麻烦
3.安装使用依赖其他条件
B/S架构:Browser/Server 浏览器/服务器 。通过浏览器与服务器交互,不需要安装其他程序
常见应用:12306、淘宝、京东、去哪儿
优点(没有客户端,直接使用浏览器即可):
1.维护和升级简单,无缝升级。
2.不用必须安装程序,操作系统内置了浏览器。大大减少了使用成本
缺点(效果一般、体验一般、服务器压力极大):
1.动画效果受浏览器限制
2.对信息安全控制较差。例如:网银就需要使用U盾,在浏览器端加密。
3.应用服务器运行数据负荷较重。大部分计算都在服务器端,增加服务器压力。使用Ajax可以改善部分用户体验。
3、WEB通信模式 (B/S)
请求和响应是成对出现的。 而且必须先有请求,再有响应 (类似与一问一答)
4、Url请求路径
URL (Uniform Resource Locator) ,统一资源定位符(器),是对互联网上资源位置的一种表示,互联网上的每个文件都有一个唯一的URL。
用于标识互联网上某个资源的具体位置,相当于内网路径中的绝对路径
完整格式如下:
协议://域名:端口号/资源位置?参数=值
协议,http、https、ftp等 【必须写】
域名,域名或IP地址,都可以访问WEB资源【必须写】
端口号,程序必须使用端口号,才可以让另一个计算机访问
资源位置,用于描述WEB资源再服务器上的位置。
参数=值,浏览器和服务器交互传递的数据
5、Web服务器软件
服务器:在电脑上安装一个服务器软件,你的电脑就是一台服务器。
J2EE 企业级开发Java规范。标准规范包括:servlet、jsp、jdbc、xml、jta、javamail等。在java中规范就是接口。J2EE又称为JavaEE。
WEB服务器对JavaEE规范部分或全部支持(实现),也就是WEB服务器实现部分或全部接口。
常见的WEB服务器:Tomcat、WebLogic、WebSphere、JBoss
二、Tomcat服务器
1、Tomcat版本
tomcat 目前存在很多版本,希望大家了解tomcat的版本,从而知道自己的创建的项目使用的是几版本规范,不同版本的规范技术可能不同。
这里看到9版本才支持java8,以前我用的一直是8.5.45版本,必须得换了。
2、Tomcat的安装
由于Tomcat是免安装的,所以解压就可以使用了
环境变量
目前的环境变量只适用于单个Tomcat的情况,所以不配置更好
3、Tomcat目录结构
webapps中有5个项目
可以通过域名访问其中的任意一个项目
可能遇到的问题:
- java环境变量没有配置
- 闪退问题:需要配置兼容性
- 乱码问题:配置文件中设置
4、Tomcat启动、访问、关闭
启动、关闭,直接运行脚本
非正常关闭
Ctrl + c 进行关闭
点叉直接关闭
电脑关机(从任务管理器关闭)
访问Tomcat服务器项目的首页
localhost:8080
5、Tomcat的配置
查看server.xml服务器的核心配置文件
默认地址为localhost:8080
默认网站应用存放位置:webApps
可以通过修改hosts文件,来修改域名
高难度面试题:
请你谈谈网站是如何进行访问的?
1、输入一个域名;回车
2、检查本机的配置文件C:\Windows\System32\drivers\etc\hosts下有没有这个域名的映射
有:直接返回对应的ip地址,这个地址中,有我们需要放的web程序,可以直接访问
没有:去DNS服务器找,找到的话就返回,找不到就返回找不到
6、Tomcat中的web项目目录结构
在JavaEE规范中,WEB项目存在一定的目录结构,具体结构如下:
一个项目只要有classes才可能有动态WEB资源
只要WEB项目符合规范,放置在webapps目录中,服务器就会将其顺利发布网络
WEB-INF 是一个保护目录 浏览器不能去访问它下边的资源
7、idea整合Tomcat
三、Eclipse & idea中tomcat的配置和web项目构建_idea tomcat部署项目eclipse 项目_Daniel521-Spark的博客-CSDN博客
项目结构
加载web.xml为web项目
跳转到artifacts页面,部署对应的web服务
创建Tomcat服务配置
部署deployment,将artifacts包加进来
启动Tomcat,即可打开首页
三、HTTP
1、概述
什么是HTTP协议
HTTP协议: 超文本传输协议 它是互联网运用最广泛的一种网络协议,专门用来进行超文本信息传输, 规定 和 规范 浏览器与服务器之间的数据传输格式
特点:1.简单快捷 2.灵活 3.无连接 4.无状态
协议组成两种: 请求协议和响应协议
两个时代
HTTP/1.0:客户端可以与web服务器连接后,只能获得一个web资源,使用完断开连接
HTTP/2.0:客户端可以与web服务器连接后,可以获得多个web资源,长连接
2、HTTP请求
客户端 -> 服务器
请求行
GET,POST, HEAD,DELETE,PUT,TRACT
Get请求和Post请求的区别:
1.get请求数据在请求行上,Post请求在请求体中
2.Get请求安全性较低, Post请求安全较高
3.Get请求提交数据有限制(不能超过4KB), Post请求数据量无限制
消息头
Accept: 告诉浏览器,它所支持的类型
Accept-Encoding: 支持哪种编码格式 GBK UTF-8 GB2312 ISO8859-1
Accept-Language: 告诉浏览器,它的语言环境
Cache-Control: 缓存控制
Connection: 告诉浏览器,请求完成是断开还是保持连接
Host:主机
3、HTTP响应
服务器 -> 客户端
响应体
传递的是请求需要查看的资源数据,数据量无限。
如果访问的是一个html页面,那么响应回来的就是一个页面
状态码
200: 响应成功
404: 路径找不到(检查路径)
500: 服务器内部代码出现异常(通过debug断点测试)
304: 缓存 (清除浏览器缓存)
302: 重定向 (后边讲)
405: 方法找不到
四、Maven
核心思想:约定大于配置
其实在开发中,处处都用到了“约定大于配置”这一思想
- 就是在开发中,如果有些值你没有配置的话,那程序会取一个默认值,换句话说,能取默认值的配置,就不需要配置了,这个默认值就是约定。
- spring boot的理念就是约定大于配置,在spring boot中提供了一套默认配置,不需要手动去写xml配置文件,只有默认配置不能满足我们的需求时,才会去修改配置。
1、什么是Maven
Maven 是 Apache 软件基金会组织维护的一款自动化构建工具,专注服务于 Java 平 台的项目构建和依赖管理。Maven 这个单词的本意是:专家,内行。读音是 ['me v( )n] 或 ['mevn]。
作用:可以对项目需要的jar包进行引入,并且进行统一化的管理;可以解决jar包之间的依赖;可以进行模块化的开发
2、Maven的安装和配置
官网下载
解压缩、配置环境变量
MAVEN_HOME
修改settings.xml
阿里云镜像地址:用的人多,说明生态很好
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>*,!jeecg,!jeecg-snapshots</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
3、在Idea中使用Maven
如何创建maven项目
总览
所以经常导入一个包,要下载很多个依赖
4、maven仓库的使用
五、Servlet
1、Servlet的发展史
Servlet也是由复杂难用、功能单一,逐步发展到目前的操作简单,功能强大的。
Servlet的发展史,完全就是一部人类由猿人的进化史。
2、Servlet简介
- servlet就是sun公司开发动态web的一门技术
- sun在这些api中提供一个接口叫做:servlet,如果你想开发一个servlet程序,只需要完成两个小步骤:
编写一个类,实现servlet接口
把开发好的java类部署到web服务器中
把实现了servlet接口的java程序叫做,servlet
3、第一个Servlet程序
导入依赖
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
</dependency>
项目结构
helloServlet.java
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
resp.setCharacterEncoding("UTF-8");
PrintWriter writer = resp.getWriter();
writer.write("第一个Servlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(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>helloServlet</servlet-name>
<servlet-class>com.kuang.Servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/helloServlet</url-pattern>
</servlet-mapping>
</web-app>
启动Tomcat(启动流程在Tomcat章节有),访问localhost:8080/helloServlet
六、Servlet的原理
1、原理图
2、Servlet的Mapping
一个servlet可以指定多个映射路径
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/hello2</url-pattern>
</servlet-mapping>
一个servlet可以指定通用映射路径
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/hello/*</url-pattern>
</servlet-mapping>
指定一些后缀或者前缀等等
<!-- 可以自定义后缀实现请求映射
注意点:*前面不能加项目映射的路径 /hello/*.do 是不可以的
但是/hello/hi.do是可以的
-->
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
Mapping的优先级
制定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求
七、ServletContext对象
web容器在启动的时候,它会为每个web程序都创建一个对应的servletContext对象,它代表了当前的web应用。
1、共享数据
创建项目
helloServlet.java
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// this.getInitParameter();
// this.getServletConfig();
// 获取servlet 上下文
ServletContext servletContext = this.getServletContext();
servletContext.setAttribute("name", "小狂狂");
PrintWriter writer = resp.getWriter();
writer.write("这是HelloServlet");
}
getServlet.java
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String name = (String) servletContext.getAttribute("name");
resp.setContentType("text/html");
resp.setCharacterEncoding("UTF-8");
PrintWriter writer = resp.getWriter();
writer.write("从ServletContext中获取到的名字是:" + name);
}
配置Tomcat,启动运行结果
2、获取初始化参数
web.xml
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
GetParamServlet.java
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String url = servletContext.getInitParameter("url");
resp.setContentType("text/html");
resp.setCharacterEncoding("UTF-8");
PrintWriter writer = resp.getWriter();
writer.write("从ContextParam中获取到的参数是:" + url);
}
启动服务器测试
3、请求转发
ReqDispatcherServlet.java
public class ReqDispatcherServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
servletContext.getRequestDispatcher("/GetServlet").forward(req, resp);
System.out.println("转发到了GetServlet");
}
启动服务器测试
4、读取资源文件
创建db.properties文件
GetLocalFileServlet.java
public class GetLocalFileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
InputStream in = req.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
Properties pro = new Properties();
pro.load(in);
String name = pro.getProperty("username");
String pwd = pro.getProperty("password");
resp.getWriter().print(name + ":" + pwd);
}
启动服务器测试
文件所在位置
八、HttpServletResponse
web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象,一个代表响应的HttpServletResponse
- 如果要获取客户端请求过来的参数:找HttpServletRequest
- 如果要给客户端响应一些信息:找HttpServletResponse
1、向浏览器输出消息
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 获取下载文件的路径
String realPath = "C:\\Users\\simmons333\\Desktop\\GitBash\\javaWeb\\responseRequest\\src\\main\\resources\\11.jpg";
// 2. 下载的文件名是啥?
String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
// 3. 设置想办法让浏览器能都支持我们下载的东西 文件名是中文的时候,可以设置URLEncoder.encode(fileName, "UTF-8"),否则有可能乱码
resp.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
// 4. 获取下载文件的输入流
FileInputStream in = new FileInputStream(realPath);
// 5. 创建缓冲区
int len = 0;
byte[] buffer = new byte[1024];
// 6. 获取OutputStrem对象
ServletOutputStream out = resp.getOutputStream();
// 7. 将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输出到客户端
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
out.flush();
out.close();
in.close();
}
启动服务器测试
2、response验证码实现
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 如何让浏览器三秒自动刷新一次
resp.setHeader("refresh", "3");
// 在内存中创建一个图片
BufferedImage bufferedImage = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
// 得到图片
Graphics2D bi = (Graphics2D) bufferedImage.getGraphics();
// 设置背景颜色为白色
bi.setColor(Color.WHITE);
bi.fillRect(0, 0, 80, 20);
// 给图片写数据
bi.setColor(Color.BLUE);
bi.setFont(new Font(null, Font.BOLD, 20));
bi.drawString(makeNum(), 0, 20);
// 告诉浏览器用图片的方式打开
resp.setContentType("image/jpeg");
// 网站存在缓存,不让浏览器缓存
resp.setDateHeader("Expires", 0);
resp.addHeader("Cache-Control", "no-cache");
resp.setHeader("Pragma", "no-cache");
ImageIO.write(bufferedImage, "jpeg", resp.getOutputStream());
}
/**
* 生成随机数
*/
private String makeNum() {
Random random = new Random();
String num = random.nextInt(999999) + "";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 6 - num.length(); i++) {
sb.append("0");
}
return sb.toString() + num;
}
启动服务器测试,这里图片的位置需要css来设置,后端无法控制
3、response重定向
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 重定向
resp.sendRedirect("/ImageServlet");
// 相当于
// resp.setHeader("Location", "/ImageServlet");
// resp.setStatus(302);
}
转发和重定向的区别
- 转发是服务器内部进行操作的,URL地址拦不会变,307
- 重定向是浏览器进行操作的,URL地址拦会发生变化,302
九、HttpServletRequest
HttpServletRequest代表客户端的请求,用户通过http协议访问服务器,HTTP请求中的所有信息会被封装到HttpServletRequest中,通过HttpServletRequest这个方法,可以获取客户端的所有信息
index.jsp
<%@ page language="java" contentType="text/html; charset=GB2312" %>
<html>
<body>
<h2>Hello World!</h2>
<%--这里提交的路径,需要寻找项目的路径--%>
<%--${pageContext.request.contextPath}代表当前的项目--%>
<form action="${pageContext.request.contextPath}/LoginServlet" method="get">
用户名:<input type="text" name="username"/><br/>
密码:<input type="password" name="pwd"/><br/>
<input type="submit"/>
</form>
</body>
</html>
LoginServlet.java
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
String username = req.getParameter("username");
String pwd = req.getParameter("pwd");
System.out.println(username + pwd);
if (username !=null && pwd!=null){
// 重定向
resp.sendRedirect("/responseRequest/success.jsp");
}
}
启动服务器测试
JSP、Tomcat、springmvc乱码解决方法
解决jsp页面乱码的方法
JSP中文乱码问题终极解决方案_jsp乱码_郗晓勇的博客-CSDN博客
1、在Servlet里加上控制字符串格式的代码
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
2、在jsp文件的头部加上一行
<%@ page language="java" contentType="text/html; charset=utf-8" %>
解决Tomcat控制台println乱码方法
Tomcat启动之后,控制台System.out.println打印中文乱码解决方案_system.out.println tomcat_月熙_的博客-CSDN博客
在Tomcat启动配置里加上,VM options = -Dfile.encoding=UTF-8
解决springmvc乱码方案
1、自己写简单过滤器
package com.zql.filter;
import javax.servlet.*;
import java.io.IOException;
import java.util.logging.LogRecord;
/**
* @Author:Daniel
* @Version 1.0
*/
public class Encoding implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
//解决请求和响应乱码问题(可移动到过滤其中统一处理)
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8");
filterChain.doFilter(request,response);
}
@Override
public void destroy() {
}
}
web.xml导入过滤器
<!--过滤器-->
<filter>
<filter-name>encoding</filter-name>
<filter-class>com.zql.filter.Encoding</filter-class>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2、使用springmvc提供的过滤器
<!--springmvc提供-->
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3、修改tomcat的配置
<Connector URIEncoding="utf-8" port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
4、自定义复杂过滤器
package com.zql.filter;
/**
* @Author:Daniel
* @Version 1.0
*/
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
/**
* 解决get和post请求 全部乱码的过滤器
*/
public class GenericEncodingFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//处理response的字符编码
HttpServletResponse myResponse=(HttpServletResponse) response;
myResponse.setContentType("text/html;charset=UTF-8");
// 转型为与协议相关对象
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
// 对request包装增强
HttpServletRequest myrequest = new MyRequest(httpServletRequest);
chain.doFilter(myrequest, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}
//自定义request对象,HttpServletRequest的包装类
class MyRequest extends HttpServletRequestWrapper {
private HttpServletRequest request;
//是否编码的标记
private boolean hasEncode;
//定义一个可以传入HttpServletRequest对象的构造函数,以便对其进行装饰
public MyRequest(HttpServletRequest request) {
super(request);// super必须写
this.request = request;
}
// 对需要增强方法 进行覆盖
@Override
public Map getParameterMap() {
// 先获得请求方式
String method = request.getMethod();
if (method.equalsIgnoreCase("post")) {
// post请求
try {
// 处理post乱码
request.setCharacterEncoding("utf-8");
return request.getParameterMap();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else if (method.equalsIgnoreCase("get")) {
// get请求
Map<String, String[]> parameterMap = request.getParameterMap();
if (!hasEncode) { // 确保get手动编码逻辑只运行一次
for (String parameterName : parameterMap.keySet()) {
String[] values = parameterMap.get(parameterName);
if (values != null) {
for (int i = 0; i < values.length; i++) {
try {
// 处理get乱码
values[i] = new String(values[i]
.getBytes("ISO-8859-1"), "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
}
hasEncode = true;
}
return parameterMap;
}
return super.getParameterMap();
}
//取一个值
@Override
public String getParameter(String name) {
Map<String, String[]> parameterMap = getParameterMap();
String[] values = parameterMap.get(name);
if (values == null) {
return null;
}
return values[0]; // 取回参数的第一个值
}
//取所有值
@Override
public String[] getParameterValues(String name) {
Map<String, String[]> parameterMap = getParameterMap();
String[] values = parameterMap.get(name);
return values;
}
}
web.xml导入过滤器
<!--自定义过滤-->
<filter>
<filter-name>encoding</filter-name>
<filter-class>com.zql.filter.GenericEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>