JavaWeb小结一

总结了Day01 到 Day09 的知识

一、servlet

Servlet的体系结构:HttpServlet extends GenericServlet extends Servlet
	
	Servlet -- 接口
		|
	GenericServlet -- 抽象类
		|
	HttpServlet  -- 抽象类

二、HTTP

1.HTTP请求消息数据格式

在这里插入图片描述

* 请求消息数据格式
	1. 请求行
		请求方式 请求url 请求协议/版本
		GET /login.html	HTTP/1.1

		* 请求方式:
			* HTTP协议有7中请求方式,常用的有2* GET:
					1. 请求参数在请求行中,在url后。
					2. 请求的url长度有限制的
					3. 不太安全
				* POST:
					1. 请求参数在请求体中
					2. 请求的url长度没有限制的
					3. 相对安全
	2. 请求头:客户端浏览器告诉服务器一些信息
		格式:“请求头名称: 请求头值”
		* 常见的请求头:
			1. User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息
				* 可以在服务器端获取该头的信息,解决浏览器的兼容性问题

			2. Referer:http://localhost/login.html
				* 告诉服务器,我(当前请求)从哪里来?
					* 作用:
						1. 防盗链:
						2. 统计工作:
	3. 请求空行
		空行,就是用于分割POST请求的请求头,和请求体的。(Get请求没有请求空行和请求体)
	4. 请求体(正文)* 封装POST请求消息的请求参数的。(Get请求没有请求空行和请求体)

2.HTTP响应消息数据格式

在这里插入图片描述

2. 响应消息:服务器端发送给客户端的数据
	* 数据格式:
		1. 响应行
			1. 组成:协议/版本 响应状态码 状态码描述
			
			  什么是响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态。
			  状态码都是3位数字 :
					1. 1xx:服务器就收客户端消息,但没有接受完成,等待一段时间后,发送1xx多状态码
					2. 2xx:成功。代表:200
					3. 3xx:重定向。代表:302(重定向)304(访问缓存)
					       	302:浏览器访问A资源,A资源发了个302(重定向)说我办不了你找C去吧。
					       	304:浏览器访问了一张图片并把它缓存下来,当它再次访问这张图片时该图片就会发出304表示你本地有缓冲,你从缓冲里面找吧
					5. 4xx:客户端错误。
						* 代表:
							* 404(请求路径没有对应的资源) 
							* 405:请求方式没有对应的doXxx方法(你代码里面删掉了doGet方法,你启动servlet,浏览器访问该页面就会报错为4056. 5xx:服务器端错误。代表:500(服务器内部出现异常)
		2. 响应头:
			1. 格式:头名称: 值
			2. 常见的响应头:
				1. Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式
				2. Content-disposition:服务器告诉客户端以什么格式打开响应体数据
					* 值:
						* in-line:默认值,在当前页面内打开
						* attachment;filename=xxx:以附件形式打开响应体。文件下载
		3. 响应空行
		4. 响应体:传输的数据

三、request的功能

1.获取路径相关
request.getContextPath()  /day14
request.getRequestURI()   /day14/demo1
request.getRequestURL()   http://localhost/day14/demo1

2. 获取请求头数据
request.getHeader("user-agent")
request.getHeaderNames():获取所有的请求头名称

3.获取请求参数
request.getParameter("username");
request.getParameterValues("hobby");
request.getParameterNames();
request.getParameterMap();

4.设置编码:
* get方式:tomcat 8 已经将get方式乱码问题解决了
* post方式:会乱码,需要request.setCharacterEncoding("utf-8");
* 设置了编码以后request.getParameter("username");//获取到的username是“张三”也不会乱码了

5.请求转发
你可以看到request的主要功能都是获取get方法(获取请求头、获取参数、获取请求体等等)
一旦要是出现了set方法那就是要走人了(先setAttribute,然后就是拿着属性转发走了)
request.setAttribute("msg","hello");
request.getAttitude("msg");
request.removeAttribute("msg");
request.getRequestDispatcher("/requestDemo9").forward(request,response);

1. 获取请求消息数据

原文中有很多,以下是我提炼出的需要你重点掌握的几个:

	1. 获取请求消息数据
		1. 获取请求行数据
			* 请求行的格式:GET /day14/demo1?name=zhangsan HTTP/1.1
			* 方法:
				1. (*重点*)获取虚拟目录:/day14
					* String getContextPath()
				2. (*重点*)获取请求URI:/day14/demo1
					* String getRequestURI():		/day14/demo1
					* StringBuffer getRequestURL()  :http://localhost/day14/demo1

					* URL:统一资源定位符 : http://localhost/day14/demo1	
					* URI:统一资源标识符 : /day14/demo1	
					* URI相当于“共和国”,URL相当于“中华人民共和国”,URI的范围要大于URL的范围
				
		2. 获取请求头数据
			* 方法:
				* (*重点*)String getHeader(String name):通过请求头的名称获取请求头的值
				* Enumeration<String> getHeaderNames():获取所有的请求头名称

1. 获取请求行数据实例

//访问网址"localhost:8080/day14/requestDemo1?name=zhangsan"

@WebServlet("/requestDemo1")  

        //2.(*)获取虚拟目录:/day14
        String contextPath = request.getContextPath();

        //5.(*)获取请求URI:/day14/demo1
        String requestURI = request.getRequestURI();
        StringBuffer requestURL = request.getRequestURL();

2. 1获取请求头数据实例1

@WebServlet("/requestDemo3")

        //演示获取请求头数据:user-agent
        String agent = request.getHeader("user-agent");
        //判断agent的浏览器版本
        if(agent.contains("Chrome")){
            //谷歌
            System.out.println("谷歌来了...");
        }else if(agent.contains("Firefox")){
            //火狐
            System.out.println("火狐来了...");
        }
//访问网址"localhost:8080/day14/requestDemo3
//输出“谷歌来了”

2. 2获取请求头数据实例2

@WebServlet("/requestDemo4")

        //演示获取请求头数据:referer
        String referer = request.getHeader("referer");
        System.out.println(referer);//http://localhost/day14/login.html

        //防盗链
        if(referer != null ){
            if(referer.contains("/day14")){
                //正常访问
                System.out.println("播放电影....");
                response.setContentType("text/html;charset=utf-8");
                response.getWriter().write("播放电影....");
            }else{
                //盗链
                System.out.println("想看电影吗?来优酷吧...");
                response.setContentType("text/html;charset=utf-8");
                response.getWriter().write("想看电影吗?来优酷吧...");
            }
        }
//访问网址"localhost:8080/day14/requestDemo4

2. 3获取请求头数据实例3

@WebServlet("/requestDemo2")

        //获取所有请求头名称
        Enumeration<String> headerNames = request.getHeaderNames();

        while(headerNames.hasMoreElements()){
            String name = headerNames.nextElement();
            //根据名称获取请求头的值
            String value = request.getHeader(name);
            System.out.println(name+"---"+value);
        }

2. 获取请求参数(重点*)

		1. 获取请求参数通用方式:不论get还是post请求方式都可以使用下列方法来获取请求参数
			1. String getParameter(String name):根据参数名称获取参数值    
							比如请求参数是username=zs&password=123,你调用getParameter(username)得到的就是zs
			2. String[] getParameterValues(String name):根据参数名称获取参数值的数组,经常用于复选框这种的
							像复选框你得到的请求参数是hobby=studey&hobby=game,你调用getParameterValues(hobby)得到的就是[study,game]
			4. Enumeration<String> getParameterNames():获取所有请求的参数名称
			5. Map<String,String[]> getParameterMap():获取所有参数的map集合

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

在这里插入图片描述
在这里插入图片描述

3. 获取请求参数中文乱码问题(重点*)

			* 中文乱码问题:
				* get方式:tomcat 8 已经将get方式乱码问题解决了
				* post方式:会乱码
					* 解决:在获取参数前,设置request的编码
					        request.setCharacterEncoding("utf-8");
@WebServlet("/requestDemo7")
//doGet里面:

        request.setCharacterEncoding("utf-8");
        String username = request.getParameter("username");//获取到的username是“张三”也不会乱码了

//doPost: 
        this.doPost(request,response);

4.请求转发(重点)

请求转发:一种在服务器内部的资源跳转方式
	1. 步骤:
		1. 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
		2. 使用RequestDispatcher对象来进行转发:forward(ServletRequest request, ServletResponse response) 

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

你可以看到request的主要功能都是获取get方法(获取请求头、获取参数、获取请求体等等)
一旦要是出现了set方法那就是要走人了(先setAttribute,然后就是拿着属性转发走了)
@WebServlet("/requestDemo8")
doPost:
        System.out.println("demo8888被访问了。。。");

        request.setAttribute("msg","hello");
        request.getRequestDispatcher("/requestDemo9").forward(request,response);
doGet:
        this.doPost(request,response);
@WebServlet("/requestDemo9")
doPost:
        Object msg = request.getAttribute("msg");
        System.out.println(msg);

        System.out.println("demo9999被访问了。。。");
doGet:
        this.doPost(request,response);

在这里插入图片描述

	2. 特点(面试常问!!):
		1. 浏览器地址栏路径不发生变化
		2. 只能转发到当前服务器内部资源中。
		3. 转发是一次请求

四、用户登录案例

Day04_用户登录案例(含BeanUtils的使用)
这个案例很重要,至少BeanUtils你得知道吧?

五、Response对象的功能

//设置状态码、请求头
response.setStatus(302);
response.setHeader("location","/day15/responseDemo2");

//设置编码,输出数据
response.setContentType("text/html;charset=utf-8");
ServletOutputStream sos = response.getOutputStream();
sos.write("你好".getBytes("utf-8"));

//完成重定向
response.sendRedirect("/day15/responseDemo2");


1.关于response

* 功能:设置响应消息
	1. 设置响应行
		1. 格式:HTTP/1.1 200 ok
		2. 方法:
			设置状态码:setStatus(int sc) 
	2. 设置响应头:
			setHeader(String name, String value) 
	3. 设置响应体:
		* 使用步骤:
			1. 获取输出流
				* 字符输出流:PrintWriter getWriter()

				* 字节输出流:ServletOutputStream getOutputStream()
			2. 使用输出流,将数据输出到客户端浏览器

2.完成重定向

	1. 完成重定向
		* 重定向:资源跳转的方式
		* 代码实现:
			//1. 设置状态码为302
	        response.setStatus(302);
	        //2.设置响应头location,告诉B资源的资源路径
	        response.setHeader("location","/day15/responseDemo2");
	        
	     * 简单的重定向方法替代上面的代码:
	        response.sendRedirect("/day15/responseDemo2");
@WebServlet("/responseDemo1")
doPost:
        System.out.println("demo1........");

       /*复杂的方法:
        response.setStatus(302);
        response.setHeader("location","/day15/responseDemo2");*/
        
        //动态获取虚拟目录
        String contextPath = request.getContextPath();

        //简单的重定向方法
        response.sendRedirect(contextPath+"/responseDemo2");
        
doGet:
        this.doPost(request,response);
@WebServlet("/responseDemo2")
doPost:
        System.out.println("demo2222222........");
doGet:
        this.doPost(request,response);

3.重定向的特点:

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

4.路径的写法

		* 路径写法:
			1. 路径分类
				1. 相对路径:通过相对路径不可以确定唯一资源
					* 如:./index.html
					* 不以/开头,以.开头路径

					* 规则:找到当前资源和目标资源之间的相对位置关系
						* ./:当前目录
						* ../:后退一级目录
				2. 绝对路径:通过绝对路径可以确定唯一资源
					* 如:http://localhost/day15/responseDemo2
						(事实上/day15/responseDemo2就是绝对路径,因为http是协议,localhost是主机,都都可以省略)
					*/开头的路径(如/day15/responseDemo2)

					* 规则:判断定义的路径是给谁用的?判断请求将来从哪儿发出
						* 给客户端浏览器使用:需要加虚拟目录(项目的访问路径)
							举例:<a>标签里的超链接路径,<form>表单路径,重定向都是给客户端用的,都需要虚拟路径
							* 建议虚拟目录动态获取:request.getContextPath()
						* 给服务器使用:不需要加虚拟目录
							* 举例:转发路径(转发路径就是给服务器用的,就不需要用虚拟目录)
							
						*你站在3班门口喊张三,那么只会三班的张三出来;你站在走廊里喊张三,那么三班和四班的张三都可能出来
						 所以站在走廊里喊张三需要加上“三班的张三”才能喊出那个人
						 给客户端浏览器使用就需要加上虚拟目录也是这个道理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.服务器输出数据到浏览器

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

	1.服务器输出字符数据到浏览器:
		* 步骤:
			1. 获取字符输出流
			2. 输出数据

		* 注意:
			* 乱码问题:
				//简单的形式,设置编码,是在获取流之前设置
    			response.setContentType("text/html;charset=utf-8");
@WebServlet("/responseDemo4")
doPost:
        //简单的形式,设置编码
        response.setContentType("text/html;charset=utf-8");

        //1.获取字符输出流
        PrintWriter pw = response.getWriter();
        //2.输出数据
        pw.write("你好啊啊啊 response");

doGet:
        this.doPost(request,response);

2. 服务器输出字节数据到浏览器

	2. 服务器输出字节数据到浏览器
		* 步骤:
			1. 获取字节输出流
			2. 输出数据
@WebServlet("/responseDemo5")
doPost:
        response.setContentType("text/html;charset=utf-8");

        //1.获取字节输出流
        ServletOutputStream sos = response.getOutputStream();
        //2.输出数据
        sos.write("你好".getBytes("utf-8"));

doGet:
        this.doPost(request,response);

六、ServletContext对象:

ServletContext context = request.getServletContext();
ServletContext context = this.getServletContext();

context.setAttribute("msg","haha");
context.getAttribute("msg");
context.removeAttribute("msg");

context.getMimeType("a.jpg");

context.getRealPath("/WEB-INF/c.txt");
1. 概念:代表整个web应用,可以和程序的容器(服务器)来通信
2. 获取:
	1. 通过request对象获取
		request.getServletContext();
	2. 通过HttpServlet获取
		this.getServletContext();
3. 功能:
	1. 获取MIME类型:
		* MIME类型:在互联网通信过程中定义的一种文件数据类型
			* 格式: 大类型/小类型   如:text/html	如:image/jpeg
		* 获取:String getMimeType(String file)  
	2. ServletContext对象是域对象----可以共享数据
		1. setAttribute(String name,Object value)
		2. getAttribute(String name)
		3. removeAttribute(String name)

		* ServletContext对象范围:所有用户所有请求的数据
	3. 获取文件的真实(服务器)路径
		1. 方法:String getRealPath(String path)  
			 String b = context.getRealPath("/b.txt");//web目录下资源访问
	
	        String c = context.getRealPath("/WEB-INF/c.txt");//WEB-INF目录下的资源访问
	
	        String a = context.getRealPath("/WEB-INF/classes/a.txt");//src目录下的资源访问

1.获取ServletContext

@WebServlet("/servletContextDemo1")
doPost:
        //1. 通过request对象获取
        ServletContext context1 = request.getServletContext();
        //2. 通过HttpServlet获取
        ServletContext context2 = this.getServletContext();

doGet:
        this.doPost(request,response);

2. 获取MIME类型:

@WebServlet("/servletContextDemo2")

        ServletContext context = this.getServletContext();

        String filename = "a.jpg";//image/jpeg

        String mimeType = context.getMimeType(filename);
        System.out.println(mimeType);

3.ServletContext对象是域对象----可以共享数据

@WebServlet("/servletContextDemo3")
doPost:
        ServletContext context = this.getServletContext();
        context.setAttribute("msg","haha");
@WebServlet("/servletContextDemo4")
        ServletContext context = this.getServletContext();
        Object msg = context.getAttribute("msg");
        System.out.println(msg);//haha

4.获取文件的真实(服务器)路径
在这里插入图片描述

七、文件下载案例

* 文件下载需求:
	1. 页面显示超链接
	2. 点击超链接后弹出下载提示框
		任何资源都必须弹出下载提示框,使用响应头设置资源的打开方式:content-disposition:attachment;filename=xxx
	3. 完成图片文件下载

* 注意:
设置了这个响应头之后,不管什么资源都不会在浏览器中打开了,而是以附件的形式弹出:
content-disposition:attachment;filename=xxx
* 步骤:
	1. 写html页面,编辑超链接href属性,指向Servlet,传递资源名称filename
	2. 定义Servlet
		1. 获取文件名称
		2. 使用字节输入流加载文件进内存
		3. 指定response的响应头: content-disposition:attachment;filename=xxx
		4. 将数据写出到response输出流

1. 写html页面
在这里插入图片描述

    <a href="/day15/downloadServlet?filename=九尾.jpg">图片1</a>
    
    //编辑超链接href属性,指向Servlet,传递资源名称filename

    <a href="/day15/downloadServlet?filename=1.avi">视频</a>

2.解决中文文件名问题
在这里插入图片描述
3.编写DownloadServlet

@WebServlet("/downloadServlet")
public class DownloadServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //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

        //解决中文文件名问题
        //1.获取user-agent请求头、
        String agent = request.getHeader("user-agent");
        //2.使用工具类方法编码文件名即可
        filename = DownLoadUtils.getFileName(agent, filename);//把"user-agent"和filename传进去就可以返回一个新的filename

        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();


    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }
}

八、Cookie

response.setContentType("text/html;charset=utf-8");
Cookie c = new Cookie("msg","hello");
c.setPath("/");
c.setMaxAge(30);
c.setDomain(".baidu.com");
response.addCookie(c);

Cookie[] cs = request.getCookies();
if(cs != null){
    for (Cookie c : cs) {
        String name = c.getName();
        String value = c.getValue();
        System.out.println(name+":"+value);
    }
}
1. 概念:客户端会话技术,将数据保存到客户端

2. 快速入门:
	* 使用步骤:
		1. 创建Cookie对象,绑定数据
			* new Cookie(String name, String value) 
		2. 发送Cookie对象
			* response.addCookie(Cookie cookie) 
		3. 获取Cookie,拿到数据
			* Cookie[]  request.getCookies() 
3. 实现原理
	* 基于响应头set-cookie和请求头cookie实现

4. cookie的细节
	1. 一次可不可以发送多个cookie?
		* 可以
		* 可以创建多个Cookie对象,使用response调用多次addCookie方法发送cookie即可。
	2. cookie在浏览器中保存多长时间?
		1. 默认情况下,当浏览器关闭后,Cookie数据被销毁
		2. 持久化存储:
			* setMaxAge(int seconds)
				1. 正数:将Cookie数据写到硬盘的文件中。持久化存储。并指定cookie存活时间,时间到后,cookie文件自动失效
				2. 负数:默认值
				3. 零:删除cookie信息
	3. cookie能不能存中文?
		* 在tomcat 8 之后,cookie支持中文数据。特殊字符还是不支持,建议使用URL编码存储,URL解码解析
			str = URLEncoder.encode(str,"utf-8");
            Cookie cookie = new Cookie("lastTime",str);
            response.addCookie(cookie);
	4. cookie共享问题?
		1. 假设在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?
			* 默认情况下cookie不能共享(/day15获取不到/day16的数据)
				cookie1.setPath("/day16");就意味着只有虚拟目录为/day16下的才能访问
				cookie1.setPath("/");管它什么/day15还是/day16都可以访问,因为它们都在同一个tomcat上
			* setPath(String path):设置cookie的获取范围。默认情况下,设置当前的虚拟目录
				* 如果要共享,则可以将path设置为"/" 
		2. 不同的tomcat服务器间cookie共享问题?
			* setDomain(String path):如果设置一级域名相同,那么多个服务器之间cookie可以共享
				比如setDomain(".baidu.com"),那么tieba.baidu.com和news.baidu.com中cookie可以共享
5. Cookie的特点和作用
	1. cookie存储数据在客户端浏览器
	2. 浏览器对于单个cookie 的大小有限制(4kb) 以及 对同一个域名下的总cookie数量也有限制(20)

	* 作用:
		1. cookie一般用于存出少量的不太敏感的数据(你想,存储数据在客户端浏览器所以不安全)
		2. 在不登录的情况下,完成服务器对客户端的身份识别

快速入门

@WebServlet("/cookieDemo1")
        //1.创建Cookie对象
        Cookie c = new Cookie("msg","hello");
        //2.发送Cookie
        response.addCookie(c);
@WebServlet("/cookieDemo2")
       //3. 获取Cookie
        Cookie[] cs = request.getCookies();
        //获取数据,遍历Cookies
        if(cs != null){
            for (Cookie c : cs) {
                String name = c.getName();
                String value = c.getValue();
                System.out.println(name+":"+value);
            }
        }

一次发送多个cookie

@WebServlet("/cookieDemo3")

        //1.创建Cookie对象
        Cookie c1 = new Cookie("msg","hello");
        Cookie c2 = new Cookie("name","zhangsan");
        //2.发送Cookie
        response.addCookie(c1);
        response.addCookie(c2);

cookie持久化存储

@WebServlet("/cookieDemo4")
        //1.创建Cookie对象
        Cookie c1 = new Cookie("msg","setMaxAge");
        
        //2.设置cookie的存活时间
        //c1.setMaxAge(30);//将cookie持久化到硬盘,30秒后会自动删除cookie文件(意味着30s后你就访问不到了)
        //c1.setMaxAge(-1);
        //c1.setMaxAge(0);//手动删除Cookie,意味着这个代码一执行你就访问不到了
        
        //3.发送Cookie
        response.addCookie(c1);

setPath("/")

@WebServlet("/cookieDemo5")

        //1.创建Cookie对象
        Cookie c1 = new Cookie("msg","你好");
        
        //设置path,让当前服务器下部署的所有项目共享Cookie信息
        c1.setPath("/");
        
        //3.发送Cookie
        response.addCookie(c1);

cookie小案例

	1. 需求:
		1. 访问一个Servlet,如果是第一次访问,则提示:您好,欢迎您首次访问。
		2. 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:显示时间字符串
@WebServlet("/cookieTest")
public class CookieTest extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //设置响应的消息体的数据格式以及编码
        response.setContentType("text/html;charset=utf-8");

        //1.获取所有Cookie
        Cookie[] cookies = request.getCookies();
        boolean flag = false;//表示没有为lastTime的cookie
        //2.遍历cookie数组
        if(cookies != null && cookies.length > 0){
            for (Cookie cookie : cookies) {
                //3.获取cookie的名称
                String name = cookie.getName();
                //4.判断名称是否是:lastTime
                if("lastTime".equals(name)){
                    //有该Cookie,不是第一次访问

                    flag = true;//有lastTime的cookie

                    //设置Cookie的value
                    //获取当前时间的字符串,重新设置Cookie的值,重新发送cookie
                    Date date  = new Date();
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
                    String str_date = sdf.format(date);
                    //存数据之前应该使用URL编码将数据转换,这样cookie才能支持
                    str_date = URLEncoder.encode(str_date,"utf-8");
                    cookie.setValue(str_date);//因为你有cookie而且cookie的键为lastTime值咱不知道,所以你必须重新赋值
                    //设置cookie的存活时间(即使你关掉浏览器重新访问依旧保留着cookie信息)
                    cookie.setMaxAge(60 * 60 * 24 * 30);//一个月
                    response.addCookie(cookie);

                    //响应数据
                    //获取Cookie的value,时间
                    String value = cookie.getValue();
                    //得进行URL解码,要不然你也看不懂啊
                    value = URLDecoder.decode(value,"utf-8");
                    response.getWriter().write("<h1>欢迎回来,您上次访问时间为:"+value+"</h1>");


                    break;

                }
            }
        }


        if(cookies == null || cookies.length == 0 || flag == false){
            //没有,第一次访问

            //设置Cookie的value
            //获取当前时间的字符串,重新设置Cookie的值,重新发送cookie
            Date date  = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
            String str_date = sdf.format(date);
            //存数据之前应该使用URL编码将数据转换,这样cookie才能支持
            str_date = URLEncoder.encode(str_date,"utf-8");

            Cookie cookie = new Cookie("lastTime",str_date);
            //设置cookie的存活时间
            cookie.setMaxAge(60 * 60 * 24 * 30);//一个月
            response.addCookie(cookie);

            response.getWriter().write("<h1>您好,欢迎您首次访问</h1>");
        }


    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

九、jsp

1. 概念:
	* Java Server Pages: java服务器端页面
		* 可以理解为:一个特殊的页面,其中既可以指定定义html标签,又可以定义java代码
		* 用于简化书写!!!
2. 原理
	* JSP本质上就是一个Servlet

3. JSP的脚本:JSP定义Java代码的方式
	1. <%  代码 %>:定义的java代码,会被解析到service方法中。service方法中可以定义什么,该脚本中就可以定义什么。
	2. <%! 代码 %>:定义的java代码,会被解析到servlet的成员变量的位置。我们很少使用这个,因为之前学过servlet尽量不要定义成员变量。
	3. <%= 代码 %>:定义的java代码,会输出到页面上。输出语句中可以定义什么,该脚本中就可以定义什么。	

4. JSP的内置对象:
	* 在jsp页面中不需要获取和创建,可以直接使用的对象
	* jsp一共有9个内置对象。今天学习3个:
		* request
		* response
		* out:字符输出流对象。可以将数据输出到页面上。和response.getWriter()类似
			* response.getWriter()和out.write()的区别:
				response.getWriter()数据输出永远在out.write()之前,不过我们一般不使用response.getWriter()
				out.write()是由上到下按顺序执行的,经常使用
			

在这里插入图片描述

十、session

HttpSession session = request.getSession();
session.setAttribute("msg","hello session");
session.getAttribute("msg");
session.removeAttribute("msg");

1. 概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。HttpSession
2. 快速入门:
	1. 获取HttpSession对象:
		HttpSession session = request.getSession();
	2. 使用HttpSession对象:
		Object getAttribute(String name)  
		void setAttribute(String name, Object value)
		void removeAttribute(String name)  
		

3. 原理
	* Session的实现是依赖于Cookie的。
4. 细节:
	1. 当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
		* 默认情况下。不是。(当你关闭浏览器后一次对话就结束了)
		* 如果需要相同,则可以创建Cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存。
			 Cookie c = new Cookie("JSESSIONID",session.getId());
	         c.setMaxAge(60*60);
	         response.addCookie(c);

	2. 客户端不关闭,服务器关闭后,两次获取的session是同一个吗?
		* 不是同一个。

			服务器重启导致session对象变化了,那么数据就会丢失,要确保数据不丢失。tomcat自动完成以下工作
			* session的钝化:
				* 在服务器正常关闭之前,将session对象系列化到硬盘上
			* session的活化:
				* 在服务器启动后,将session文件转化为内存中的session对象即可。
			*这一切都不需要你操心,tomcat会自动完成上面的操作,数据就不会丢失
			
	3. session什么时候被销毁?
		1. 服务器关闭
		2. session对象调用invalidate()3. session默认失效时间 30分钟(也就是打开一个网站30分钟没有做任何操作,session会失效,你需要重新登录)
			选择性配置修改session默认失效时间
			<session-config>
		        <session-timeout>30</session-timeout>
		    </session-config>

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

	* session与Cookie的区别:
		1. session存储数据在服务器端,Cookie在客户端
		2. session没有数据大小限制,Cookie有
		3. session数据安全,Cookie相对于不安全

快速入门

@WebServlet("/sessionDemo1")

        //使用session共享数据
        //1.获取session
        HttpSession session = request.getSession();
        //2.存储数据
        session.setAttribute("msg","hello session");
@WebServlet("/sessionDemo2")
        //1.获取session
        HttpSession session = request.getSession();
        //2.获取数据
        Object msg = session.getAttribute("msg");
        System.out.println(msg);

期望客户端关闭、服务器不关闭,session也能相同

@WebServlet("/sessionDemo3")

        //1.获取session
        HttpSession session = request.getSession();

        //期望客户端关闭后,session也能相同
        Cookie c = new Cookie("JSESSIONID",session.getId());
        c.setMaxAge(60*60);//一个小时
        response.addCookie(c);

十一、验证码案例—session的使用

1. 案例需求:
	1. 访问带有验证码的登录页面login.jsp
	2. 用户输入用户名,密码以及验证码。
		* 如果用户名和密码输入有误,跳转登录页面,提示:用户名或密码错误
		* 如果验证码输入有误,跳转登录页面,提示:验证码错误
		* 如果全部输入正确,则跳转到主页success.jsp,显示:用户名,欢迎您

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
login.jsp(仅供了解)
在这里插入图片描述

success.jsp(仅供了解)
在这里插入图片描述
CheckCode.servlet(仅供了解)
在这里插入图片描述
Login.Servlet(核心,重点!!!)

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.设置request编码
        request.setCharacterEncoding("utf-8");
        //2.获取参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String checkCode = request.getParameter("checkCode");
        //3.先获取生成的验证码
        HttpSession session = request.getSession();
        String checkCode_session = (String) session.getAttribute("checkCode_session");
        //3.先判断验证码是否正确
        if(checkCode_session.equalsIgnoreCase(checkCode)){
            //忽略大小写比较用户输入的验证码和生成的验证码
            
            //验证码正确后判断用户名和密码是否一致
            if("zhangsan".equals(username) && "123".equals(password)){//本来该用数据库实现
                //登录成功,存储信息,用户信息
                session.setAttribute("user",username);
                //重定向到success.jsp(重定向需要加虚拟目录)
                response.sendRedirect(request.getContextPath()+"/success.jsp");
            }else{
                //登录失败,存储提示信息到request
                request.setAttribute("login_error","用户名或密码错误");
                //转发到登录页面(转发不需要虚拟目录)
                request.getRequestDispatcher("/login.jsp").forward(request,response);
            }


        }else{
            //验证码不一致
            //存储提示信息到request
            request.setAttribute("cc_error","验证码错误");
            //转发到登录页面
            request.getRequestDispatcher("/login.jsp").forward(request,response);

        }

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

十二、JSP续学

1.指令

1. 指令
	* 作用:用于配置JSP页面,导入资源文件
	* 格式:
		<%@ 指令名称 属性名1=属性值1 属性名2=属性值2 ... %>
	* 分类:
		1. page		: 配置JSP页面的
			* contentType等同于之前学的response.setContentType(),它有两个含义:
				1. 设置响应体的mime类型以及字符集
				2. 设置当前jsp页面的编码(只能是高级的IDE才能生效,如果使用低级工具,则需要设置pageEncoding属性设置当前页面的字符集)
					<%@ page contentType="text/html;charset=UTF-8" pageEncoding="GBK" %>
			* import:导包
			* errorPage:当前页面发生异常后,会自动跳转到指定的错误页面
						<%@ errorPage="error.jsp" %>
			* isErrorPage:标识当前也是是否是错误页面。
				* true:是,可以使用内置对象exception
				* false:否。默认值。不可以使用内置对象exception
				也就是说只有<%@ isErrorPage="true"  %>你才能使用String message = exception.getMessage();out.print(message);这段代码
		2. include	:将来很多页面的一部分内容是一样的,我们可以编写一个页面然后让其它页面包含这个页面就可以了,这就不用你重复编写了。
			* <%@include file="top.jsp"%>
		3. taglib	: 导入资源
			* <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
				* prefix:前缀,自定义的,像定义成什么就定义成什么

2.注释

1. html注释:
	<!-- -->:只能注释html代码片段
2. jsp注释:推荐使用
	<%-- --%>:可以注释所有

3.内置对象(面试重点)

3. 内置对象
	* 在jsp页面中不需要创建,直接使用的对象
	* 一共有9个:
			变量名					真实类型						作用
		* pageContext				PageContext					共享当前页面的资源,还可以获取其他八个内置对象
		* request					HttpServletRequest			共享一次请求访问的多个资源(如:转发)
		* session					HttpSession					共享一次会话的多个请求间的资源(如:重定向等)
		* application				ServletContext				共享所有用户间共享资源

		* response					HttpServletResponse			响应对象
		* page						Object						当前页面(当前Servlet)的对象,可以理解为this
		* out						JspWriter					输出对象,数据输出到页面上
		* config					ServletConfig				Servlet的配置对象
		* exception					Throwable					异常对象

pageContext共享当前页面的资源
在这里插入图片描述
pageContext还可以获取其他八个内置对象
在这里插入图片描述

exception对象
在这里插入图片描述

十三、EL表达式

1. 概念:Expression Language 表达式语言
2. 作用:替换和简化jsp页面中java代码的编写
3. 语法:${表达式}
4. 注意:
	* jsp默认支持el表达式的。如果要忽略el表达式
		1. 设置jsp中page指令中:isELIgnored="true" 忽略当前jsp页面中所有的el表达式
		2. \${表达式} :忽略当前这个el表达式
5. 使用:
	1. 运算:
		* 运算符:
			1. "加减乘除"中除可以用/或div表示,取余可以用%或mod表示
			2. 逻辑运算符: &&(and) ||(or) !(not)
			3. 空运算符: empty (重点)
				* 功能:用于判断字符串、集合、数组对象是否为null或者长度是否为0
				* ${empty list}:判断字符串、集合、数组对象是否为null或者长度为0
				* ${not empty str}:表示判断字符串、集合、数组对象是否不为null 并且 长度>0
	2. 获取值(重点)
		1. el表达式只能从域对象中获取值
		2. 语法:
			1. ${域名称.键名}:从指定域中获取指定键的值
				* 域名称:
					1. pageScope		--> 从pageContext对象中获取值
					2. requestScope 	--> 从request对象中获取值
					3. sessionScope 	--> 从session对象中获取值
					4. applicationScope --> 从application(ServletContext)对象中获取值
				* 举例:在request域中存储了name=张三
						获取张三:${requestScope.name}

			2. ${键名}:表示依次从最小的域中查找是否有该键对应的值,直到找到为止。
						你写了${name}它就会从pageScope中找键为name的,找不到就继续在requestScope中找,,,找到为止
			3. 获取对象、List集合、Map集合的值
			
				1. 获取对象:${域名称.键名.属性名}
					* 本质上会去调用对象的getter方法

				2. 获取List集合:${域名称.键名[索引]}

				3. 获取Map集合:
					* ${域名称.键名.key名称}
					* ${域名称.键名["key名称"]}
	3. 隐式对象:
		* el表达式中有11个隐式对象
		* pageContext:
			* 获取jsp其他八个内置对象
				* ${pageContext.request.contextPath}:动态获取虚拟目录

忽略el表达式
在这里插入图片描述
运算符:
在这里插入图片描述
获取值(重点)
在这里插入图片描述
在这里插入图片描述

获取对象(重点)
对象的属性是是什么?请参考Day04_用户登录案例的“11.关于BeanUtils”

在这里插入图片描述
在这里插入图片描述

<%@ page import="cn.itcast.domain.User" %>
<%@ page import="java.util.*" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>el获取数据</title>
</head>
<body>

    <%
        User user = new User();
        user.setName("张三");
        user.setAge(23);
        user.setBirthday(new Date());

        request.setAttribute("u",user);
    %>

<h3>el获取对象中的值</h3>

    ${requestScope.u}<br>   //这句代码只能获取到u的地址值,要想获取到值必须通过对象的属性获取

    //通过的是对象的属性来获取
    ${requestScope.u.name}<br>  //requestScope.u就是找request域中有没有一个u的键,找到它对应的对象,然后通过这个对象调用getname方法获取name值
    ${u.age}<br>
    ${u.birthday}<br>
    ${u.birthday.month}<br>  //这是美国的日期,美国的3月就是我们的4月,那么如果你想获取中国的日期格式怎么办呢?

    ${u.birStr}<br>   //必须有一个自己写的getBirStr()方法,要不然会报错
</body>
</html>

获取list集合、map集合的值(重点)
在这里插入图片描述
空运算符
在这里插入图片描述
隐式对象
在这里插入图片描述

十四、JSTL

1. 概念:JavaServer Pages Tag Library  JSP标准标签库
	*用于简化和替换jsp页面上的java代码		

2. 使用步骤:
	1. 导入jstl相关jar包
	2. 引入标签库:taglib指令:  <%@ taglib %>
	3. 使用标签

3. 常用的JSTL标签(今天只学习三个)
	1. if:相当于java代码的if语句
		1. 属性:
            * test 必须属性,接受boolean表达式
                * 如果表达式为true,则显示if标签体内容,如果为false,则不显示标签体内容
                * 一般情况下,test属性值会结合el表达式一起使用
   		 2. 注意:
       		 * c:if标签没有else情况,想要else情况,则可以在定义一个c:if标签
	2. choose:相当于java代码的switch语句
		1. 使用choose标签声明         			相当于switch声明
        2. 使用when标签做判断         			相当于case
        3. 使用otherwise标签做其他情况的声明    	相当于default

	3. foreach:相当于java代码的for语句
        1. 完成重复的操作
            for(int i = 0; i < 10; i ++){

            }
            * 属性:
                begin:开始值。
                end:结束值。
                var:临时变量。
                step:步长。
                varStatus:循环状态对象
                    index:容器中元素的索引,从0开始
                    count:循环次数,从1开始
                    
			例如:<c:forEach begin="1" end="10" var="i" step="2" varStatus="s">
				  </c:forEach>
			
        2. 遍历容器
            List<User> list;
            for(User user : list){

            }

            * 属性:
                items:容器对象
                var:容器中元素的临时变量
                varStatus:循环状态对象
                    index:容器中元素的索引,从0开始
                    count:循环次数,从1开始
                    
				例如:<c:forEach items="${list}" var="str" varStatus="s">
    				  </c:forEach>

if标签
在这里插入图片描述
choose标签
在这里插入图片描述
foreeach标签
在这里插入图片描述
JSTL小练习

需求:在request域中有一个存有User对象的List集合。需要使用jstl+el将list集合数据展示到jsp页面的表格table中
表格中如果是奇数行就让它是绿色,如果是偶数行就让他是红色

在这里插入图片描述

在这里插入图片描述

十五、三层架构:软件设计架构

1. 界面层(表示层):用户看的得界面。用户可以通过界面上的组件和服务器进行交互
2. 业务逻辑层:处理业务逻辑的。
3. 数据访问层:操作数据存储文件。

在这里插入图片描述

十六、用户信息列表展示

这个案例相当重要,它综合了所有知识。

Day09_用户信息列表展示

感谢浏览和收藏

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BlackTurn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值