JavaWeb

web概念

1. 软件架构
	1. C/S:客户端/服务器端
	2. B/S:浏览器/服务器端

2. 资源分类
	1. 静态资源:所有用户访问后,得到的结果都是一样的,称为静态资源.静态资源可以直接被浏览器解析
		* 如: html,css,JavaScript
	2. 动态资源:每个用户访问相同资源后,得到的结果可能不一样。称为动态资源。动态资源被访问后,需要先转换为静态资源,在返回给浏览器
		* 如:servlet/jsp,php,asp....
3. 网络通信三要素
	1. IP:电子设备(计算机)在网络中的唯一标识。
	2. 端口:应用程序在计算机中的唯一标识。 0~65536
	3. 传输协议:规定了数据传输的规则
		1. 基础协议:
			1. tcp:安全协议,三次握手。 速度稍慢
			2. udp:不安全协议。 速度快

tomcat服务器

Tomcat:web服务器软件
	1. 下载:http://tomcat.apache.org/
	2. 安装:解压压缩包即可。
		注意:安装目录建议不要有中文和空格
	3. 卸载:删除目录就行了
	4. 启动
		bin/startup.bat ,双击运行该文件即可
		访问:浏览器输入:http://localhost:8080 回车访问自己
						  http://别人的ip:8080 访问别人
	可能遇到的问题:
		1. 黑窗口一闪而过:
			原因: 没有正确配置JAVA_HOME环境变量
			解决方案:正确配置JAVA_HOME环境变量
		2. 启动报错:
			1. 暴力:找到占用的端口号,并且找到对应的进程,杀死该进程
				netstat -ano
			2. 温柔:修改自身的端口号
				conf/server.xml
				"8888" protocol="HTTP/1.1"
	               connectionTimeout="20000"
	               redirectPort="8445" />
				一般会将tomcat的默认端口号修改为80。80端口号是http协议的默认端口号。
				好处:在访问时,就不用输入端口号
	5. 关闭
		1. 正常关闭:
			bin/shutdown.bat
			ctrl+c
		2. 强制关闭:
			点击启动窗口的×
	6. 配置
		部署项目的方式:
			1. 直接将项目放到webapps目录下即可。
			http://localhost:8080/hello/index.html
				/hello:项目的访问路径-->虚拟目录
				简化部署:将项目打成一个war包,再将war包放置到webapps目录下。
					war包会自动解压缩
			3. 配置conf/server.xml文件
				在标签体中配置
				"D:\hello" path="/hehe" />
				docBase:项目存放的路径
				path:虚拟目录
			4. 在conf\Catalina\localhost创建任意名称的xml文件。在文件中编写
				"D:\hello" />
				虚拟目录:xml文件的名称
		静态项目和动态项目:
			目录结构
				java动态项目的目录结构:
					-- 项目的根目录
						-- WEB-INF目录:
							-- web.xml:web项目的核心配置文件
							-- classes目录:放置字节码文件的目录
							-- lib目录:放置依赖的jar包

IDEA集成Tomcat

Run–>Edit Configurations–>Defaults–>Tomcat Server–>Local–>Configure…–>Tomcat_Home配置tomcat路径

创建web项目

JavaWeb_第1张图片
JavaWeb_第2张图片

web项目热部署

JavaWeb_第3张图片
“/“指项目目录,http://localhost:8080/hello/index.html中等于”/hello”
JavaWeb_第4张图片

Servlet: server applet

概念:运行在服务器端的小程序
	Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则。
	自定义一个类,实现Servlet接口,复写方法。
执行原理:
	1. 当服务器接受到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径
	2. 查找web.xml文件,是否有对应的标签体内容。
	3. 如果有,则在找到对应的全类名
	4. tomcat会将字节码文件加载进内存,并且创建其对象
	5. 调用其方法
配置Servlet
	在web.xml中配置:
	
	
	    demo1
	    cn.itcast.web.servlet.ServletDemo1
	
	
	    demo1
	    /demo1
	

Servlet生命周期

Servlet中的生命周期方法:
	1. 被创建:执行init方法,只执行一次,用于初始化资源
		Servlet什么时候被创建?
			默认情况下,第一次被访问时,Servlet被创建
			可以配置执行Servlet的创建时机。
				在<servlet>标签下配置
					1. 第一次被访问时,创建
                		<load-on-startup>的值为负数
		            2. 在服务器启动时,创建
		                <load-on-startup>的值为0或正整数
		  Servlet的init方法,只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的
			多个用户同时访问时,可能存在线程安全问题。
			解决:尽量不要在Servlet中定义成员变量。即使定义了成员变量,也应该是final2. 提供服务:执行service方法,执行多次
		每次访问Servlet时,Service方法都会被调用一次。
	3. 被销毁:执行destroy方法,只执行一次
		Servlet被销毁时执行。服务器正常关闭时,先执行destroy方法,然后Servlet被销毁
		destroy方法在Servlet被销毁之前执行,一般用于释放资源

Servlet+注解

Servlet3.0:
	好处:
		支持注解配置。可以不需要web.xml了。
	步骤:
		1. 创建JavaEE项目,选择Servlet的版本3.0以上,可以不创建web.xml
		2. 定义一个类,实现Servlet接口
		3. 复写方法
		4. 在类上使用@WebServlet注解,进行配置
			@WebServlet(urlPatterns="/资源路径") 或者 @WebServlet("/资源路径")

HttpServlet

Servlet -- 接口
	|
HttpServlet  -- 抽象类
HttpServlet:对http协议的一种封装,简化操作
		1. 定义类继承HttpServlet
		2. 复写doGet/doPost方法

urlpartten:Servlet访问路径

Servlet相关配置
urlpartten:Servlet访问路径
	1. 一个Servlet可以定义多个访问路径 : @WebServlet({"/d4","/dd4","/ddd4"})
	2. 路径定义规则:
		1. /xxx:路径匹配
		2. /xxx/xxx:多层路径,目录结构
		3. *.do:扩展名匹配

HTTP

Hyper Text Transfer Protocol 超文本传输协议
传输协议:定义了,客户端和服务器端通信时,发送数据的格式
特点:
	1. 基于TCP/IP的高级协议
	2. 默认端口号:80
	3. 基于请求/响应模型的:一次请求对应一次响应
	4. 无状态的:每次请求之间相互独立,不能交互数据
请求头Referer:告诉服务器,当前请求从哪里来?1. 防盗链:2. 统计工作

Request

request对象和response对象的原理
1. request和response对象是由服务器创建的。我们来使用它们
2. request对象是来获取请求消息,response对象是来设置响应消息

请求头
//1. 获取请求方式 :GET
String method = request.getMethod();
//2.(*)获取虚拟目录:/JavaWeb
String contextPath = request.getContextPath();
//3. 获取Servlet路径: //HttpServletTest
String servletPath = request.getServletPath();
//4. 获取get方式请求参数:userid=1&typeid=2
String queryString = request.getQueryString();
//5.(*)获取请求URI:/JavaWeb/HttpServletTest
String requestURI = request.getRequestURI();
//请求URL:http://localhost:8080/JavaWeb/HttpServletTest
StringBuffer requestURL = request.getRequestURL();
//6. 获取协议及版本:HTTP/1.1
String protocol = request.getProtocol();
//7. 获取客户机的IP地址:
String remoteAddr = request.getRemoteAddr();

//通过请求头的名称获取请求头的值
String cookie = request.getHeader("Cookie");
//获取所有的请求头名称
Enumeration<String> headers = request.getHeaderNames();
while (headers.hasMoreElements()){
    String key = headers.nextElement();
    String value = request.getHeader(key);
}

请求体
请求体:只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数
获取流对象
regist.html
<body>
    <form action="/JavaWeb/HttpServletTest" method="post">
        <input type="text" placeholder="pls input username" name="username"><br>
        <input type="text" placeholder="pls input pwd" name="password"><br>
        <input type="submit" value="注册"><br>
    </form>
</body>
//获取字符输入流,只能操作字符数据,可以获取form表单中传入的参数
protected void doPost(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
    BufferedReader bufferedReader  = request.getReader();
    String temp;
    while((temp=bufferedReader.readLine())!=null){
        System.out.println(temp);//username=philo_grace&password=Knight23-3
    }
}
//获取字节输入流,可以操作所有类型数据,在文件上传知识点后讲解
ServletInputStream getInputStream()

request ge&post请求通用方法

使用以下方法前不能使用request.getReader().readLine()
获取请求参数通用方式:不论get还是post请求方式都可以使用下列方法来获取请求参数
1. String getParameter(String name):根据参数名称获取参数值    username=zs&password=123
	String username = request.getParameter("username");
3. String[] getParameterValues(String name):根据参数名称获取参数值的数组  hobby=xx&hobby=game
4. Enumeration<String> getParameterNames():获取所有请求的参数名称
5. Map<String,String[]> getParameterMap():获取所有参数的map集合
	Map<String, String[]> parameterMap = request.getParameterMap();
	Set<String> keySet = parameterMap.keySet();
	for (String key : keySet) {
	    String[] values = parameterMap.get(key);
	    for (String value : values) {
	    }
	}

中文乱码问题

get方式:tomcat 8 已经将get方式乱码问题解决了
post方式:会乱码
	解决:在获取参数前,设置request的编码request.setCharacterEncoding("utf-8");

请求转发

域对象

servletA

//域对象:一个有作用范围的对象,可以在范围内共享数据
//request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
//方法:
//1. void setAttribute(String name,Object obj):存储数据
//2. Object getAttitude(String name):通过键获取值
//3. void removeAttribute(String name):通过键移除键值对
request.setAttribute("helloKey","helloValue");//域对象
        
请求转发,一种在服务器内部的资源跳转方式
request.getRequestDispatcher("/HelloWorldAnnotation").forward(request,resp);
特点:
1. 浏览器地址栏路径不发生变化
2. 只能转发到当前服务器内部资源中。
3. 转发是一次请求

servletB

一个有作用范围的对象,可以在范围内共享数据
request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
Object helloKey = servletRequest.getAttribute("helloKey");

BeanUtils工具类

BeanUtils工具类,简化数据封装
用于封装JavaBeanJavaBean:标准的Java,要求:
	1. 类必须被public修饰
	2. 必须提供空参的构造器
	3. 成员变量必须使用private修饰
	4. 提供公共setter和getter方法
导包commons-beanutils-1.8.0.jar
方法一:
String username = request.getParameter("username");
String password = request.getParameter("password");
UserBean userBean = new UserBean(1, username, password);
方法二:BeanUtils工具类
//获取请求所以参数
Map<String, String[]> map = request.getParameterMap();
//创建user对象
UserBean userBean = new UserBean();
//使用BeanUtils封装对象
BeanUtils.populate(userBean,map);

http响应状态码

响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态。
1. 状态码都是3位数字 
2. 分类:
	1. 1xx:服务器就收客户端消息,但没有接受完成,等待一段时间后,发送1xx多状态码
	2. 2xx:成功。代表:200
	3. 3xx:重定向。代表:302(重定向)304(访问缓存)
	4. 4xx:客户端错误。代表:
			404(请求路径没有对应的资源) 
			405:请求方式没有对应的doXxx方法
	5. 5xx:服务器端错误。代表:500(服务器内部出现异常)

重定向

重定向:资源跳转的方式
//1. 设置状态码为302
response.setStatus(302);
//2.设置响应头location
response.setHeader("location","/day15/responseDemo2");
//简单的重定向方法
response.sendRedirect("/day15/responseDemo2");

重定向的特点:redirect
1. 地址栏发生变化
2. 重定向可以访问其他站点(服务器)的资源
3. 重定向是两次请求。不能使用request对象来共享数据
转发的特点:forward
1. 转发地址栏路径不变
2. 转发只能访问当前服务器下的资源
3. 转发是一次请求,可以使用request对象来共享数据

相对路径&绝对路径

相对路径:通过相对路径不可以确定唯一资源
	如:./index.html
	不以/开头,以.开头路径
	规则:找到当前资源和目标资源之间的相对位置关系
	./:当前目录
	../:后退一级目录
绝对路径:通过绝对路径可以确定唯一资源
	如:http://localhost/webProject/webProject  /webProject/webProject
	以/开头的路径
	
	规则:判断定义的路径是给谁用的?判断请求将来从哪儿发出
		给客户端浏览器使用:需要加虚拟目录(项目的访问路径),"/webProject/webProject"
			建议虚拟目录动态获取:request.getContextPath()
			 , 
重定向... 给服务器使用:不需要加虚拟目录,"/AServlet" 转发路径

中文乱码

服务器输出字符数据到浏览器

//设置该流的默认编码,告诉浏览器响应体使用的编码
response.setContentType("text/html;charset=utf-8");
//PrintWriter不需要关闭资源,因为流对象由response获取,当此会话完成,流对象将自动关闭
PrintWriter pw = response.getWriter();
pw.write("你好");

ServletContext对象

ServletContext代表整个web应用,可以和程序的容器(服务器)来通信
获取:
1. 通过request对象获取
	request.getServletContext();
2. 通过HttpServlet获取
	this.getServletContext();
获取MIME类型:
	MIME类型:在互联网通信过程中定义的一种文件数据类型
		格式: 大类型/小类型   text/html		image/jpeg
	ServletContext servletContext = request.getServletContext();
	String file = "a.jpg";
	//获取MIME类型
	//image/jpeg
	String mimeType = servletContext.getMimeType(file);
	
域对象:共享数据
	ServletContext对象范围:所有用户所有请求的数据

获取文件的真实(服务器)路径
	/filename 指web目录下资源访问
	/WEB-INF指WEB-INF/filename 目录下资源访问
	/WEB-INF/classes/filename 指src目录下资源访问
	//D:\Developer\project\NewProject\out\artifacts\JavaWeb_war_exploded\index.jsp
	String realPath = servletContext.getRealPath("/index.jsp");

下载图片案例

download.html


"en">

    "UTF-8">
    download


    "/JavaWeb/downloadServlet?filename=abc.jpg">图片1


downloadServlet

//Ctrl+Alt+v自动补全返回值
//1.获取请求参数,文件名称
String filename = request.getParameter("filename");
//2.使用字节输入流加载文件进内存
//2.1找到文件服务器路径
ServletContext servletContext = this.getServletContext();
String realPath = servletContext.getRealPath("/img/" + filename);
//2.2用字节流关联
FileInputStream fis = new FileInputStream(realPath);
//3.设置response的响应头
//3.1设置响应头类型:content-type
String mimeType = servletContext.getMimeType(filename);//获取文件的mime类型
response.setHeader("content-type",mimeType);
//3.2设置响应头打开方式:content-disposition
response.setHeader("content-disposition","attachment;filename="+filename);
//4.将输入流的数据写出到输出流中
ServletOutputStream sos = response.getOutputStream();
byte[] buff = new byte[1024 * 8];
int len = 0;
while((len = fis.read(buff)) != -1){
    sos.write(buff,0,len);
}
fis.close();

会话

一次会话中包含多次请求和响应
一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止
1. 客户端会话技术:Cookie
2. 服务器端会话技术:Session

Cookie曲奇

客户端会话技术,将数据保存到客户端

Cookie原理
第一次请求
	1,服务器,new Cookie();response.addCookie(cookie);
	2,浏览器,响应头Set-Cookie: lastLogonTime=2022%E5%B9%B407%E6%9C%8821%E6%97%A5+22%3A29%3A41; Max-Age=3000; Expires=Thu, 21-Jul-2022 15:19:41 GMT
第二次请求
	3,浏览器,请求头Cookie: lastLogonTime=2022%E5%B9%B407%E6%9C%8821%E6%97%A5+23%3A26%3A44
	4,服务器,request.getCookies();

可以创建多个Cookie对象,使用response调用多次addCookie方法发送cookie即可

cookie保存时间
	默认情况
		当浏览器关闭后,Cookie数据被销毁
	持久化存储
		//set cookie 过期时间为3000s
		cookie.setMaxAge(3000);

cookie共享
	假设在一个tomcat服务器中,部署了多个web项目
		cookie.setPath(String path):设置cookie的获取范围.默认情况下,设置当前的虚拟目录.如果要共享,则可以将path设置为"/"
	不同的tomcat服务器间cookie共享
		如果设置一级域名相同,那么多个服务器之间cookie可以共享
		cookie.setDomain(".baidu.com"),那么tieba.baidu.com和news.baidu.com中cookie可以共享

cookie作用:
	cookie一般用于存出少量的不太敏感的数据
	在不登录的情况下,完成服务器对客户端的身份识别

URL编码,解码

//URL编码
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String format = sdf.format(date);
//An invalid character [32] was present in the Cookie value,由于字符串中带有空格造成
//2022%E5%B9%B407%E6%9C%8821%E6%97%A5+22%3A29%3A41
String encode = URLEncoder.encode(format, "utf-8");

//URL解码
//2022年07月21日 23:26:44
String decode = URLDecoder.decode(cookie.getValue(), "utf-8");

set a lastLogonTime cookie案例

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //Ctrl+Alt+v自动补全返回值
    response.setContentType("text/html;charset=utf-8");
    PrintWriter writer = response.getWriter();
    boolean flag = false;
    //not first logon
    Cookie[] cookies = request.getCookies();
    if (cookies!=null && cookies.length>0){
        for (Cookie cookie : cookies) {
            if("lastLogonTime".equals(cookie.getName())){
                flag = true;
                updateCookie(response);
                String decode = URLDecoder.decode(cookie.getValue(), "utf-8");
                writer.write("welcome to back, last logon time is "+decode);
                break;
            }
        }
    }
    //first logon
    if (!flag){
        updateCookie(response);
        writer.write("welcome to this page");
    }
}
private void updateCookie(HttpServletResponse response) throws UnsupportedEncodingException {
    Date date = new Date();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
    String format = sdf.format(date);
    //An invalid character [32] was present in the Cookie value
    String encode = URLEncoder.encode(format, "utf-8");
    Cookie cookie = new Cookie("lastLogonTime",encode);
    //set cookie 过期时间为3000s
    cookie.setMaxAge(3000);
    response.addCookie(cookie);
}

Session主菜

服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。HttpSession

Session原理
第一次请求
	1,服务器端,
		HttpSession session = request.getSession();
		session.setAttribute("s1","v1");
	2,浏览器,响应头Set-Cookie:
		Set-Cookie: JSESSIONID=990D92A162E50B2B82853C704AAD9C44; Path=/JavaWeb; HttpOnly
第二次请求
	3,浏览器,请求头Cookie: 
		Cookie: JSESSIONID=990D92A162E50B2B82853C704AAD9C44
	4,服务器,
		HttpSession session = request.getSession();
		String s1 = (String)session.getAttribute("s1");

session的特点
	 1. session用于存储一次会话的多次请求的数据,存在服务器端
	 2. session可以存储任意类型,任意大小的数据

关闭浏览器/服务器时session状态

当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
默认情况下。不是。
如果需要相同,则可以创建Cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存。
	 Cookie c = new Cookie("JSESSIONID",session.getId());
     c.setMaxAge(60*60);
     response.addCookie(c);

客户端不关闭,服务器关闭后,两次获取的session是同一个吗?
	不是同一个,但是要确保数据不丢失。tomcat自动完成以下工作
		session的钝化:
			在服务器正常关闭之前,将session对象系列化到硬盘上
		session的活化:
			在服务器启动后,将session文件转化为内存中的session对象即可(反序列化)

session失效时间

web.xml


    30

销毁session

//返回当前会话的session,如果当前会话session为null,则返回空
HttpSession session = request.getSession(false);
if (session!=null){
	//销毁当前session
    session.invalidate();
}
//返回当前会话session对象,如果为null,则创建一个新session
session = request.getSession(true);

Session与Cookie的区别

1. Session存储数据在服务器端,Cookie在客户端
2. Session没有数据大小限制,Cookie有
3. Session数据安全,Cookie相对于不安全

JSP

Java Server Pages: java服务器端页面
JSP本质上就是一个Servlet
<%  代码 %>
定义的java代码,在service方法中。service方法中可以定义什么,该脚本中就可以定义什么
<%! 代码 %>
定义的java代码,在jsp转换后的java类的成员位置
<%= 代码 %>
定义的java代码,会输出到页面上。输出语句中可以定义什么,该脚本中就可以定义什么
jsp一共有9个内置对象
request
response
out相当于response.getWriter()

JSP配置

<%--page配置JSP页面的--%>
<%-- contentType:等同于response.setContentType()
1. 设置响应体的mime类型以及字符集
2. 设置当前jsp页面的编码--%>
<%--import:导包--%>
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="com.web.bean.Student" %>
<%--errorPage:当前页面发生异常后,会自动跳转到指定的错误页面
isErrorPage:标识当前也是是否是错误页面
  true:是,可以使用内置对象exception
  false:否。默认值。不可以使用内置对象exception--%>
<%@ page contentType="text/html;charset=UTF-8" language="java"
errorPage="download.html" isErrorPage="false" %>

<%--include	: 导入别的页面的资源文件--%>
<%@include file="top.jsp"%>

<%--taglib	: 导入资源; prefix:前缀,自定义的--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

JSP内置对象

内置对象
在jsp页面中不需要创建,直接使用的对象
一共有9个:
变量名					真实类型						作用
pageContext				PageContext					当前页面共享数据,还可以获取其他八个内置对象
request					HttpServletRequest			一次请求访问的多个资源(转发)
session					HttpSession					一次会话的多个请求间
application				ServletContext				所有用户间共享数据
response				HttpServletResponse			响应对象
page					Object						当前页面(Servlet)的对象  this
out						JspWriter					输出对象,数据输出到页面上
config					ServletConfig				Servlet的配置对象
exception				Throwable					异常对象

MVC:开发模式

MVC:开发模式
1. M:Model,模型。JavaBean
  完成具体的业务操作,如:查询数据库,封装对象
2. V:View,视图。JSP
  展示数据
3. C:Controller,控制器。Servlet
  获取用户的输入
  调用模型
  将数据交给视图进行展示

EL表达式

EL表达式
Expression Language 表达式语言
作用:替换和简化jsp页面中java代码的编写
语法:${表达式}

1.${域名称.键名}:从指定域中获取指定键的值
  域名称:
    1. pageScope		--> pageContext
    2. requestScope 	--> request
    3. sessionScope 	--> session
    4. applicationScope --> application(ServletContext)
  举例:在request域中存储了name=张三
  获取:${requestScope.name}
2.${键名}:表示依次从最小的域中查找是否有该键对应的值,直到找到为止
3. 获取对象、List集合、Map集合的值
    1. 对象:${域名称.键名.属性名}
        本质上会去调用对象的getter方法
    2. List集合:${域名称.键名[索引]}
    3. Map集合:
        ${域名称.键名.key名称}
        ${域名称.键名["key名称"]}
  <%
    request.setAttribute("name","zhangsan");
    Student student = new Student("jack");
    request.setAttribute("student",student);
    List list = new ArrayList();
    list.add("abc");
    request.setAttribute("list",list);
  %>
  ${requestScope.name}
$
{requestScope.student.name}
$
{requestScope.list[0]}
运算符:
1. 算数运算符: + - * /(div) %(mod)
2. 比较运算符: > < >= <= == !=
3. 逻辑运算符: &&(and) ||(or) !(not)
4. 空运算符: empty
功能:用于判断字符串、集合、数组对象是否为null或者长度是否为0
${empty list}:判断字符串、集合、数组对象是否为null或者长度为0
${not empty str}:表示判断字符串、集合、数组对象是否不为null 并且 长度>0

空运算符: empty
$
{empty requestScope.list[0]}
$
{not empty requestScope.list[0]}
隐式对象:
el表达式中有11个隐式对象
pageContext:
获取jsp其他八个内置对象
${pageContext.request.contextPath}:动态获取虚拟目录

虚拟路径是	 ${pageContext.request.contextPath}
<%--if语句--%>
<%--c:if标签没有else情况,想要else情况,则可以在定义一个c:if标签--%>
  <c:if test="${not empty requestScope.name}">
    if语句被执行
c:if> <%--Switch语句--%> 1. 使用choose标签声明 相当于switch声明 2. 使用when标签做判断 相当于case 3. 使用otherwise标签做其他情况的声明 相当于default <% request.setAttribute("num",6); %> <c:choose> <c:when test="${num<=5}">周内c:when> <c:when test="${num>5 && num<=7}">周末c:when> <c:otherwise>不晓得c:otherwise> c:choose> <%--foreach语句 items容器对象 var容器中的元素 varStatus循环状态对象 index索引 count循环次数--%> <% List lists = new ArrayList(); lists.add("abc"); lists.add("bcd"); lists.add("xyz"); request.setAttribute("lists",lists); %> ${list} ${s.index} ${s.count}
c:forEach>

Filter过滤器

web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能
一般用于完成通用的操作。如:登录验证、统一编码处理、敏感字符过滤...

配置filter
方法1,注解
@WebFilter("/*")//访问所有资源之前,都会执行该过滤器
public class FilterDemo1 implements Filter {}
方法2,web.xml配置

   demo1
    cn.itcast.web.filter.FilterDemo1


    demo1
	
    /*
    
    REQUEST


Filter过滤器生命周期方法
1. init:在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源
2. doFilter:每一次请求被拦截资源时,会执行。执行多次
3. destroy:在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源

过滤器配置详解
拦截路径配置:
	1. 具体资源路径: /index.jsp   只有访问index.jsp资源时,过滤器才会被执行
	2. 拦截目录: /user/*	访问/user下的所有资源时,过滤器都会被执行
	3. 后缀名拦截: *.jsp		访问所有后缀名为jsp资源时,过滤器都会被执行
	4. 拦截所有资源:/*		访问所有资源时,过滤器都会被执行
拦截方式配置:资源被访问的方式
	注解配置:
		设置dispatcherTypes属性
			1. REQUEST:默认值。浏览器直接请求资源
			2. FORWARD:转发访问资源
			3. INCLUDE:包含访问资源
			4. ERROR:错误跳转资源
			5. ASYNC:异步访问资源
	web.xml配置
		设置标签即可

过滤器先后顺序问题:
		1. 注解配置:按照类名的字符串比较规则比较,值小的先执行
			如: AFilter 和 BFilter,AFilter就先执行了。
		2. web.xml配置: 谁定义在上边,谁先执行

触发link
localhost:8080/projectName/oneServlet?name=我是和谐词
结果: 我是***词

import javax.servlet.*;
import java.io.*;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
//@WebFilter("/*")
public class ReplaceFilter implements Filter {
    private List lists = new ArrayList();
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        try {
            //1.获取文件真实路径
            ServletContext servletContext = filterConfig.getServletContext();
            String realPath = servletContext.getRealPath("/WEB-INF/classes/replace.txt");
            System.out.println(realPath);
            //2.读取文件
            InputStreamReader fReader = new InputStreamReader(new FileInputStream(realPath),"UTF-8");
            BufferedReader br = new BufferedReader(fReader);
            //3.将文件的每一行数据添加到list中
            String line = null;
            while((line = br.readLine())!=null){
                lists.add(line);
            }
            System.out.println(lists);
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //servletRequest.getParameter("");
        ServletRequest proxyRequest = (ServletRequest)Proxy.newProxyInstance(
                servletRequest.getClass().getClassLoader(),
                servletRequest.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //增强getParameter方法
                        if ("getParameter".equals(method.getName())) {
                            //增强返回值
                            String value = (String) method.invoke(servletRequest, args);
                            if (value != null) {
                                for (String str : lists) {
                                    if (value.contains(str)) {
                                        value = value.replace(str, "***");
                                    }
                                }
                            }
                            return value;
                        }else{
                            return method.invoke(servletRequest, args);
                        }
                    }
                });
        //放行
        filterChain.doFilter(proxyRequest,servletResponse);
    }
    @Override
    public void destroy() {}
}

web.xml config


    demo1
    com.web.filter.ReplaceFilter


    demo1
    
    /*

Listener监听器

事件监听机制
	事件	:一件事情
	事件源 :事件发生的地方
	监听器 :一个对象
	注册监听:将事件、事件源、监听器绑定在一起。 当事件源上发生某个事件后,执行监听器代码
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.io.FileInputStream;
@WebListener
public class ContextLoaderListener implements ServletContextListener {
    /**
     * 监听ServletContext对象创建的。ServletContext对象服务器启动后自动创建。
     * 在服务器启动后自动调用
     */
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        //加载资源文件
        //1.获取ServletContext对象
        ServletContext servletContext = servletContextEvent.getServletContext();
        //2.加载资源文件
        /*
            contextConfigLocation
            /WEB-INF/classes/applicationContext.xml
        */
        String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation");
        //3.获取真实路径
        String realPath = servletContext.getRealPath(contextConfigLocation);
        //4.加载进内存
        try{
            FileInputStream fis = new FileInputStream(realPath);
            System.out.println(fis);
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println("ServletContext对象被创建了。。。");
    }
    //在服务器关闭后,ServletContext对象被销毁。当服务器正常关闭后该方法被调用
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("ServletContext对象被销毁了。。。");
    }
}

web.xml配置监听器



   cn.itcast.web.listener.ContextLoaderListener



    contextConfigLocation
    /WEB-INF/classes/applicationContext.xml

applicationContext.xml配置文件

"1.0" encoding="UTF-8"?>

post请求中查看RequestBody

在JME中遇到org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: 问题的解决方法
postman使用@RequestBody的方式传递两个List<String>集合

payload–>request payload–>view parsed–>copy
在这里插入图片描述
在这里插入图片描述

你可能感兴趣的:(Java基础,java)