JavaWeb笔记

1、基本概念

web开发:

  • 静态web:
    • html,css;
    • 始终不会变化;
  • 动态web:
    • 现在几乎所有网站都是“千人千面”;(例如淘宝)
    • 技术栈:Servlet/JSP,ASP,PHP;

在java中,动态web资源开发的级数统称为JavaWeb;

1.2、web应用程序

web应用程序:可以提供浏览器访问的程序;

  • a.html、b.html……多个web资源,这些web可以被外界访问,对外界提供服务;
  • 我们能够访问到任何一个资源;(URL)
  • web资源会被统一放在一个文件夹下,web应用程序--> Tomcat:服务器;
  • 一个web应用由多个部分组成(静态web,动态web)
    • html,css,js;
    • jsp,servlet;
    • java程序;
    • jar包;
    • 配置文件;(properties)

web应用程序编写完毕后,若想给外界访问,则需要一个服务器来统一管理!

1.3、静态web

静态web架构

  • *.htm 、 *.html、如果服务器上一直存在这些东西,我们就可以直接进行读取;
  • 缺点:
    • web无法动态更新;
      • 轮播图,点击特效:微动态
      • JavaScript【实际开发中,用的最多】
      • VBScript
    • 无法与数据库进行交互(数据无法持久化,用户无法交互)

1.4、动态web

页面会动态展示:“web展示页面因人而异”

动态web架构

缺点:

  • 加入服务器的动态web资源出现了错误,需要重新编写后台程序,重新发布;
    • 停机维护;

有点:

  • 可以动态更新web;
  • 可以与数据库交互(数据持久化,用户交互)

2、web服务器

2.1、介绍

ASP

  • 微软:国内最早流行的;
  • 在html中嵌入了VB脚本,ASP+COM;
  • 在ASP开发中,一个基本页面中,要嵌入大量的java代码业务,代码更乱;
  • 使用C#语言;
  • IIS

PHP

  • PHP开发速度很快,功能很强大,跨平台,代码简单(70%的网页都使用);
  • 无法承载大访问量,具有局限性,支持不了大型网站;

JSP/Servlet

B/S架构:浏览器和服务器;

C/S架构:客户端和服务器;

  • sun公司主推的B/S架构;
  • 基于java语言的(所有的大公司,或者一些开源的组件,都是用java写的);
  • 可以承载三高问题带来的影响;(高可用,高并发,高性能)
  • 语法像ASP,加强时长竞争力;

2.2、web服务器

服务器是一种被动操作,用来处理用户的请求,和响应信息;

  • IIS
    • 微软,ASP……Windows中自带;
  • Tomcat:
    • Apache,性能稳定,技术先进,免费,深受喜爱。
    • 免费开源的web应用服务器,属于轻量级应用服务器,中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP的首选。
    • Tomcat处理静态HTML的能力不如Apache服务器。
    • Tomcat实际上运行JSP页面和Servlet,目前Tomcat最新版本为10.0;

下载Tomcat:

  1. 安装./解压;
  2. 了解配置文件和目录结构;
  3. 作用;

3、Tomcat

3.1、安装Tomcat

官网:https://tomcat.apache.org/

image-20220330165159258

image-20220330165820124


3.2、启动/关闭Tomcat

bin目录下的startup.bat / shutdown.bat ;

测试:访问 localhost:8080

可能遇到的问题:

  1. java环境变量没有配置;
  2. 闪退问题,需要配置兼容性;
  3. 乱码问题;去配置文件中设置(conf/server.xml);

3.3、配置

  • 查看配置文件;
  • 默认网站应用存放位置:webapps

3.4、发布一个自己的网站

模仿:

  • 将自己写的网站,放到服务器(Tomcat)中指定的web应用的文件夹(webapps)下,就可以访问了;

网站结构:

--webapps:Tomcat服务器的web目录
    -ROOT
    -myweb:网站的目录名
    	- WEB-INF
    		-classes:java程序
    		-lib:web应用所依赖的jar包
            -web.xml:网站配置文件
        - index.html  默认的首页
        - static
        	-css
                -style.css
            -js
            -img
        - ……

5、Maven

为什么需要这个技术?

  1. 在JavaWeb开发中,需要使用大量的jar包,需要手动导入;
  2. 需要一个东西自动帮我们导入和配置jar包;

因此,maven诞生!

Maven项目架构管理工具:就是用来方便导入jar包的!

Maven的核心思想:约定大于配置

Maven会规定好该如何编写java代码,必须按照规范来;

5.1、下载安装Maven

image-20220331161616808

下载、解压;(所有环境放在同一个文件夹中);

注意:(我下载这个版本遇到了bug,建议3.6.2以下)

5.2、配置环境变量

  1. 在系统环境变量中添加配置
  • MAVEN_HOME:Maven文件目录
  • M2_HOME(后期会用到):maven文件下的bin目录
  • 系统环境变量
  1. 添加到path路径中

    添加path路径

  2. 检查配置是否成功:

    检查配置结果


5.3、修改阿里云镜像

加速下载;

  1. 打开maven的配置文件:conf\settings.xml

    maven配置文件位置

  2. 添加阿里云镜像:

    <mirror>
        <id>nexus-aliyun</id>
        <mirrorOf>*,!jeecg,!jeecg-snapshots</mirrorOf>
        <name>Nexus aliyun</name>
        <url>https://maven.aliyun.com/nexus/content/groups/public</url> 
    </mirror>
    

    阿里云镜像


5.4、建立本地仓库

本地仓库:

默认位置:默认的本地仓库位置

建立过程:

  1. 在maven目录下新建本地仓库文件夹:maven-repo

    新建本地仓库文件夹

  2. 修改配置文件本地仓库路径:

  3. 修改配置文件localRepository


5.5、在IDEA中使用Maven

  1. 打开IDEA创建新的MavenWeb项目:

    创建新Maven项目

image-20220401165620329


image-20220401165814384

image-20220401170317361


  1. 等待项目初始化:

    image-20220401171510508

  2. 观察Maven仓库中的文件:

    image-20220401171603176

  3. IDEA中的Maven设置:

    image-20220401171822479

    image-20220401172210044

注意(问题):在IDEA中,项目自动创建完成后,MavenHome经常会使用IDEA默认的配置!!需要手动修改!

所以,项目创建成功后,注意瞟一眼配置;

  1. 到这里IDEA的Maven创建和配置就OK了!

5.6、创建一个普通的MavenWeb项目

这次不使用Maven模板,直接创建一个Maven项目

项目结构:

image-20220401174937853

(对比Web应用的项目结构:image-20220401215221356)

(纯净maven)步骤:

  • 修改项目结构;创建两个文件夹:java、resources;并标记为对应文件夹;

  • 得到maven初始的pom.xml文件

    <?xml version="1.0" encoding="UTF-8"?>
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>org.example</groupId>
        <artifactId>javaweb-session-cookie</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>war</packaging>
    
        </dependencies>
    </project>
    
  • 防止maven默认web项目中的web.xml版本问题:

    修改web.xml:(复制于Tomcat目录里的原始web.xml,因为这样子对Tomcat的兼容性最强(原生))

    <?xml version="1.0" encoding="UTF-8"?>
    
    <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
                          https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
      version="5.0"
      metadata-complete="true">
        
    </web-app>
    
  • 写java代码;

  • web.xml中注册,添加映射:

      <servlet>
        <servlet-name>CookieDemo01</servlet-name>
        <servlet-class>com.study.CookieDemo01</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>CookieDemo01</servlet-name>
        <url-pattern>/c1</url-pattern>
      </servlet-mapping>
    
  • 去Tomcat中发布项目;

  • 启动Tomcat进行访问;

发布Servlet时遇到的bug:

  • 服务器500报错;

解决:

Tomcat10版本环境下,将 javax.servlet 都改为了jakarta.servlet

 <dependency>
      <groupId>jakarta.servlet.jsp</groupId>
      <artifactId>jakarta.servlet.jsp-api</artifactId>
      <version>3.0.0</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>jakarta.servlet</groupId>
      <artifactId>jakarta.servlet-api</artifactId>
      <version>5.0.0</version>
      <scope>provided</scope>
    </dependency>

Mark文件来:

image-20220401215527603

或者:设置中的项目结构配置:

image-20220401215621077

image-20220401215905690


5.7、在IDEA中配置Tomcat

  1. 添加配置:image-20220401220331301
  2. image-20220401220417728
  3. image-20220401220855625
  4. 创建一个artifacts,解除警告:

此处我遇到一个deployment里没有artifacts选项的问题:

image-20220401223741956

(idea:2021.3.2;Tomcat:10.0.8)

解决办法见:https://blog.csdn.net/qq_31887267/article/details/90775368

image-20220401224508776

配置的项目不写路径,默认端口号8080访问服务器;

image-20220511004831356

为什么会有这个警告?------->因为访问布一个网站,需要指定一个文件名字;

  1. 启动Tomcat:image-20220401224814122

    启动成功!

    image-20220401224924536


5.8、 Pom文件

image-20220401230630824

这里我遇到一个问题:idea中maven project只看到lifecycle而没plugins和dependencies:

原因:idea和3.6.2(及以上)版本的maven不兼容(此处我用的是3.8版本);

解决办法,下载3.6.2以下版本并重新配置环境变量和项目即可;

pom.xml是Maven的核心配置文件;image-20220401230952908

image-20220401231209583

image-20220401231406442


image-20220401231555663


image-20220401231714357


image-20220401231811427

maven的高级之处就在于他能够自动帮忙导入jar包及其所需的其他包!

Maven由于约定大于配置,可能遇到的问题:

我们之后写的配置文件可能无法导出!

解决资源到处问题:

在biuld中配置resources,防止资源导出失败;

<!--在build中配置resources,来防止我们资源导出失败的问题-->
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <excludes>
                    <exclude>**/*.properties</exclude>
                    <exclude>**/*.xml</exclude>
                </excludes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>

5.11、IDEA生成目录树

Maven中jar包的联系关联图:

image-20220401232548238

image-20220401232612802


Maven仓库的使用

添加Servlet的maven依赖:

  • 首次使用去官网下载jar包:https://mvnrepository.com/:

    既然Tomcat的examples里面有Servlet的例子,能启动就一定有对应的jar包,进入文件目录找到:image-20220511010735314

    于是就去官网中搜索:image-20220511010827056

    下载使用者最多的一个;image-20220511011002543

  • 复制仓库依赖进pom.xml配置文件:image-20220511011411875

    image-20220511011434959

  • 继续导入其他需要的包:image-20220511011725274

6、Servlet

Setvlet接口规定了两个必须继承的实现类:HttpServletGevericServlet

6.1、Servlet简介

  • Servlet就是sun公司开发动态web的技术;
  • Sun在这些API中提供了一个借口叫做:Servlet,如果想开发一个Servlet程序,就只需要:
    • 编写一个类,实现Servlet接口;
    • 把开发好的java类部署到web服务器中;
      实现了Servlet接口的java程序就叫做Servlet

6.2、HelloServlet

  1. 构建一个普通的Maven项目,删掉里面的src项目,以后学习就在这个文件下创建module,这个空的工程就是Maven主工程;
  2. 关于Maven父子工程的理解;父项目中的java子项目可以直接使用;
  3. Maven环境优化:
    1. 修改web.xml为最新的;
    2. 讲maven的结构搭建完整;
  4. 编写一个Servlet程序;
    1. 编写一个普通类;
    2. 实现一个Servlet接口;继承HttpServlet接口;
  5. 编写Servlet的映射
    理由 :因为我们写的是java程序,但是要通过浏览器访问,而浏览器需要链接web服务器,所以我们要在web服务中注册我们写的Servlet,还需要给他一个浏览器能够访问的路径;
  6. 配置Tomcat;(注意配置项目发布的路径!)
  7. 启动测试;(启动后会生成target目录)

6.3、Servlet运行原理

6.4、Mapping问题

请求路径的映射问题

  1. 一个Servlet可以指定一个映射路径:
  2. 一个Servlet可以指定多个映射路径
  3. 一个Servlet可以指定通用映射路径
  4. 一个Servlet可以指定一些后缀或前缀等等……
  5. 指定了固有路径的映射优先级最高,它的优先级大于通配符的映射;

可以用映射来解决一些error(404……)
例如: *.error


6.5、ServletContext

web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前web应用;

6.5.1、共享数据

  • 在这个Servlet中保存的数据,可以在另外一个Servlet中拿到(传递);

  • 放置数据类:

    public class HelloServlet extends HttpServlet{
        @Override
        protected void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{
            //this.getInitialParermeter();//初始化参数
            //this.getServletConfig();	//获得Servlet配置
            //this.getServletContext;	//获得Servlet上下文
            ServletContext context=this.getServletContext;
            
            String username = "秦疆";
            context.getAttribute("username",username);	//将一个数据存在了ServletContext中,名字为username,值为username
        }
    }
    
  • 读取数据的类:

    public class GetServlet extends HttpServlet{
        @Override
        protected void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{
            ServletContext context=this.getServletContext;
            String username =(String)context.getAttribute("username");
           
            resp.setContextType("text/html");
            resp.setCharacterEncoding("utf-8");
            resp.getWriter().print("名字"+username);
        }
    
        @Override
        protected void doPost(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{
            doGet(req,resp);
        }
    }
    
  • web.xml:

    <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>
    
    <servlet>
    	<servlet-name>getc</servlet-name>
        <servlet-class>com.kuang.servlet.GetServlet</servlet-class>
    </servlet>
    <servlet-mapping>
    	<servlet-name>getc</servlet-name>
        <url-pattern>/getc</url-pattern>
    </servlet-mapping>
    
  • 测试访问结果:


6.5.2、获取初始化参数

<!--配置web应用的初始化参数-->
<context-param>
	<param-name>url</param-name>
    <param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>

获取:

@Override
protected void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{
        ServletContext context=this.getServletContext;
        String url =context.getInitParammeter("url");
		resp.getWriter().print(url);
    }

6.5.3、请求转发

@Override
protected void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{
        ServletContext context=this.getServletContext;
		RequestDispatcher requestDispatcher=context.getRequestDispatcher("/gp");//转发的请求路径
    requestDispatcher.forward(req,resp);//执行转发请求
    }

6.5.4、读取资源文件

Properties

  • 在java目录下新建properties;
  • 在resources目录下进件properties;

执行程序发现,都被打包到了同一个target目录下,classes,俗称这个路径为classpath

通过context读取properties配置文件中的信息:(需要一个文件流getResourceAsStream()

@Override
protected void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{
        InpuStream is=this.getServletContext.getResourceAsStream("/WEB-INF/classes/db.properties");//将配置文件作为流输入
		Properties prop=new Properties();
    
    	prop.load(is);
    	String username=prop.getProperty("username");
    	String pwd=prop.getProperty("password");
    
    	resp.getWriter().print(username+":"+pwd);
    }

6.6、HttpServletResponse

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

1、简单分类

  • 负责向浏览器发送数据的方法:
ServletOutputStream getOutputStream() throws IOException;

PrintWriter getWriter() throws IOException;
  • 负责向浏览器发送响应头的方法:(编码、解码之类)

  • 响应的状态码:


2、常见应用

  • 向浏览器输出信息:(前面一直在使用)

  • 下载文件

    1. 获取下载文件的路径:
    2. 下载文件的文件名;
    3. 设置让浏览器能够支持下载我们需要的文件
    4. 获得文件输入流;
    5. 创建缓冲区;
    6. 获取Outputstream对象
    7. 将FileOutputStream流写入到缓冲区buffer;
    8. 使用OutputStream对象将缓冲区中的数据输出到客户端;
    @Override
    protected void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{
        //1. 获取下载文件的路径:
        String realPath="F:\\XXXX\\JavaWeb\\javaweb-02-servlet\\response\\target\\classes\\秦疆.png";
        //2. 下载文件的文件名;
        String fileName=realPath.subString(RealPath.lastIndexOf("\\")+1);
        //3. 设置让浏览器能够支持(Content-Disposition)下载我们需要的文件,(URLEncoder.encode(fileName,"UTF-8"))解决中文文件名问题)
        resp.setHeader("Content-Disposition","attatchment;filename="+URLEncoder.encode(fileName,"UTF-8"));
        //4. 获得文件输入流;
        FileInputStream in = new FileInputStream(realPath);
        //5. 创建缓冲区;
        byte[] buffer=new byte[1024];
        int len=0;
        //6. 获取Outputstream对象
        ServletOutputStream out=resp.getOutputStream();
        //7. 将FileOutputStream流写入到缓冲区buffer;
        while((len=in.read(buffer))!=-1){
            out.write(buffer,0,len);
        }
        
        in.close();
        out.close();
        }
    
    • 写完doget之后,记得要去pom.xml中注册新的web;

      <servlet>
      	<servlet-name>filedown</servlet-name>
          <servlet-class>com.kuang.servlet.FileServlet</servlet-class>
      </servlet>
      <servlet-mapping>
      	<servlet-name>filedown</servlet-name>
          <url-pattern>/down</url-pattern>
      </servlet-mapping>
      
    • 在Tomcat中发布新的项目;


3、验证码功能

实例:在网页上显示验证码(图片形式),每3s刷新一次

@Override
protected void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{
 	//让浏览器3秒刷新一次
    resp.setHeader("refresh","3");
    
    //在内存中创建一张图片
    BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGN);//宽80,高20
    //得到图片
    Graphics2D g = (Graphics2D) image.getGraphics();//画笔
    //设置图片的背景颜色
    g.setColor(Color.white);
    g.fillRect(0,0,80,20);
    //给图片写入随机验证码
    g.setColor(Color.BLUE);//切换蓝色画笔 
    g.setFont(new Font(null,Font.BOLD,20));
    g.drawString(makeNum(),0,0);
    
    //告诉浏览器,这个请求用图片方式打开
    resp.setContentType("image/jpeg");//这里的JPEG也可以是JPG、png等格式
    
    //网站存在缓存,设置不让缓存
    resp.setDateHeader("expires",-1);
    resp.setHeader("Cache-Control","no-cache");
    resp.setHeader("Pragma","no-cache"); 
    
    //把图片写给浏览器--->ImageIO--->专门写图片的IO
    ImageIO.write(image,"jpg",resp.getOutputStream());
    }

//生成随机数方法
private String makeNum(){
    Random random=new Random();
    String num= random.nextInt(9999999)+"";//7位数,+""--->把int转换为String
    //随机生成的num有可能小于7位,验证码少几位,就在StringBuffer里面添加几个0,之后再拼接起来,确保7位验证码
    StringBuffer sb=new StringBUffer();
    for(int i;i<7-num.length;i++){
        ab.append("0");
    }
    num=sb.toString()+num;
    return num;
}

接下来去 pom.xml中注册对应服务;

这种方式产生的验证码,可以再网站中下载验证码图片,因为我们是让浏览器把它识别为图片的形式("image/jpeg")


4、实现重定向

含义:一个web资源收到客户端请求之后,通知客户端去访问另一个web资源;

重定向实现:

void sendDirect(String var1) throws IOException;

测试:

@Override
protected void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{
	resp.sendDirect("/r/img");
    /*
    resp.setHeader("Location","/r/img");
    resp.setStatus(302);//重定向代码
    */
    }

重定向和转发的区别:

  • 相同:页面实现跳转
  • 不同:
    • 转发时,URL不会发生变化;
    • 重定向时,客户端跳转到访问新的URL;

表单提交重定向实例:

index.jsp:(需要在maven中导入jsp的包

<%-- action中,放入跳转的请求地址 
--    这里提交的路径,需要寻找到项目路径;
--    ${pageContext.request.contextPath}代表当前项目
    --%>

<form action="${pageContext.request.contextPath}/login" method="get">
    用户名:<input type="text" name="username">
    密码:<input type="password" name="password">
    <input type="submit">
</form>

发起请求的java类:

public class RequestTest extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{
        //处理请求
        String username=req.getParameter("username");
        String password=req.getParameter("password");
        
        System.out.println(username+":"+password);
        //重定向		(注意路径问题,否则404)
        resp.sendRedirect("/r/success.jsp");//成功后跳转的jsp页面
    }
    
    @Override
    protected void doPost(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{
        doGet();
    }
}

配置web.xml:网站中输入/login 就跳转到服务,将这个地址添加到jsp的action中

<servlet>
	<servlet-name>request</servlet-name>
    <servlet-class>com.kuang.servlet.RequestTest</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>request</servlet-name>
    <url-pattern>/login</url-pattern>
</servlet-mapping>

6.7、HttpServletRequest

​ HttpServletRequest代表客户端发送的请求,通过这个对象的方法,能够获得客户端提交的所有信息。

1、获取前端传递参数、请求转发

req.getParameter(String s)			---> 返回一个String
req.getParameterValues(String s)	---> 返回String[]数组

实例:

​ 获取多选表单的值(代码和上例登录实例类似)

//解决乱码
req.setCharacterEncoding("utf-8");	//请求,解决控制台输出中文乱码问题
resp.setCharacterEncoding("utf-8");	//响应返回的解决乱码问题


//视频中的转发路径问题
req.getRequestDispatcher("/r/success.jsp").foward(req,resp);//转发,不需要 /r/success.jsp,直接写目标网页就行。现在这种方式会跳转到/r/r/success.jsp路径(404)
//sendRedirect()  重定向:方法中才需要添加 --> /路径

7、Cookie、Session

7.1、会话

会话:

有状态会话:服务器端会记录来过的客户端

一个网站如何知道一个客户端是否来访问过?

  1. 服务端给客户端一个信件,客户端下次访问的时候携带上这个信件;Cookie

  2. 服务端登记客户端已来过,下次客户端再来时,服务端对客户端进行匹配;Session;

7.2、保存会话的两种技术

Cookie:

  • 客户端技术(响应,请求;);

Session:

  • 服务器技术,我们可以利用这个技术,把客户端的会话信息保存在session中;

7.3、Cookie

  1. 从请求中拿到cookie信息;

  2. 服务器响应给客户端cookie

    Cookie[] cookies=req.getCookies();//获得cookie
    cookie.getName();//获得cookie中的key
    cookie.getValue();//获得cookie中的value
    new Cookie("lastLoginTime",Sytem.currentTimeMillis()+"");//新建cookie
    cookie.setMaxAge(24*60*60);//设置cookie的有效期
    resp.addCookie(cookie);//响应给客户端一个cookie
    
    

    cookie:一般会保存在本地的 用户目录名下的appdata;

    IO中解决中文乱码问题会用到:

    //编码
    Cookie cookie =new Cookie("name",URLEncoder.encode("秦疆","utf-8"));
    //解码   
    out.write(URLDecoder.decode(cook.getValue(),"utf-8"));
    
    
    //解决中文乱码
    req.setCharacterEncoding("UTF-8");
    resp.setCharacterEncoding("UTF-8");
    resp.setContentType("text/html;charset=UTF-8");		//我电脑上少了这条的话,输出还是中文乱码
    

    ​ 关于cookie的一些细节:

    • cookie:一般会保存在本地的用户目录下appdata;
    • 一个网站的cookie是否存在上限?
      • 一个cookie只能保存一个信息;
      • 一个web站点可以给浏览器发送多个cookie,最多20个;
      • cookie大小限制4kb;
      • 300个cookie浏览器上限;

    删除cookie:

    • 不设置有效期,关闭浏览器就自动失效;
    • 设置有效期为0;

    实例:

    ​ 通过cookie获得最后登录时间;

    package com.study;
    
    import jakarta.servlet.ServletException;
    import jakarta.servlet.http.Cookie;
    import jakarta.servlet.http.HttpServlet;
    import jakarta.servlet.http.HttpServletRequest;
    import jakarta.servlet.http.HttpServletResponse;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Date;
    
    //保存用户上一次访问的时间
    public class CookieDemo01 extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //服务器告知用户来访问的时间,用户把这个时间封装成一个信件,下次访问时带上,服务器就知道你来了;
    
            //解决中文乱码
            req.setCharacterEncoding("UTF-8");
            resp.setCharacterEncoding("UTF-8");
            resp.setContentType("text/html;charset=UTF-8");
    
            //响应输出流
            PrintWriter out = resp.getWriter();
    
            //从客户端获得cookie
            Cookie[] cookies = req.getCookies();//这里返回的是一个cookie数组,说明cookie可能存在多个!
    
            //判断cookie是否存在
            if (cookies != null) {
                //若存在则进行的操作
                out.write("您上一次登录的时间是:");
                for (int i = 0; i < cookies.length; i++) {
                    Cookie cookie = cookies[i];
                    //获取cookie的值
                    if (cookie.getName().equals("LastLoginTime"))
                    //将时间转换为long
                    {
                        long LastLoginTime = Long.parseLong(cookie.getValue());
                        Date date = new Date(LastLoginTime);
                        out.write(date.toLocaleString());
                    }
                }
            } else {
                //否则通知这是第一次来,还没有cookie
                System.out.println("这是您的第一次访问");
            }
    
            //服务器为客户端设置(添加)cookie,最后一次登录时间
            Cookie cookie = new Cookie("LastLoginTime", System.currentTimeMillis() + "");
            resp.addCookie(cookie);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    

    配置文件:web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
                          https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
             version="5.0"
             metadata-complete="true">
    
      <display-name>Welcome to Tomcat</display-name>
      <description>
        Welcome to Tomcat
      </description>
    
      <servlet>
        <servlet-name>CookieDemo01</servlet-name>
        <servlet-class>com.study.CookieDemo01</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>CookieDemo01</servlet-name>
        <url-pattern>/c1</url-pattern>
      </servlet-mapping>
    </web-app>
    

    pom.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>org.example</groupId>
        <artifactId>javaweb-session-cookie</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>war</packaging>
    
        <dependencies>
            <dependency>
                <groupId>jakarta.servlet.jsp</groupId>
                <artifactId>jakarta.servlet.jsp-api</artifactId>
                <version>3.0.0</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>jakarta.servlet</groupId>
                <artifactId>jakarta.servlet-api</artifactId>
                <version>5.0.0</version>
                <scope>provided</scope>
            </dependency>
    
        </dependencies>
    </project>
    

7.4、Session(重点)

什么是Session:

  • 服务器会给每一个用户(浏览器)创建一个会话;
  • session区别于cookie,他可以在值中传入对象

session新建时,相当于:

Cookie cookie=new Cookie("JSESSIONID",sessionId);
resp.addCookie(cookie);

相当于新建了一条sessionID,创建到了新的cookie中;


Session和Cookie的区别:

  • Cookie是把用户的数据写给用户的浏览器,由浏览器保存;
  • Session把用户的数据写到用户独占的Session中,只要浏览器没关,这个session就一直存在。由服务器端保存(只保存重要信息,减少服务器资源的浪费);
  • Session对象由服务器创建;

使用场景:

  • 保存用户登录的信息;
  • 购物车信息;
  • 在整个项目中经常访问到的数据,保存在Session中;

实例:

​ s1:获得session 的id,查看session是否已经存在,给session设置属性;

​ s2:得到session中的属性值

​ s3:使session失效;

s1:

package com.study;

import com.study.pojo.Person;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

import java.io.IOException;
import java.io.PrintWriter;

public class SessionDemo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //先解决乱码问题
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

        //获得session
        HttpSession session = req.getSession();

        //往session中存信息
        session.setAttribute("name", new Person("Lemon", 1));
        //获得session的id
        String id = session.getId();

        //判断session是否是新创建的
        if (session.isNew()) {
            PrintWriter writer = resp.getWriter();
            writer.write("session创建成功!ID:" + id);
        } else {
            resp.getWriter().write("session已经存在!ID为" + id);
        }

    }

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

s2:

//先解决乱码问题
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");

//获得session
HttpSession session = req.getSession();

//得到属性,输出到控制台
Person person = (Person) session.getAttribute("name");

System.out.println(person);

s3:

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    HttpSession session = req.getSession();
    Object name = session.getAttribute("name");
    //手动注销session
    session.invalidate();
}

在web.xml中设置session的有效时间:

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

8、JSP

1、什么是JSP?

JSP:java server pages;Java服务器端页面,和Servlet一样属于动态web技术

特点:

  • JSP像在写html;
  • 区别:
    • html 只给用户提供静态的数据;
    • jsp页面中可以嵌入java代码,提供动态数据;

2、JSP原理

思路:JSP怎么执行的?

  • 代码层面,服务器文件中jsp文件还是jsp文件;

  • 服务器内部工作:

    • Tomcat中有一个work目录:

      image-20220528183020192

    • IDEA中使用Tomcat也会在IDEA的Tomcat工作空间中生成一个work目录:

      image-20220528183757161
      image-20220528183826671
      C:\Users\Hanzo\AppData\Local\JetBrains\IntelliJIdea2021.3\tomcat\54acedf1-7fb2-4912-999b-53e632cac06c\work\Catalina\localhost\javaweb_session_cookie_war_exploded\org\apache\jsp
    • 发现在work中jsp文件转换为了java文件;

  • 分析:

    • 浏览器向服务器发送请求,不论是访问什么资源,其实都是访问Servlet!

    • jsp文件在被访问的过程中,最终还是转换为了一个java文件!

    • 所以,JSP本质上还是一个Servlet文件;

    • 打开index_jsp.java,能发现其中的初始化,销毁,服务请求、响应方法(同Servlet中的方法)

      public void _jspInit() {
        }
      
        public void _jspDestroy() {
        }
      //JSPService
        public void _jspService(HttpServletRequest request,HttpServletResponse response) throws java.io.IOException, jakarta.servlet.ServletException {
      
      • 在这个转换的java文件的service方法中:

        1. 判断请求;

        2. 内置了一些对象:

          //页面上下文,
          final jakarta.servlet.jsp.PageContext pageContext;
          //session
          jakarta.servlet.http.HttpSession session = null;
          //applicationContext
          final jakarta.servlet.ServletContext application;
          //config
          final jakarta.servlet.ServletConfig config;
          //out!
          jakarta.servlet.jsp.JspWriter out = null;
          //page:当前
          final java.lang.Object page = this;
          //请求
          HttpServletRequest request
          //响应
          HttpServletResponse response
          
        3. 输出页面前,增加了一些代码:

          response.setContentType("text/html");		//设置响应的页面类型
          pageContext = _jspxFactory.getPageContext(this, request, response,
                                                    null, true, 8192, true);
          _jspx_page_context = pageContext;
          application = pageContext.getServletContext();
          config = pageContext.getServletConfig();
          session = pageContext.getSession();
          out = pageContext.getOut();
          _jspx_out = out;
          
        4. 以上这些变量可以再JSP中直接使用;

      • JSP页面在服务器的执行流程:

        image-20220528185806306
      • 在JSP页面中:

        • 只要是Java代码就会原封不动的输出

        • 如果是HTML代码,就会转换为:

          out.write("<html>\n");
          out.write("<body>\n");
          out.write("<h2>Hello World!</h2>\n");
          out.write("</body>\n");
          out.write("</html>\n");
          

          这种样式进行输出渲染;

3、JSP基础语法

补充:IDEA建立一个普通maven项目,在通过添加支持转换为web项目

  1. 创建普通项目:

    image-20220529175221628
  2. 添加支持:

    image-20220529175300333
    image-20220529175319792
    image-20220529175343267
  3. 不过这种方式插入的项目结构跟标准的maven目录结构不一样

    • 创建jsp项目需要导入的包:

      <dependencies>
              <!--Servlet依赖-->
              <dependency>
                  <groupId>javax.servlet</groupId>
                  <artifactId>servlet-api</artifactId>
                  <version>2.5</version>
              </dependency>
              <!--JSP依赖-->
              <dependency>
                  <groupId>javax.servlet.jsp</groupId>
                  <artifactId>javax.servlet.jsp-api</artifactId>
                  <version>2.3.3</version>
              </dependency>
              <!--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>
          </dependencies
      
  4. 给项目配置Tomcat环境;

​ 任何语言都有自己的语法,JSP作为java技术的一种应用,不仅支持java的所有语法,还额外扩充了一些语法(了解即可);

JSP表达式

<%--  jsp表达式
  作用:用来将程序的输出,输出到客户端页面
--%>
<%= new java.util.Date()%>

JSP脚本片段

jsp脚本片段:

  <%
    for (int i = 0; i < 5; i++) {
      out.println(i);
    }
  %>
  • 脚本片段和html代码嵌套、交替使用;

  • 作用域问题:

    • 脚本中的作用域都是在jsp.java文件中的service方法中的局部变量;注意同名问题;

    • 要想定义全局的变量、方法,就需要使用jsp声明标签:<%! %>包裹起来;

      用该标签框起来的代码,被放在了类下的全局位置,打开work生成的java文件可以看到:

      image-20220529182224320

JSP声明

jsp声明:会被编译到JSP生成的Java类中,其他的生成到_jspService方法中;

jsp声明使用标签:<%! %>包裹起来;

在JSP中,嵌入java代码即可;

EL表达式:${};

小结

<%%>	---代码块
<%=%>  	--输出到页面
<%!%>	---声明
<%--注释--%>

JSP 注释 与 html注释 在JSP代码中的差异:

JSP的注释不会在客户端中显示,而html的注释会显示;

image-20220529183118098
image-20220529183129527

4、JSP指令

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

错误页面的转发:

<%@ page errorPage="error/500.jsp" %> 直接在jsp页面头部写入错误转发指令(注意我这里如果用了<%=out.print(1/0)%>它并没有给我转发到我的页面,我也不知道原因)
image-20220529185245898 另一种方法是在web.xml中配置响应的page属性,也能实现错误时的页面转发;(修改web.xml的话,就需要重启Tomcat)

注意:这里转发page的时候,如果在另外一个jsp中


页面公用部分拼接:

<%@include file="/common/header.jsp" %> <h2>项目主体</h2> <%@include file="common/footer.jsp" %> image-20220529190327914
header.jsp image-20220529190347449
footer.jsp image-20220529190401356
效果 image-20220529190443966
  • 还可以用另外一种写法,JSP标签<jsp:include page="common/header.jsp"/>

    image-20220529190754938 image-20220529190803866

注意:JSP标签 & <%@%> 两种标签拼接方式的差异:

jsp:include page="" @include file=""
拼接页面,本质上还是三个页面; @include会将多个页面合为一个html页面(一套html代码)
image-20220529191619291
image-20220529191452007
灵活性更高(常用)
在被拼接的页面中如果也有java的代码,并且与主页面的变量名可以重复,不会冲突 这种方式如果有重名的java变量,就会报错500

5、9大内置对象

  • PageContext 存东西;
  • Request 存东西;
  • Response ;
  • Session 存东西;
  • Application 【ServletContext】 存东西;
  • config 【ServletConfig】;
  • out;
  • page;不用了解
  • Exception;

pageContext:保存的数据只能在一个页面中有效,一旦跳转到其他页面就无法访问了;

request:在一次请求过程中有效,请求转发会携带这个信息数据;客户端向服务器发送请求,产生的数据,在传递转发到下一个页面之后就没用了,比如:新闻;

session:保存的数据在一次会话中有效,打开浏览器到关闭浏览器;客户端向服务器发送请求,服务器替一个用户(客户端)保存数据,待会儿可能还会使用,比如:购物车;

application:保存的数据在服务器中有效,打开服务器到关闭服务器有效;客户端向服务器发送请求,产生的数据保存在服务器端,一个用户用完了,其他的用户也可以访问使用;

6、JSP标签、JSTL标签、EL表达式

导入需要的包:

<!--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>

EL表达式:$

  • 获取数据;
  • 执行运算;
  • 获取web开发的常用对象;

作用域获取(当不同作用域存储键值对中的 key 相同时,想要直接获取该域对象的值可以通过 EL 表达式的方式)

<%-- EL 表达式的方式 --%>
<%-- 在作用域范围我们的名字取成一样了,怎么去找到特定的一个作用域中的值呢?? --%>
  	${pageScope.name}
  	${requstScope.name}
<%-- session比较特别,因为session是存在浏览器中的,只有关闭浏览器之后才可以拿到后面作用域中的值 --%>
  	${sessionScope.name}
  	${applicationScope.name}

JSP标签:

<%jsp:include%>

<%-- http://localhost:8080/jsptag.jsp?name=kuangshen&age=12 --%>
<%--等价于--%>
<jsp:forward page="/jsptag.jsp">
	<jsp:param name="name" value="kuangshen"></jsp:param>
    <jsp:param name="age" value="12"></jsp:param>
</jsp:forward>

JSTL标签:

JSTL标签库的使用就是为了弥补HTML标签的不足,自定义了许多的标签类,可以供我们使用,标签的功能和java代码一样;

  • 核心标签:(掌握部分)
  • 格式化标签:
  • SQL标签:
  • XML标签:

JSTL标签库使用步骤:

  1. 引入对应的taglib:
  2. 使用其中的标签;
  3. 注意:在Tomcat服务器中也需要引入JSTL的包,否则会报错;JSTL解析错误!

9、JavaBean

实体类
JavaBean有特定的写法:

  • 必须要有一个无参构造;
  • 属性必须私有化;
  • 必须有对应的get/set方法;

一般用来和数据库的字段做映射;

ORM:对象关系映射

  • 表-->类;
  • 字段-->属性
  • 行---->类对象

10、MVC三层架构

什么是MVC: Model View Controller 模型 视图 控制器

11、Filter过滤器

filter过滤器:过滤网站的请求、数据

  • 处理中文乱码;
  • 登录验证;
web 服务器启动后,过滤器加载初始化

//chain:链
1.过滤的所有代码,在过滤特定请求的时候都会执行;
2.必须要让过滤器继续通行;		chain.doFilter(request,respone);

web服务器关闭时,过滤销毁;

12、监听器

实现一个监听器接口:(有N种)

实例:

编写监听网站在线访问人数!

13、过滤器、监听器的常见应用

用户登录之后才能进入主页,注销之后无法进入主页。

注意点:

  • 页面中经常需要用到的值,例如用户登录之后保存在session中的user_session,可以再src下去创建一个静态常量的类,(有点类似枚举),Constant类,去给会反复用到的值定义一个变量名,例如:

    plubic class Constant{
    	public final static String USER_SESSION="USER_SESSION";
    }
    

    这么做的好处是,方便后期对他的值进行修改;(例如重命名)

  • 权限管理:可以利用过滤器,在过滤器中对服务器中保存的对象进行等级判断,然后跳转到不同的界面;

14、JDBC回顾

JDBC:连接数据库的接口

jar包依赖:

  • java.sql
  • javax.sql
  • mysql-connecter-java 连接驱动(必须导入)

事务

ACID原则:保证数据安全;

开启事务
提交事务  commit()
事务回滚  rollback()
关闭事务

补充知识点:

Test单元测试,可以直接执行方法,不需要main方法在调用(只在方法上有效)

package org.junit

@Test

JDBC中通知数据库开启事务,setAutoCommit(false);

//false 是开启,即关闭自动提交	
connection.setAutoCommit(false);

// 提交
connection.commit();

一般在事务中通过捕获异常,让事务回滚;

try{
	//执行事务
    
}catch(Eception e){
    try{
		//如果事务出现异常,回滚
		connection.rollback();
    }catch(SQLException e1){
    e1.printStackTrace();
    }
    e.printStackTrace();
}finally{
    //关闭资源
    connection.close();
}

项目:SMBMS----超市订单管理系统

详细见项目管理笔记;

BaseDao:

关闭jdbc连接资源的方法:

public static boolean closeResource(Connection conn,PreparedStatement pst,ResultSet rs){
    boolean flag=true;
    if(resultSet!=null){
        try{
            resultSet.close();
            //设置为空,让GC回收
            resultSet=null;
        }catch(SQLException e){
            e.printStackTrace();
            flag=false;
        }
    }
    if(pst!=null){
        try{
            pst.close();
            //设置为空,让GC回收
            pst=null;
        }catch(SQLException e){
            e.printStackTrace();
            flag=false;
        }
    }
    if(conn!=null){
        try{
            conn.close();
            //设置为空,让GC回收
            conn=null;
        }catch(SQLException e){
            e.printStackTrace();
            flag=false;
        }
    }
    return flag;
}

posted @ 2022-06-21 23:51  devynlime  阅读(334)  评论(0编辑  收藏  举报