12.Javaweb

Javaweb

一.tomcat服务器

1.下载tomcat压缩包

https://tomcat.apache.org/download-90.cgi
在这里插入图片描述

2.tomcat文件结构

在这里插入图片描述

3.启动,关闭tomcat服务器

在这里插入图片描述

4.tomcat配置

在这里插入图片描述
server.xml文件可以配置启动的端口号:tomcat的默认端口号为:8080,mysql:3306 http:80,https:443
在这里插入图片描述
可以配置主机名称:
默认主机名为: localhost —>127.0.0.1(本地DNS域名解析)
在这里插入图片描述
例如如果改name=“www.123.com”,则www.123.com应映射到127.0.0.1。这样可以通过
www.123.com:8080访问到tomcat的webapps网站。
修改映射地址的文件:C:\Windows\System32\drivers\etc下的hosts文件在这里插入图片描述
在这里插入图片描述

二.HTTP

1、什么是HTTP

(超文本传输协议)是一个简单的请求-响应协议,它通常运行在TCP之上。
https(443端口):安全版的http

2、两个时代

HTTP/1.0:客户端可以与web服务器连接后,只能获得一个web资源,获取完资源就断开连接
HTTP/1.1:客户端可以与web服务器连接后,可以获得多个web资源,获取完资源不会断开资源。

3、http请求

客户端发请求(Request)给服务器
搜索百度的请求头部分信息:

Request URL: https://www.baidu.com/  请求地址
Request Method: GET    //请求方式get/post
Status Code:200 OK    //状态码
Remote(远程) Address:14.215.177.38:443//远程ip地址

Accept:text/html  //支持的数据类型
Accept-Encoding:gzip, deflate, br  //支持的编码格式
Accept-Language:zh-CN,zh;q=0.9//语言
Cache-Control:max-age=0//缓存控制
Connection:keep-alive  //是否长连接

请求行:
请求行中的请求方式:Get,Post,HEAD,DELETE,PUT,TRACT…
get:请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但高效
post:请求能够携带的参数没有限制,大小没有限制,不会在浏览器的URL地址栏显示数据内容,安全,但不高效。

4、http响应

服务器给客户端作出响应(Response)
搜索百度的响应头部分信息:

Cache-Control:private    缓存控制
Connection:Keep-Alive    连接
Content-Encoding:gzip    编码
Content-Type:text/html   类型  

1)、响应体

Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码格式  GBK   UTF-8   GB2312  ISO8859-1
Accept-Language:告诉浏览器,它的语言环境Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
HOST:主机....
Refresh:告诉客户端,多久刷新一次;Location:让网页重新定位;
Location: 让网页重新定位

2)、响应状态码

200:   请求响应成功
3xx:   请求重定向
4xx:   如找不到资源(404)
5xx:   如服务器代码错误(500) 网关错误(502)

三.Maven

我为什么要学习这个技术?1.在Javaweb开发中,需要使用大量的jar包,我们手动去导入;2.如何能够让一个东西自动帮我导入和配置这个jar包。由此,Maven项目架构管理工具诞生了!
Maven记住约定大于配置(项目目录结构按照规范来)

1.下载

在这里插入图片描述
下载完成后,解压即可;

2.Maven环境变量配置

在我们的系统环境变量中配置如下配置:
M2_HOME:maven目录下的bin目录
MAVEN_HOME:maven的目录
在系统的path中配置%MAVEN_HOME%\bin
在这里插入图片描述
在这里插入图片描述
测试环境变量配置成功:在这里插入图片描述

3.配置阿里云镜像

作用:加速我们的下载(比如自动导包的速度)
在Maven配置文件D:\Environment\apache-maven-3.8.1\conf\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>

在这里插入图片描述

4.创建本地仓库

作用:存放jar包

<localRepository>D:\Environment\apache-maven-3.8.1\maven-repo</localRepository>

在这里插入图片描述

5.IDEA中使用Maven

1.新建Maven工程项目
在这里插入图片描述
2.选择我们自己的Maven(3.8.1),同时选择配置文件及本地仓库路径
在这里插入图片描述
3.等待下载完依赖包到本地仓库中显示构建成功,并在本地仓库中看多了很多jar包。
在这里插入图片描述在这里插入图片描述

6.pom.xml文件

pom.xml是Maven的核心配置文件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
Maven由于约定大于配置,如果不按照约定在规定文件夹内创建对象的文件,会导致无法导出或则无法生效(比如我们自己写的配置文件如果乱放的话),解决方法:
在这里插入图片描述

7.web.xml版本修改

IDEA中Maven的web应用项目web.xml版本配置保持与tomcat的一致。(为了让环境达到最优)
原来:在这里插入图片描述
改为:
在这里插入图片描述

四.IDEA配置tomcat服务器

1.tomcat基本配置:

2.解决警告问题:

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

3.添加虚拟路径映射

启动tomcat打开的地址为http://localhost:8080/liqingfeng,既当前web项目的根路径。
在这里插入图片描述

五.Servlet

1.概念

Servlet就是sun公司开发动态web的一门技术
Sun在这些APi中提供一个接口叫做:Servlet,如果你想开发一个Servlet程序,只需要完成两个小步骤:

  • 1.编写一个类,实现Servlet接口 把开
  • 2.将写好的java类部署到web服务器中。
2.Servlet原理

执行原理:
Servlet是由Web服务器调用,web服务器在收到浏览器请求之后,会:
1. 当服务器接受到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径
2. 查找web.xml文件,是否有对应的标签体内容。
3. 如果有,则在找到对应的全类名
4. tomcat会将字节码文件加载进内存,并且创建其对象
5. 调用其方法
在这里插入图片描述
在这里插入图片描述

3.Mapping映射

在web.xml中需要将我们写的java类映射,如下,当请求localhost:8080/hello就会在服务器中找到com.kuang.servlet.HelloServlet这个类去执行其doGet或则doPost方法。

<!--注册Servlet-->
      <servlet>
          <servlet-name>hello</servlet-name>
          <servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
      </servlet>
      <!--Servlet的请求路径-->
      <servlet-mapping>
          <servlet-name>hello</servlet-name>
          <url-pattern>/hello</url-pattern>
      </servlet-mapping>

*:通配符。如下表示当请求localhost:8080/hello(*为空时) 或localhost:8080/hello/......(*为有值时)下的所有url路径就会在服务器中找到com.kuang.servlet.HelloServlet这个类去执行其doGet或则doPost方法。

	<servlet>
          <servlet-name>hello</servlet-name>
          <servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
      </servlet>
	 <servlet-mapping>
          <servlet-name>hello</servlet-name>
          <url-pattern>/hello/*</url-pattern>
      </servlet-mapping>
4.ServletContext

web服务器在启动的时候,它会为每个web应用程序都创建一个对应的ServletContext对象,它代表了当前的web应用;
getRealPath方法: 获取文件真实工作路径

 System.out.println(
 this.getServletContext().getRealPath("/WEB-INF/classes/db.properties")); 
//D:\Environment\apache-tomcat-9.0.48\webapps\digitalreview\WEB-INF\classes\db.properties

**getMimeType方法:**获取MIME类型
MIME类型:在互联网通信过程中定义的一种文件数据类型
格式: 大类型/小类型 (如:text/html,image/jpeg)

1)、共享数据
在一个servlet的servletContext 对象中添加一个属性,在另一个servlet的servletContext 获取该属性的值

public class Servletcontext1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();   //获取当前web应用的ServletContext对象,它表示当前web应用
        servletContext.setAttribute("username","王老五");  //给servletContext添加一个新属性值,其属性为username,值为王老五
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
public class Servletcontext2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();   //获取当前web应用的ServletContext对象,它表示当前web应用
        Object username = servletContext.getAttribute("username");  //获取存放在servletContext中的属性(username)的值

        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf-8");
        resp.getWriter().print("username:" + username);	//打印在页面上
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

web.xml配置该类映射

	<servlet>
        <servlet-name>setservletcontext</servlet-name>
        <servlet-class>com.liqingfeng.Servletcontext1</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>setservletcontext</servlet-name>
        <url-pattern>/setdata</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>getservletcontext</servlet-name>
        <servlet-class>com.liqingfeng.Servletcontext2</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>getservletcontext</servlet-name>
        <url-pattern>/getdata</url-pattern>
    </servlet-mapping>

2).请求转发
当请求http://localhost:8080/liqingfeng/rd时,会执行该类,然后会转发到http://localhost:8080/liqingfeng/getdata路径去执行那个路径所映射的类,但浏览器url地址栏一直显示http://localhost:8080/liqingfeng/rd

public class Requestdispatcher extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        System.out.println("进入了ServletDemo04");
        RequestDispatcher requestDispatcher = context.getRequestDispatcher("/getdata"); //请求转发的路径
        requestDispatcher.forward(req,resp); //调用forward实现请求转发;
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

web.xml配置该类映射

	<servlet>
        <servlet-name>requestdispatcher</servlet-name>
        <servlet-class>com.liqingfeng.Requestdispatcher</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>requestdispatcher</servlet-name>
        <url-pattern>/rd</url-pattern>
    </servlet-mapping>

3).资源文件读取
user.properties资源文件放在resources文件夹,在启动tomcat时会在target下的java-01-maven(当前web项目根路径)WEB-INF/classes下生成user.properties文件。
在这里插入图片描述

public class Readresource extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/user.properties"); //绝对路径,第一个/是"http://localhost:8080/liqingfeng/"
        System.out.println(is);
        Properties prop = new Properties();
        prop.load(is);
        String user = prop.getProperty("username");
        String pwd = prop.getProperty("password");

        resp.getWriter().print(user+":"+pwd);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

web.xml配置该类映射

	<servlet>
        <servlet-name>readresource</servlet-name>
        <servlet-class>com.liqingfeng.Readresource</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>readresource</servlet-name>
        <url-pattern>/read</url-pattern>
    </servlet-mapping>
5.Request

HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器, HTTP请求中的所有信息会被封装到HttpServletRequest,通过HttpServletRequest的方法,获得客户端的所有信息。
在request请求中存放的数据,生存期随着请求消失而消失,多个Servlet不能共享,除非这个请求一直在这几个Servlet中来回。
在ServletContext中存放的数据,生存期随着web应用关闭而消失,多个Servlet可以共享。
在这里插入图片描述
req.getParameter()和req.getAttribute()方法的区别:
getParameter() :该方法是用于客户端传递过来的参数,它的返回值类型永远是字符串类型这个赋值动作是有客户端完成的。
getAttribute():该方法是专用在请求传到服务器端后,在去使用其进行存取一些附加数据。它的返回类型永远是Object.
问题:
既然parameter和attribute都是传递参数,为什么不直接使用parameter呢?
原因:
1)从上面分析可以找到getParameter获取的是客户端发送的参数,而且在服务器端不能通过setParameter(key, value)来添加参数,因为没有这个函数,所以如果需要在服务器端进行跳转,并需要向下个页面发送新的参数时,则没法实现。但是attribute可以,可以通过setAttribute(),将值放入到request对象,然后在其他页面使用getAttribute获取对应的值,这样就达到一次请求可以在多个页面共享一些对象信息
2)parameter返回值是字符串,意味着不能传递其他的对象,如List,但是attribute则可以存放任意类型的Java对象
getContextPath(): 获取当前web项目的虚拟路径(即tomcat配置的web项目访问的根路径)
在这里插入图片描述

public class Request extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username"); //获取浏览器请求过来的参数值
        String[] hoppys = req.getParameterValues("hoppys"); //获取浏览器请求过来的参数值数组
        System.out.println(username);
        for (String hoppy : hoppys) {
            System.out.println(hoppy);
        }
        req.getRequestDispatcher("/login.jsp").forward(req,resp);//请求转发,/表示当前web项目的根路径
        request.setAttribute("list","对象"); //还可以往本次请求中加数据,该请求到了其他地方可以取这个属性值
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
	<servlet>
        <servlet-name>request</servlet-name>
        <servlet-class>com.liqingfeng.Request</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>request</servlet-name>
        <url-pattern>/req</url-pattern>
    </servlet-mapping>

当发送请求http://localhost:8080/liqingfeng/req?username=老李&hoppys=game&hoppys=java时,工作台打印:
在这里插入图片描述
同时跳转到http://localhost:8080/liqingfeng/login.jsp页面,但由于是请求转发,所以浏览器url地址栏不会变。
请求转发:req.getRequestDispatcher(String path).forward(req,resp)
1. 浏览器地址栏路径不发生变化
2. 只能转发到当前服务器内部资源中。(path就不能写当前服务器资源外的路径)
3. 转发是一次请求(通过set/getgetAttribute在请求中加入信息给转发的资源共享数据)

6.Response

web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的一个HttpServletResponse;

  • 如果要获取客户端请求过来的参数:找HttpServletRequest
  • 如果要给客户端响应一些信息:找HttpServletResponse
    在这里插入图片描述
    2)下载文件
    下载:从服务器下载资源到客户端用户
    上传:从客户端用户上传数据到服务器存储着
public class Response extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1. 要获取下载文件的路径
        String realPath = "C:\\Users\\秋天的思念\\Desktop\\Java\\Java web\\javaweb\\java-01-maven\\src\\main\\resources\\img\\img1.jpg";
        // 2. 下载的文件名是啥?
        String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
        System.out.println(realPath.lastIndexOf("\\"));//81
        // 3. 设置想办法让浏览器能够支持(Content-Disposition)下载我们需要的东西,中文文件名URLEncoder.encode编码,否则有可能乱码
        resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));
        //设置响应头ContentType,告诉浏览器本次响应体数据格式以及编码格式
        //resp.setHeader("ContentType","text/html;charset=utf-8");
        resp.setContentType("text/html;charset=utf-8");
        // 4. 获取下载文件的输入流
        FileInputStream in = new FileInputStream(realPath);
        // 5. 创建缓冲区
        int len = 0;
        byte[] buffer = new byte[1024];
        // 6. 获取OutputStream对象
        ServletOutputStream out = resp.getOutputStream();
        // 7. 将输入流的内容按照1024字节一次循环读取到buffer中,然后响应输出流输出到浏览器页面
        while ((len=in.read(buffer))>0){
            out.write(buffer,0,len);	//写到了响应体中
        }

        in.close();
        out.close();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

3)重定向
1. 地址栏发生变化
2. 重定向可以访问其他站点(服务器)的资源
3. 重定向是两次请求。不能使用request对象来共享数据

//重定向
public class SendRedirect extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("走到了SendRedirect类的doGet方法");
        resp.sendRedirect("/liqingfeng/sendRedirect.jsp");//重定向到http://localhost:8080/liqingfeng/sendRedirect.jsp
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
	<servlet>
        <servlet-name>sendredirect</servlet-name>
        <servlet-class>com.liqingfeng.SendRedirect</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>sendredirect</servlet-name>
        <url-pattern>/sd</url-pattern>
    </servlet-mapping>

在浏览器url地址栏输入http://localhost:8080/liqingfeng/sd,会走到SendRedirect类的doGet方法,然后重定向到http://localhost:8080/liqingfeng/sendRedirect.jsp

路径写法

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

					* 规则:找到当前资源和目标资源之间的相对位置关系
						* ./:当前目录
						* ../:后退一级目录
			2. 绝对路径:通过绝对路径可以确定唯一资源
					* 如:http://localhost/day15/responseDemo2		/day15/responseDemo2
					* 以/开头的路径

					* 规则:判断定义的路径是给谁用的?判断请求将来从哪儿发出
						* 给客户端浏览器使用:需要加虚拟目录(项目的访问路径):/day15/responseDemo2
							* 建议虚拟目录(/dat15)动态获取:request.getContextPath()
							* 如<a> , <form>, 重定向...
						* 给服务器使用:不需要加虚拟目录:/responseDemo2
							* 如请求转发的路径

六.Cookie、Session

会话:用户打开一个浏览器,访问web资源,最后关闭浏览器,这个过程可以称之为会话。
有状态会话:一个用户来过某个网站,下次再来该网站,还能识别该用户,称之为有状态会话。
cookie: 服务器端给客户端一个信件,客户端下次访问服务端带上信件就可以了。
所以cookie属于客户端技术 。
session: 服务器登记你来过了,下次你来的时候我来匹配你。
所以session属于服务器技术。

1.Cookie

客户端会话技术,将数据保存到客户端浏览器;浏览器发起请求的请求头中会包含cookie。服务器响应的响应头中会包含set-cookie
cookie只在当前浏览器有效,其他浏览器中不存在该cookie。
每个cookie只能保存一个键值对(name:value),而session可以保存对象及多个键值对,所以后面都是session用的多(而且cookie作用域只在当前页面,session作用域在整个浏览器)
响应头中会有set-cookie:键值对、键值对…
请求头会有cookie:键值对、键值对…

public class Cookies extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      //设置响应的消息体的数据格式以及编码  text/html:charset=utf-8
		        response.setContentType("text/html;charset=utf-8");
		        //1.请求头中有cookie,获取所有Cookie
		        Cookie[] cookies = request.getCookies();
		        boolean flag = false;//没有cookie为lastTime
		        //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,时间
		                    String value = cookie.getValue();
		                    System.out.println("解码前:"+value);
		                    //URL解码:
		                    value = URLDecoder.decode(value,"utf-8");
		                    System.out.println("解码后:"+value);
		                    response.getWriter().write("<h1>欢迎回来,您上次访问时间为:"+value+"</h1>");
 							//获取当前时间的字符串,重新设置Cookie的值,重新发送cookie
		                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
		                    String str_date = sdf.format(new Date());
		                    System.out.println("编码前:"+str_date);
		                    //URL编码
		                    str_date = URLEncoder.encode(str_date,"utf-8");
		                    System.out.println("编码后:"+str_date);
		                    cookie.setValue(str_date);
		                    //设置cookie的存活时间
		                    cookie.setMaxAge(60 * 60 * 24 * 30);//一个月
		                    response.addCookie(cookie);//添加到响应头中  cookie:键值对
		                    break;
		
		                }
		            }
		        }
				    if(cookies == null || cookies.length == 0 || flag == false){//没有,第一次访问,设置Cookie的value
		            //获取当前时间的字符串,重新设置Cookie的值,重新发送cookie
		            SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
		            String str_date = sdf.format(new Date());
		            System.out.println("编码前:"+str_date);
		            //URL编码
		            str_date = URLEncoder.encode(str_date,"utf-8");
		            System.out.println("编码后:"+str_date);
		            //创建新的cookie
		            Cookie cookie = new Cookie("lastTime",str_date);
		            //设置cookie的存活时间
		            cookie.setMaxAge(60 * 60 * 24 * 30);//一个月
		            //添加到响应头中  set-cookie:键值对
		            response.addCookie(cookie);
		            response.getWriter().write("<h1>您好,欢迎您首次访问</h1>");
	}
	
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<servlet>
        <servlet-name>cookie</servlet-name>
        <servlet-class>com.liqingfeng.Cookies</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>cookie</servlet-name>
        <url-pattern>/cookie</url-pattern>
    </servlet-mapping>

Cookie在浏览器中的存活时间:

		1. 默认情况下,当浏览器关闭后,Cookie被销毁
		2. 持久化存储:通过setMaxAge(int seconds)方法
				(1). seconds为正数:指定cookie存活时间,时间到后cookie自动被销毁(将Cookie数据写到硬盘的文件中,持久化存储)
				(2). seconds为负数:默认值(浏览器关闭cookie就被销毁)
			    (3). seconds为零:销毁该cookie

在上述情况下,若设置的cookie存活时间比较长,那么在此期间关闭浏览器,再打开浏览器,cookie仍然存在,直到存活时间到才被销毁。

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

2.Session

服务器端会话技术,在一次会话的多次请求间共享数据(多个servlet可以共享),将数据保存在服务器端的对象中。默认情况下关闭浏览器session被销毁,再次打开浏览器访问时session自动又被重新创建。 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在。
原理:
session依赖cookie实现。当浏览器发起请求,服务器给出的响应头中有set-cookie:JSESSIONID=xxxxxxxxx,并自动在服务器端创建该id的session对象,这样该浏览器在服务器断就有了唯一的session标识。再次访问服务器时,请求头中有cookie:JSESSIONID=xxxxxxxxx,服务器就会根据这个session的id找到是哪个浏览器的session对象。
所以,一个浏览器只有一个session(但可以有多个cookie),该浏览器只要访问服务器,保存在session中的数据就可以在servlet和jsp中共享。
Session和cookie的区别:

1. session存储数据在服务器端,Cookie在客户端
2. session没有数据大小限制、类型也无限制,Cookie有
3. session数据安全,Cookie相对于不安全
public class Sessions 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");

        //session不用我们创建,服务器会给每一个用户(浏览器)创建一个Session对象
        HttpSession session = req.getSession(); //获取session
        session.setAttribute("user",new Person("王老吉",new Random().nextInt(10)));   //往session中添加新的属性值(键值对)
        String sessionId = session.getId(); //获得session的id

        if(session.isNew()){    //判断session是否为新创建的
            resp.getWriter().print("session创建成功,ID:"+sessionId);    //第一次请求该Servlet都会执行这一行,如果本次请求Servlet中销毁了session,则下次请求仍会执行这一行
        }
        else{
            resp.getWriter().print("session已经在服务器中存在了,ID:"+sessionId);//如果本次请求Servlet中没有销毁session,则下次请求就会执行这一行
        }
        //Session创建的时候做了什么事情;
//        Cookie cookie = new Cookie("JSESSIONID",sessionId);
//        resp.addCookie(cookie);

        Person person = (Person) session.getAttribute("user"); //获取session中user属性的值
        System.out.println(person);

        session.removeAttribute("user");  //删除user属性和对应的值
//        session.invalidate();   //手动销毁当前发起请求的浏览器session,然后服务器又会自动创建一个新的session给该浏览器,且sessionid会变
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
 	<servlet>
        <servlet-name>session</servlet-name>
        <servlet-class>com.liqingfeng.Sessions</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>session</servlet-name>
        <url-pattern>/session</url-pattern>
    </servlet-mapping>

Session存活时间:

方法1:session.invalidate() //手动代码实现服务器端销毁该Session对象
方法2:关闭浏览器,自动销毁当前Session的id,下次访问不是同一个session
方法3:web.xml配置 //时间到服务器端自动销毁该Session对象(浏览器不关闭,时间到该session就被销毁)

<!--设置Session默认的有效时间-->
<session-config>
    <!--15分钟后Session自动失效,以分钟为单位-->
    <session-timeout>15</session-timeout>
</session-config>

浏览器关闭再次访问,服务器不关闭时session不是同一个问题
因为默认情况下,当getSession()后,session就被被创建。session在创建时,服务器会通过Cookie返回session 的ID给浏览器,之后服务器根据浏览器Cookie里的session的ID来分辨不同浏览器。但是,这种方法返回的cookie是保存在浏览器的内存中,浏览器关闭后内存会被清理,所以该sessionid在浏览器关闭后就失效了。再次访问服务器,服务器又会重新给浏览器一个新的sessionid和创建对应的session对象。虽然在服务器保存的session会在有效期后才会被销毁,但是浏览器的cookie里没有之前的session的ID,服务器就不能判断出当前用户是否是原先的那个用户(即使之前那个seesion对象还在)。
所以,设置session的有效时间只是服务器端保证该session对象有效时间到了就被销毁。浏览器端关闭后若要想再次访问时session还是同一个,则需要保证sessionid为同一个,这样服务器端才能识别该浏览器。
解决方法如下(该cookie最大存活时间应<=服务器端设施的有效时间,否则服务器端有效时间到会自动销毁当前id的session对象,这样浏览器的sessionid就匹配不了被销毁的那个session对象)

Cookie c = new Cookie("JSESSIONID",session.getId());
c.setMaxAge(60*60);	//该cookie最大存活时间=
response.addCookie(c);

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

七.JSP

1.原理

Java Server Pages : Java服务器端页面,也和Servlet一样,用于动态Web技术!
最大的特点:写JSP就像在写HTML。
区别:HTML只给用户提供静态的数据,JSP页面中可以嵌入JAVA代码,为用户提供动态数据。
找到该路径:
C:\Users\秋天的思念\AppData\Local\JetBrains\IntelliJIdea2020.1\tomcat\Unnamed_java-01-maven\work\Catalina\localhost\liqingfeng\org\apache\jsp
在这里插入图片描述
发现jsp转变成了Java程序!
所以,浏览器向服务器发送请求,不管访问什么资源,其实本质都是访问Servlet!JSP最终也会被转换成为一个Java类!JSP 本质上就是一个Servlet。
login.jsp和login_jsp.java对比可知,其实jsp就是简化了java代码书写。在JSP页面中,只要是 JAVA代码就会原封不动的输出;如果是HTML代码,就会被转换为:out.write("<html>\r\n");这样的格式,输出到前端页面。
在这里插入图片描述
JSP九大内置对象,这些对象我们可以在JSP中直接访问使用

			变量名					真实类型						作用
		* pageContext				PageContext					当前页面共享数据,还可以获取其他八个内置对象
		* request					HttpServletRequest			一次请求访问的多个资源(转发)共享数据
		* session					HttpSession					一次会话的servlet、jsp之间共享数据
		* application				ServletContext				服务器的资源都可以共享数据
		* response					HttpServletResponse			响应对象
		* page						Object						当前页面(Servlet)的对象  this
		* out						JspWriter					输出数据到页面上
		* config					ServletConfig				Servlet的配置对象
		* exception					Throwable					异常对象
2.JSP语法

JSP脚本:
1.<%= java代码%>(用来将程序输出(out.print(java代码)),输出到客户端,在jsp .java的service方法中)

  <%= new java.util.Date()%>
  <%= i%>

2.<% java代码%>(用来放java代码,在jsp .java的service方法中)

  <%
     int sum = 0;
     for (int i = 1; i <=100 ; i++) {
       sum+=i;
     }
     out.println("<h1>Sum="+sum+"</h1>");
  %>

2.<%! java代码%>(用来声明改类的成员(变量或方法),在jsp .java的类中)

<%!
    static {
      System.out.println("Loading Servlet!");
    }
    private int globalVar = 0;
    public void kuang(){
      System.out.println("进入了方法Kuang!");
    }
  %>

JSP指令:
用于配置JSP页面,导入资源文件
<%@ 指令名称 属性名1=属性值1 属性名2=属性值2 … %>
指令名称:
page: 配置JSP页面
include : 包含其他页面,导入页面的资源文件
taglib: 导入资源

<%@page args.... %>
<%@include file=""%>

<%--@include  会将两个页面合二为一--%>
<%@include file="common/header.jsp"%>
<h1>网页主体</h1>
<%@include file="common/footer.jsp"%>

JSP标签:
<jsp: …> </jsp:…>

<jsp:forward page="/jsptag2.jsp">
    <jsp:param name="name" value="kuangshen"></jsp:param>
    <jsp:param name="age" value="12"></jsp:param>
</jsp:forward>
3.JSTL(JSP标准标签库)

在pom.xml导入两个依赖包

<!-- JSTL表达式的依赖 -->
<dependency>
   <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>jstl-api</artifactId>
    <version>1.2</version>
</dependency>
<!-- standard标签库 -->
<dependency>
    <groupId>taglibs</groupId>
    <artifactId>standard</artifactId>
    <version>1.1.2</version>
</dependency>

分为格式化标签,SQL标签,XML 标签,核心标签 (掌握部分),JSTL 函数
详解可参考https://www.runoob.com/jsp/jsp-jstl.html

以<c:forEach>遍历为例:

<%--导入核心标签库才能使用--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
    ArrayList<String> people = new ArrayList<>();
    people.add(0,"张三");
    people.add(1,"李四");
    people.add(2,"王五");
    people.add(3,"赵六");
    people.add(4,"田六");
    request.setAttribute("list",people);//在本次请求存放数据(list:people),随着请求消失数据也消失,这样节约资源
%>
<%--
	var,  临时变量
	items, 要遍历的对象
	begin, 哪里开始
	end,   到哪里
	step,  步长
--%>
<c:forEach var="people" items="${list}">
    <c:out value="${people}"/> <br>
</c:forEach>
<hr>
<c:forEach var="people" items="${list}" begin="1" end="3" step="1" >
    <c:out value="${people}"/> <br>
</c:forEach>
4.EL表达式

格式:${表达式}
作用:替换和简化jsp页面中java代码的编写
jsp默认支持el表达式的。如果要忽略el表达式1.设置jsp中的page指令:isELIgnored=“true” 忽略当前jsp页面中所有的el表达式;2.\${表达式}:忽略当前这个el表达式
使用:(具有2个功能)

	1. 运算:
		1. 算数运算符: + - * /(div) %(mod)     如${3/4},浏览器访问该jsp将显示0
		2. 比较运算符: > < >= <= == !=
		3. 逻辑运算符: &&(and) ||(or) !(not)
		4. 空运算符: empty
			* 功能:用于判断字符串、集合、数组对象是否为null或者长度是否为0
			* ${empty list}:判断字符串、集合、数组对象是否为null或者长度为0
			* ${not empty str}:表示判断字符串、集合、数组对象是否不为null 并且 长度>0
	2. 获取值
		1. el表达式只能从域对象中获取值
		2. 语法:
			1. ${域名称.键名}:从指定域中获取指定键的值
				* 域名称:(域的大小排名pageContext<request<session<application)
					1. pageScope		--> pageContext
					2. requestScope 	--> request
					3. sessionScope 	--> session
					4. applicationScope --> application(ServletContext)
				* 举例:在request域中存储了name=张三(request.setAttribute(name","张三"))
				* 获取:${requestScope.name}

			2. ${键名}:表示依次从最小的域中开始查找是否有该键对应的值,直到找到为止。
			3. 获取对象、List集合、Map集合的值
				1. 对象:${域名称.键名.属性名}
				    *属性:类中set/get方法去掉set和get,首字母小写后的字符串
					* ${域名称.键名.属性名}本质上是调用该键名对应对象的get方法,如{user.name}:调用user对应的对象(假设也为user)的user.getName方法返回的name值
				2. List集合:${域名称.键名[索引]}
				3. Map集合:
					* ${域名称.键名.key名称}
					* ${域名称.键名["key名称"]}
	3. 隐式对象:
		* el表达式中有11个隐式对象
		* pageContext隐式对象:(可以获取jsp其他八个内置对象)
				* ${pageContext.request.contextPath}:动态获取虚拟目录,实质调用pageContext.getRequest.getContextPath。

八.JavaBean

JavaBean即实体类,一般用来和数据库的字段做映射 ORM
JavaBean有特定的写法:必须要有一个无参构造,属性必须私有化,必须有对应的get/set方法;
ORM :对象关系映射
数据库表——一个类
表中一个字段——类的一个属性
表中一行数据——类的一个实例化对象

九.MVC三层架构

MVC( Model view Controller):即模型、视图、控制器架构
以前的架构:
用户直接访问控制器,控制器就可以直接操作数据库。
在这里插入图片描述
MVC三层架构:各层只做自己的事,分工明确
Model
业务层:业务逻辑(Service)
数据持久层:CRUD (Dao - 数据持久化到数据库)

View
展示数据(jsp)
提供链接发起Servlet请求 (a,form,img…)

Controller
接收用户的请求,获取数据:(req:请求参数、Session信息….)
交给业务层处理对应的代码
控制视图的跳转

在这里插入图片描述

十.Filter过滤器

过滤器 :用来过滤网站的数据。
可以用来处理中文乱码,登录验证……
过滤器执行流程:
1.执行过滤器
2.执行放行后的资源(jsp、servlet)
3.回来执行过滤器放行代码下边的代码

@Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //是由请求触发的filter,Request的处理放这里
        servletRequest.setCharacterEncoding("utf-8");
        //放行
        filterChain.doFilter(servletRequest,servletResponse);
        //响应后走到这里,Response的处理放这里
        servletResponse.setContentType("text/html;charset=UTF-8");
    }

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

* 注解配置:
	* 设置dispatcherTypes属性
		1. REQUEST:默认值。浏览器请求时触发filter   @WebFilter(dispatcherTypes = DispatcherType.REQUEST)
		2. FORWARD:服务器请求转发时触发filter 
		3. INCLUDE:包含访问资源时触发filter 
		4. ERROR:错误跳转资源时触发filter 
		5. ASYNC:异步访问资源时触发filter 
	* web.xml配置
		* 设置<dispatcher></dispatcher>标签即可

过滤器链(配置多个过滤器)
执行顺序:
如果有两个过滤器:执行顺序为过滤器1和过滤器21. 过滤器1;2. 过滤器2;3. 资源执行;4. 过滤器2;5. 过滤器1
过滤器执行先后顺序问题:
1.都采用注解配置:按照类名的字符串比较规则比较,值小的先执行。如: AFilter 和 BFilter,AFilter就会先执行。2. 都采用web.xml配置: 谁定义在上边,谁先执行
在这里插入图片描述
自己的过滤器必须实现Filter(javax.servlet.Filter)接口,在doFilter方法中写需要过滤的代码,切记加上chain.doFilter(request,response);
过滤器使用的request,response放行后到其他jsp(servlet)时的request,response是同一个对象,所以在filter里对request,response进行d的操作,是直接影响放行后在jsp(servlet)的request,response对象。

//过滤器实现字符编码
public class Filters implements Filter {
    @Override
    //初始化:web服务器启动,就以及初始化了,随时等待过滤对象出现!
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("Filter初始化");
    }

    @Override
      /*
      1. doFilter方法,在过滤特定请求的时候都会执行
      2. 必须要让过滤器放行
          chain.doFilter(request,response);
      */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=UTF-8");

        System.out.println("CharacterEncodingFilter执行前....");
        chain.doFilter(request,response); //让我们的请求继续走,如果不写,程序到这里就被拦截停止!
        System.out.println("CharacterEncodingFilter执行后....");
    }

    @Override
    //销毁:web服务器关闭的时候,过滤器会销毁
    public void destroy() {
        System.out.println("Filter销毁");
    }
}

web.xml配置过滤器映射
只要是 http://localhost:8080/liqingfeng/session的任何请求,会先经过这个过滤器。

	<filter>
        <filter-name>Filters</filter-name>
        <filter-class>com.liqingfeng.Filters</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>Filters</filter-name>
        <url-pattern>/session/*</url-pattern>
    </filter-mapping>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值