javaweb 学习笔记 (2021.10.29~11.2)

JavaWeb

目录

一、web基本概念

Java web

1. 基本概念

web开发:

  • web,网页的意思
  • 静态web
    • html,css
    • 提供给所有人的数据不会有任何变化
  • 动态web
    • 提供给所有人的数据会有任何变化,人人看到的信息各不相同
    • 几乎所有网站
    • 技术栈:servlet/JSP、ASP,PHP

在Java中,动态web资源开发的技术统称为Javaweb。

2. web应用程序下

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

  • a.html、b.html……多个web资源,这些可以被外部调用,然后可以提供服务

  • 你们能访问到的任何一个页面或者资源,都存在这个世界上某个计算机上。

  • url

  • 这个统一的web资源会被放在同一个文件夹下,web应用程序--->Tomcat:服务器

  • 一个web应用由多个部分组成(静态web,动态web)

    • html,css,js
    • jsp,servlet
    • java程序
    • jar包
    • 配置文件(Properties)

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

3. 静态web

  • .htm、.html,如果一个服务器上以制存有这些东西,我们就可以直接进行读取,通过网络。

  • image

  • 静态web存在的缺点

    • 无法动态更新,永远是同一个页面
      • 轮播图:伪动态
      • JavaScript(用的多)
      • VBScript
    • 无法和用户交互,数据无法持久化,用户无法交互

4. 动态web

页面会动态展示:Web展示的效果因人而异

image

缺点

  • 假如动态资源出现错误,我们需要重新编写后台程序,重新发布
    • 停机维护

优点

  • 可以动态更新,不是是同一个页面
    • 轮播图:伪动态
    • JavaScript(用的多)
    • VBScript
  • 可以和数据库交互,数据持久化(持久化:注册,商品信息)

二、web服务器讲解

1. 技术讲解

ASP

  • 微软:国内最早流行
  • HTML中嵌入了VB脚本,ASP+COM
  • 在ASP开发中,一个页面的业务代码庞杂而乱,不宜与维护,可能有几千行代码
  • C#
  • IIS

PHP

  • 开发速度快,功能强大,跨平台,代码简单(70%)
  • 无法承载大访问量情况(局限性)

JSP/Servlet

  • sun公司主推的B/S架构
  • 基于Java语言(大公司和开源组件都用Java)
  • 承载高并发、高承载、高性能问题
  • 语法向ASP

2. web服务器

服务器是被动操作,用来处理请求和返回响应信息

IIS

微软的;ASP...,Windows中自带的

Tomcat

面向百度编程

对初学者来说,是最佳选择,免费

工作3-5年后尝试手写Tomcat;

下载Tomcat:

  1. 安装或解压
  2. 了解配置文件及目录结构
  3. 连接这个东西的作用

三、Tomcat详解

1.安装解压

image

image

2. Tomcat的启动和配置

文件夹作用

image

启动关闭Tomcat

image

访问测试 127.0.0.1:8080

可能遇到问题

  1. java环境变量没配
  2. 闪退问题:配置兼容性
  3. 乱码问题:配置文件设置

服务器核心配置文件

image

可以配置

  • 启动端口号

    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    
  • 主机名称

    <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
    
    • 默认主机名localhost->127.0.0.1
    • 默认网站应用存放的位置为:webapps
  • 高难度面试题

    请你谈谈网站时如何进行网站的

    1. 输入域名;回车

    2. 检查本机hosts配置文件下有无域名配置

      1. 有:直接返回对应地址,这个地址中有我们要访问的web程序,如果可以直接访问,就访问

      2. 没有:到DNS服务器中找(全世界域名在这个服务器),找不到就返回找不到

        image

  • 可配置环境变量(可选)

3. 发布一个web网站

  • 把自己的网页放到webapps文件夹下就可以访问了

网站应该有的结构

--webapps:tomcat服务器的web资源目录
    -root:默认目录
    -xiaowei:网站的目录名
    	-web-inf
    		-classes:Java程序
            -lib:web应用依赖的jar包
            -web.xml:网站配置文件
        -index.html 默认首页
        -static
            -css
            -js
            -img
        -...

四、Http讲解

1. 什么是Http

超文本传输协议(Hyper Text Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。

  • 文本:html,字符串,……
  • 超文本:图片、视频、音乐,……
  • 80默认端口

Https:安全的

  • 443

2. 两个时代

  • http1.0
    • http/1.0:客户端可以和web服务器连接后只能获取一个资源,断开连接
  • http2.0
    • http/1.1:客户端可以和web服务器连接后可获取多个资源。

3. http请求

客户端---发请求(request)---服务器

百度

Request URL: https://www.baidu.com/    //请求地址
Request Method: GET					// get方法/post方法
Status Code: 200 OK					//状态码:200
Remote Address: 183.232.231.172:443
Referrer Policy: strict-origin-when-cross-origin
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
  • 请求方式:GET/POST/HEAD/DELETE/PUT/TRACT
    • get:请求参数少,大小有限值,不安全但是高效
    • post:请求参数无限制,大小无限值,安全但是不高效

消息头

Accept:高速浏览器,它所支持的类型
Accept-Encoding:支持哪种编码格式UTF-8 GBK
Accept-Language:告诉浏览器,它应该用的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
HOST:主机
    .....

4. http响应

服务器----给响应

百度

Cache-Control: private	缓存控制
Connection: keep-alive	连接
Content-Encoding: gzip	编码
Content-Type: text/html;charset=utf-8	类型

响应体

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

响应状态码(重点)

200:请求响应成功

3xx:请求重定向

  • 你重新到我指定的新位置

4xx:找不到资源

5xx:服务器代码错误 500 502:网关错误

常见面试题:

当你的浏览器中地址栏输入地址并回车的一瞬间,到页面能展示回来,经历了什么

五、Maven环境搭建

我为什么要学习Maven?

  1. 在javaweb开发中需要使用大量jar包,需要手动导入

  2. 如何能够让一个东西帮我导入配置jar包。

    由此,Maven诞生了!

1. Maven项目架构管理工具

我们目前用它来方便导入jar包的!

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

  • 有约束就别区违反

Maven会规定好你如何区编写我们的Java代码,必须按照这个规定来!

2. 下载安装Maven

image

下载完解压(尽量自己弄个文件夹专门放这些东西)

3. 配置环境变量

配置如下配置:

  • M2_HOME :Maven的bin目录
  • MAVEN_HOME:Maven目录
  • 在系统Path中配置Maven目录 %MAVEN_HOME%\bin(多了个MAVEN_HOME的变量是因为之后的学习的框架会引用这个变量)

cmd中使用指令查看是否安装成功

mvn -version

image

4. 修改配置镜像

阿里云镜像:加速你的文件下载

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

5. 本地仓库

建立一个仓库(本地、远程)

建立本地仓库:localRepository

  <!-- localRepository
   | The path to the local repository maven will use to store artifacts.
   | 默认的地方↓
   | Default: ${user.home}/.m2/repository   
  <localRepository>/path/to/local/repo</localRepository>
  -->
  <localRepository>E:\Environment\apache-maven-3.8.3\maven-repo</localRepository>
	<!--这里放你自己的指定仓库 -->

六、IDEA中Maven的操作

1. 配置Maven

  1. 启动IDEA

  2. 创建Maven项目

    image

    确定名字

    image

    确定配置和仓库

    image

  3. 等待项目搭建

    成功如图:

    image

  4. 观察本地仓库中多了什么?

  5. IDEA中的Maven设置

    image

    自动导入源码(可选)

    image

    选中配置文件:也可以不选

    image

  6. 到这里,Maven在IDEA的设置和配置就OK了

  7. 目录结构

    image

    标记了目录才能新建响应文件:

    image

    这样也可以标记目录

    image

2. IDEA配置Tomcat

  1. 点击配置文件

    image

  2. 点击加号

    image

  3. 选中TomcatServer

    image

  4. Tomcat选项

    image

    image

    解决警告办法:

    为什么会有这个问题:我们访问一个网站需要一个文件夹名字

    image

  5. 启动Tomcat

    image

3. Maven目录结构

image

<?xml version="1.0" encoding="UTF-8"?>

<!--Maven版本和头文件-->
<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>

  <!--这里就是刚刚配置的GAV-->
  <groupId>com.xiaowei</groupId>
  <artifactId>javaweb-01-maven</artifactId>
  <version>1.0-SNAPSHOT</version>
  <!--packaging:项目的打包方式
  jar:Java应用
  war:Javaweb应用
  -->
  <packaging>war</packaging>

  <name>javaweb-01-maven Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <!--配置-->
  <properties>
    <!--项目默认的建构编码-->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <!--编码版本-->
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <!--项目依赖-->
  <dependencies>
    <!--具体依赖的jar包配置文件-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <!--项目构建用的东西-->
  <build>
    <finalName>javaweb-01-maven</finalName>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>3.2.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

4. Maven功能与问题

功能

<?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>com.xiaowei</groupId>
    <artifactId>javaweb-02-maven</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>

        <!--Maven的高级之处在于帮助你导入这个jar所依赖的其他jar-->
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.12</version>
        </dependency>

    </dependencies>

</project>

问题:

Maven由于他的约定大于配置,我们之后可能遇到我们写的配置文件,无法被导出或者生效的问题

解决方案

<build>
    <!--在build中配置resource,防止资源导出失败问题-->
    <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. IDEA使用Maven的功能

生成目录树:maven中jar包的依赖体系

image

☆可能的问题

https://www.bilibili.com/video/BV12J411M7Sj?p=7&spm_id_from=pageDriver

八、HelloServlet

1. 添加jar依赖

  • 本地仓库没有,IDEA中也没有搜索到
  • 去网上Maven仓库搜索HttpServlet也没找到
  • 到tomcat的依赖jar包中找寻相关的jar包
  • 发现一个servlet-app包
  • 再次去网上Maven仓库搜索servlet-app包
  • 找到人最多的,复制依赖xml
  • 粘贴到pom.xml配置文件中
  • 自动下载依赖

2. 配置web.xml和servlet类

web.xml:

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0"
         metadata-complete="true">

  <!--web.xml中是配置我们web的核心应用-->
  <!--注册servlet-->
  <servlet>
    <servlet-name>helloServlet</servlet-name>
    <servlet-class>com.xiaowei99.servlet.HelloServlet</servlet-class>
  </servlet>
  <!--一个servlet对应一个Mapping-->
  <servlet-mapping>
    <servlet-name>helloServlet</servlet-name>
    <!--请求路径-->
    <url-pattern>/xiaowei</url-pattern>
  </servlet-mapping>

</web-app>

servlet类:

package com.xiaowei99.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf-8"); //设置响应回去的编码
        PrintWriter out = resp.getWriter();
        out.println("<html>");
        out.println("<head>");
        out.println("<title>Hello World!</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>你好</h1>");
        out.println("</body>");
        out.println("</html>");
    }

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

3. servlet简介

  • sun公司用于开发动态web资源的技术
  • sun在这些api中提供一个接口叫做Servlet,如果你想开发一个servlet程序,只需要完成两个步骤
    • 编写一个类,实现servlet接口
    • 把开发好的Java类部署到服务器中

把实现了Servlet接口的Java程序叫做Servlet。

4. HelloServlet

  1. 构建一个普通的Maven项目,删掉不必要的东西(src),以后我们学习就在这个项目里面新建Moudel,这个空的工程就是Maven的主工程

  2. 关于Maven父子工程的理解

    父项目中有moudel标签

    <modules>
        <module>servlet-01</module>
    </modules>
    

    子项目中有parent标签

    <parent>
      <groupId>com.xiaowei</groupId>
      <artifactId>javaweb-04-servlet</artifactId>
      <version>1.0-SNAPSHOT</version>
    </parent>
    

    父项目中的jar子项目可用

  3. Maven环境优化

    1. 修改web.xml为最新的
    2. 将maven的结构搭建完整
  4. 编写一个Servlet类

    1. 编写普通类继承于httpservlet继承于generalservlet类实现于servlet接口

    2. 实现servlet接口,直接继承HttpServle

      package com.xiaowei99.servlet;
      
      
      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import java.io.IOException;
      import java.io.PrintWriter;
      
      public class MyServlet extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              resp.setContentType("text/html");
              resp.setCharacterEncoding("utf-8"); //设置响应回去的编码
              PrintWriter out = resp.getWriter();
              out.println("<html>");
              out.println("<head>");
              out.println("<title>Hello World!</title>");
              out.println("</head>");
              out.println("<body>");
              out.println("<h1>你好</h1>");
              out.println("</body>");
              out.println("</html>");
          }
      
          @Override
          protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              doGet(req, resp);
          }
      }
      
  5. 编写Servlet映射

    为什么要写映射?我们写的是Java程序,如果要通过浏览器访问,则需要连接web服务器,我们需要在web服务器中的配置文件中注册我们的Servlet,需要给浏览器一个路径。

  6. 配置Tomcat,设置项目名

  7. 启动项目

九、Servlet原理

Servlet是由web服务器调用,web服务器在收到浏览器请求后会:

image

Mapping问题

  • 一个Servlet可以指定一个映射路径
  • 一个Servlet可以指定多个映射路径
  • 一个Servlet可以指定通用映射路径
  • 用过通配符*指定一些后缀或前缀等等....
  • 优先级问题,指定了固定路径的映射优先级高,然后通配符*的路径优先级低

十、SelvletContext对象

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

  • 共享数据

放入数据:

package com.xiaowei.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //this.getInitParameter() 初始化参数
//        this.getServletConfig() 获取Servlet配置
//        this.getServletContext() 获取Servlet上下文

        ServletContext servletContext = this.getServletContext();
        servletContext.setAttribute("username","xiaowei99"); //在上下文中放入username xiaowei99


    }

}

另一个servlet获得数据

package com.xiaowei.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;

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");//获取上下文中的数据username

        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf-8");
        resp.getWriter().print("名字"+username);
    }
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0"
         metadata-complete="true">


  <servlet>
    <servlet-name>helloServlet</servlet-name>
    <servlet-class>com.xiaowei.servlet.MyServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>helloServlet</servlet-name>
    <url-pattern>/s2</url-pattern>
  </servlet-mapping>


  <servlet>
    <servlet-name>get</servlet-name>
    <servlet-class>com.xiaowei.servlet.GetServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>get</servlet-name>
    <url-pattern>/get</url-pattern>
  </servlet-mapping>

</web-app>

十一、SelvletContext应用

1. 获取初始化参数

web.xml:

<context-param>
  <param-name>connUrl</param-name>
  <param-value>jdbc:mysql://localhost:3306</param-value>
</context-param>

class:

ServletContext context = this.getServletContext();
String connUrl = context.getInitParameter("connUrl");
resp.getWriter().print(connUrl);

2. 请求转发Dispatcher

context.getRequestDispatcher("/gs").forward(req,resp);

请求转发和重定向的区别

请求转发是:当前页面请求转发至另一个页面的时候,本质上还在自己的页面,用的是自己的请求行请求头响应行响应头:因为抓包发现状态码还是200.

重定向是:本质已经是另一个页面了,request和respond都已经改变。

3. 读取资源文件

如果没有在Maven文件的build中配置resource,那么如果你的资源文件比如db.properties如果不在标记的resource文件夹下,启动服务器时你的类文件夹(classes)就不生成你的资源文件

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    ServletContext context = this.getServletContext();
    InputStream resource = context.getResourceAsStream("/WEB-INF/classes/db.properties");
    Properties properties = new Properties();
    properties.load(resource);

    resp.getWriter().print(properties.getProperty("username"));
}

十二、Response下载文件

web服务器接收到客户端的http请求,针对这个请求,针对这个请求,就生成了request和response方法

  • 获取客户端请求过来的参数,找request
  • 返回给客户端的信息:response

发送给浏览器的方法:

PrintWriter getWriter() throws IOException;
ServletOutputStream getOutputStream() throws IOException;

发送给浏览器响应头的方法:

void setCharacterEncoding(String var1);

void setContentLength(int var1);

void setContentLengthLong(long var1);

void setContentType(String var1);

void setBufferSize(int var1);

void setLocale(Locale var1);

void setIntHeader(String var1, int var2);

void addIntHeader(String var1, int var2);

void setHeader(String var1, String var2);

void setDateHeader(String var1, long var2);

void setStatus(int var1);

void addDateHeader(String var1, long var2);

响应状态码

int SC_CONTINUE = 100;
int SC_SWITCHING_PROTOCOLS = 101;
int SC_OK = 200;
int SC_CREATED = 201;
int SC_ACCEPTED = 202;
int SC_NON_AUTHORITATIVE_INFORMATION = 203;
int SC_NO_CONTENT = 204;
int SC_RESET_CONTENT = 205;
int SC_PARTIAL_CONTENT = 206;
int SC_MULTIPLE_CHOICES = 300;
int SC_MOVED_PERMANENTLY = 301;
int SC_MOVED_TEMPORARILY = 302;
int SC_FOUND = 302;
int SC_SEE_OTHER = 303;
int SC_NOT_MODIFIED = 304;
int SC_USE_PROXY = 305;
int SC_TEMPORARY_REDIRECT = 307;
int SC_BAD_REQUEST = 400;
int SC_UNAUTHORIZED = 401;
int SC_PAYMENT_REQUIRED = 402;
int SC_FORBIDDEN = 403;
int SC_NOT_FOUND = 404;
int SC_METHOD_NOT_ALLOWED = 405;
int SC_NOT_ACCEPTABLE = 406;
int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
int SC_REQUEST_TIMEOUT = 408;
int SC_CONFLICT = 409;
int SC_GONE = 410;
int SC_LENGTH_REQUIRED = 411;
int SC_PRECONDITION_FAILED = 412;
int SC_REQUEST_ENTITY_TOO_LARGE = 413;
int SC_REQUEST_URI_TOO_LONG = 414;
int SC_UNSUPPORTED_MEDIA_TYPE = 415;
int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
int SC_EXPECTATION_FAILED = 417;
int SC_INTERNAL_SERVER_ERROR = 500;
int SC_NOT_IMPLEMENTED = 501;
int SC_BAD_GATEWAY = 502;
int SC_SERVICE_UNAVAILABLE = 503;
int SC_GATEWAY_TIMEOUT = 504;
int SC_HTTP_VERSION_NOT_SUPPORTED = 505;

下载文件

package com.xiaowei.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Set;

public class ServlerDemo06 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        String path = "E:\\程序学习\\学习时的代码\\jspstudy\\javaweb-04-servlet\\servlet_02\\src\\main\\resources\\1.jpg";
        String filename = path.substring(path.lastIndexOf("\\")+1);


        resp.setHeader("Content-disposition","attachment;filename="+ URLEncoder.encode(filename,"utf-8"));
        FileInputStream fin = new FileInputStream(path);
        ServletOutputStream os = resp.getOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while((len = fin.read(buffer))>0){
            os.write(buffer,0,len);
        }
        os.close();
        fin.close();
    }

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

十三、Response验证码实现

  • 前端实现
  • 后端实现:使用java图片类
package com.xiaowei.servlet;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStreamImpl;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

public class ServletDemo07 extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setHeader("refresh","3");
        BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
        Graphics graphics = image.getGraphics();
        graphics.drawString(getRandom(),20,20);

        resp.setDateHeader("expires",-1);
        resp.setHeader("Cache-Control","no-cache");
        resp.setHeader("Pragma","no-cache");

        ImageIO.write(image, "jpg", resp.getOutputStream());
    }

    public String getRandom(){
        Random random = new Random();
        String s = random.nextInt(999999)+ "";
        StringBuffer stringBuffer = new StringBuffer(s);
        for (int i = 0; i < 6-s.length(); i++) {
            stringBuffer.append("0");
        }
        return stringBuffer.toString();
    }

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

十四、Response重定向

常见场景:

  • 用户登录,登陆成功跳转(重定向)
  • .......
void sendRedirect(String var1) throws IOException;

重定向:

resp.sendRedirect("/servlet_02_war/sd7");

使用jsp:

接收请求servlet

package com.xiaowei99;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class JspDemo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入请求了");
        String username = req.getParameter("username");//获取请求中的参数
        String password = req.getParameter("password");
        System.out.println(username+":"+password);
        resp.sendRedirect("/servlet_03_war/success.jsp");//重定向
    }

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

发送请求jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h2>Hello World!</h2>
<form action="${pageContext.request.contextPath}/login" method="get">
    <p>用户名: <input type="text" name="username"></p>
    <p>密码: <input type="password" name="password"></p>
    <input type="submit" value="确定">
</form>

</body>
</html>

十五、Request应用

Request代表客户端的请求,用户通过http协议访问服务器,请求的所有信息封装到request中,通过这个对象我们可以获得请求的所有信息

req.getParameterValues("hobbys");//获取多个参数,用于前端checks的
req.getParameter("password");//获取单个参数
//解决后台接收乱码:
req.setCharacterEncoding("utf-8");

十六、Cookie讲解

会话:打开浏览器,打开很多连接,访问了很多web资源,关闭浏览器,这个过程可以称之为会话

有状态会话:一个同学来过教室,下次再来就知道了,这一次来教室就是有状态会话

你能怎么证明你是你学校的学生?

  • 交钱发票 学校给你的发票
  • 学校登记花名册 学校标记你是学生

网站怎么证明你来过?

客户端 服务端

  • 服务端给客户端一个信件,客户端下次带上信件就认得了(cookie)
  • 服务端登记客户端,下次来直接就匹配保存的登记信息就好啦(session)

cookie

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

session

  • 服务器技术,利用这个技术,可以保存用户的会话信息。我们可以把信息或者数据放在session中。

登录后,一段时间就不需要登录你信息也在网页上!

image

基本方法

Cookie[] cookies = req.getCookies();//获得所有cookie
Cookie cookie = new Cookie();//新建cookie
resp.addCookie(cookie);//向客户端发送cookie
cookie.getName();//获得cookie的name
cookie.getValue();//获得cookie的value
cookie.setMaxAge(24*60*60);//存活时间,单位秒

使用

package com.xiaowei99.cookie;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

public class Demo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("GBK");
        resp.setCharacterEncoding("GBK");

        PrintWriter out = resp.getWriter();

        if (req.getCookies().length==4){
            out.print("这是你第一次访问");
        }else {
            out.print("你上一次访问的时间是:");
            Cookie[] cookies = req.getCookies();
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals("lastLoginTime")){
                    String time = cookie.getValue();
                    long l = Long.parseLong(time);
                    Date date = new Date(l);
                    out.print(date.toLocaleString());
                }
            }
        }
        Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
        cookie.setMaxAge(24*60*60);//存活时间,单位秒
        resp.addCookie(cookie);


    }

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

cookie:一般会保存在本地目录下的用户文件夹中的appdata文件夹

cookie是否存在上限:

  • 一个cookie只能保存一个信息
  • 一个web站点可以给浏览器发送多个cookie,最多20个
  • 大小限制4kb
  • 浏览器最多有300个cookie

删除cookie:

  • 不设置有效期,关掉浏览器自动失效
  • 设置maxAge为0,存活时间为0

十七、Session讲解(重点)

什么是session:

  • 服务器会给每一个用户(浏览器)创建一个Session
  • 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在
  • 用户登录后,整个网站都可以访问-->保存用户信息;保存购物车信息....

session和cookie区别

  • cookie把用户的数据写给浏览器,浏览器保存(可以保存多个)
  • session是把用户的数据写到服务器,服务端保存(保存重要的信息,减少资源的浪费)
  • Session对象由服务器创建

image

使用场景:登录用户、购物车、整个网站中经常会使用的,我们放到Session中

image

基本使用

package com.xiaowei99.session;

import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;

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

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

        //给session中存东西
        session.setAttribute("name","xiaowei99");

        //获取session的id
        String id = session.getId();

        //判断是不是新分配session
        if(session.isNew()){
            resp.getWriter().print("session创建成功");
        }else {
            resp.getWriter().print("session已经创建,id:"+id);
        }

        //在创建session时做了什么
        //Cookie jsessionid = new Cookie("JSESSIONID", id);
        //resp.addCookie(jsessionid);


    }

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

获取数据

PrintWriter writer = resp.getWriter();
writer.print((String) session.getAttribute("name"));

remove相关

session.removeAttribute("name");//把结点删除
session.invalidate();//手动注销

context作用:统计不同用户

image

十八、JSP原理分析

1. 什么是服务器?

Java Server Pages:Java服务端页面,也和Servlet一样用于动态web技术。

特点:

  • 写JSP就像再写HTML
  • 区别:
    • html只提供静态数据
    • JSP页面中可以嵌入Java代码,为用户提供动态数据

2. JSP原理

思路:JSP怎么执行的

  • 代码层面没有任何问题

  • 服务器内部如何工作

    tomcat中有work目录:

    IDEA中使用Tomcat会在IDEA的tomcat中生成一个work目录(C盘用户目录中)

    C:\Users\Red\AppData\Local\JetBrains\IntelliJIdea2021.1\tomcat\9bb594c5-fed9-4bf9-ab65-40a15f0fcd72\work\Catalina\localhost\xiaowei99\org\apache\jsp

    发现页面变成了Java程序~

    image

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

    JSP最终变成Java类

    JSP本质就是Servlet

    public void _jspInit() {
    }//初始化
    
    public void _jspDestroy() {
    }//销毁
    
    //jspService
    public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
        throws java.io.IOException, javax.servlet.ServletException {}
    
  1. 判断请求

  2. 内置一些对象

    final javax.servlet.jsp.PageContext pageContext;//页面上下文
    javax.servlet.http.HttpSession session = null;	//session
    final javax.servlet.ServletContext application; //applicationcontext
    final javax.servlet.ServletConfig config;		//config
    javax.servlet.jsp.JspWriter out = null;			//out
    final java.lang.Object page = this;				//page:当前页
    final javax.servlet.http.HttpServletRequest request;	//请求
    final javax.servlet.http.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页面中直接使用

  5. 流程

    image

  6. 在JSP页面中,只要是Java代码就会被原封不动的执行,html就会被out.print()输出到前端

十九、JSP基础语法和指令

Maven依赖:

<?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>com.xiaowei</groupId>
  <artifactId>javaweb-jsp</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <dependencies>
    <!--Servlet-->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>javax.servlet.jsp-api</artifactId>
      <version>2.3.3</version>
    </dependency>
    <!--JSP-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
    </dependency>
    <!--JSTL表达式的依赖-->
    <!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
    <dependency>
      <groupId>javax.servlet.jsp.jstl</groupId>
      <artifactId>jstl-api</artifactId>
      <version>1.2</version>
    </dependency>
    <!--standard标签库-->
    <!-- https://mvnrepository.com/artifact/taglibs/standard -->
    <dependency>
      <groupId>taglibs</groupId>
      <artifactId>standard</artifactId>
      <version>1.1.2</version>
    </dependency>

  </dependencies>
</project>

JSP可以使用任何Java语法,但是又有自己扩充的语法

表达式

<%--
JSP表达式:
    <%= var Object%>
    用来将程序变量输出到客户端
--%>
<%=new Date()%>

脚本片段

<%--
JSP脚本片段
--%>
<%
    int sum = 0;
    for (int i = 0; i < 10; i++) {
        sum+=i;
    }
    out.print("<h1>Sum="+sum+"</h1>");

%>

脚本片段再实现

<%--脚本片段再实现--%>

<%   for (int i = 0; i < 10; i++) {%>
    <h6>输出10次内容:第<%=i+1%>次</h6>
    <hr>
<%    }%>

定义java文件类下的变量,jsp声明,会被编译到类中,其他的都是在方法中

<%!
static {
    System.out.println("加载了Servlet");
}
public void aVoid(){
    System.out.println("定义了一个方法");
}
%>

EL表达式

${var};

JSP的注释不会再客户端显示,html的会!

指定错误页面

<%@page errorPage="error/404.jsp" %>//该页面的错误跳转至此

<%@page isErrorPage="true" %>//这是个显示错误的页面

指定错误页面二:再web.xml中配置

<error-page>
    <error-code>400</error-code>
    <location>/error/404.jsp</location>
</error-page>

嵌入jsp:将两个页面合二为一

<%@include file="error/500.jsp"%>

jsp标签:会导入文件作为静态资源

<jsp:include page="error/500.jsp"/>

二十、JSP内置对象及作用域

1. 九大对象

  • PageContext 存东西
  • Request 存东西
  • Response
  • Session 存东西
  • Application(ServletContext)存东西
  • Config(Servlet config)
  • out
  • page
  • exception

2. 作用域

四个存东西的对象,作用域

找参数的时候:pageContext找不到---->request找不到---->session找不到---->application找不到--->null

pageContext.setAttribute("name1","xiaowei1");//只在一个页面中有效
request.setAttribute("name2","xiaowei2");//在一次请求中携带并有效
session.setAttribute("name3","xiaowei3");//在一次浏览器会话中有效
application.setAttribute("name4","xiaowei4");//服务器不重启都有效

pageContext.findAttribute("name1");
....

手动确定作用域,在pageContext可以用

public static final int PAGE_SCOPE = 1;
public static final int REQUEST_SCOPE = 2;
public static final int SESSION_SCOPE = 3;
public static final int APPLICATION_SCOPE = 4;

public void setAttribute(String name, Object attribute, int scope) {
    switch(scope) {
        case 1:
            this.mPage.put(name, attribute);
            break;
        case 2:
            this.mRequest.put(name, attribute);
            break;
        case 3:
            this.mSession.put(name, attribute);
            break;
        case 4:
            this.mApp.put(name, attribute);
            break;
        default:
            throw new IllegalArgumentException("Bad scope " + scope);
    }

}

3. 应用场景

request:用户用完就不用了,产生的数据需要丢掉:新闻...

session:用户用完还要用,产生的数据需要存一会:购物车...

application:用户用完了,其他用户可能还得用:统计数据、聊天数据...

二十一、JSP、JSTL、标签、EL表达式

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

1. EL表达式

  • 获取数据
  • 执行运算
  • 获取web开发常用对象
  • 格式${}

2. JSP标签

<%--jsp:include 包含页面--%>

<%--跳转页面--%>
<%--携带参数--%>
<jsp:forward page="jsptag2.jsp">
    <jsp:param name="name" value="xiaowei"/>
    <jsp:param name="age" value="22"/>
</jsp:forward>

3. JSTL标签

为了弥补HTML标签的内容功能的不足,自定义了许多标签可以供我们使用,标签的功能和Java代码一样

格式化标签

sql标签

XML标签

核心标签(掌握部分)

image

引入JSTL核心标签库:(还有其他的)

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

使用其中方法

<form action="JSTLtag.jsp" method="get">
    <%--EL表达式获取值
    ${param.var}
    --%>
    <input type="text" name="username" value="${param.username}">
        <input type="submit" value="登录">

</form>
<c:if test="${param.username=='admin'}" var="isAdmin">
    <c:out value="欢迎您${param.username}"></c:out>
</c:if>

<c:out value="${isAdmin}"></c:out>

选择标签:

<c:set var="score" value="${param.username}"></c:set>

<%--从上到下哪个先碰到就判断哪个,判断条件为真后,后面的条件不会再去判断--%>
<c:choose>
    <c:when test="${score>=90}">
        成绩优秀
    </c:when>
    <c:when test="${score>=80}">
        成绩良好
    </c:when>
    <c:when test="${score>=70}">
        成绩一般
    </c:when>
    <c:when test="${score>=60}">
        成绩及格
    </c:when>
</c:choose>

forEach:

<%
    ArrayList arrayList = new ArrayList();
    arrayList.add("张三");
    arrayList.add("李四");
    arrayList.add("王五");
    arrayList.add("赵六");
    arrayList.add("田七");
    request.setAttribute("peoples",arrayList);
%>

<%--var:进入了request的Attribute中,用于输出遍历出的值
    items:遍历的列表
    --%>
<c:forEach var="people" items="${peoples}">
    <c:out value="${people}"></c:out>
</c:forEach>

PS:标签中的var通常进入了request中的Attribute,EL表达式直接输入变量名可以获取,而如果是在request的Parameter中,EL表达式则需要${param.变量名}来获取

在Tomcat中也需要引入JSTL的jar包,否则会有JSTL引入错误

二十二、JavaBean

实体类

JavaBean有特定写法:

  • 必须有无参构造
  • 属性必须私有化
  • 必须有对应的getset

一般用来和数据库字段做映射:ORM:对象 关系 映射

  • 表-->类
  • 字段-->属性
  • 行记录-->对象
<%--创建一个
    类为com.xiaowei99.pojo.Person
    变量名为xiaowei
    有效范围是page
    的对象--%>
<jsp:useBean id="xiaowei" scope="page" class="com.xiaowei99.pojo.Person"></jsp:useBean>

<%--设置对象属性--%>
<jsp:setProperty name="xiaowei" property="id" value="1"></jsp:setProperty>
<jsp:setProperty name="xiaowei" property="name" value="xiaowei"></jsp:setProperty>
<jsp:setProperty name="xiaowei" property="age" value="22"></jsp:setProperty>

<%--获取对象属性--%>
<jsp:getProperty name="xiaowei" property="id"/>
<jsp:getProperty name="xiaowei" property="name"/>
<jsp:getProperty name="xiaowei" property="age"/>

之后使用的数据库:https://github.com/WalterWen/smbms/blob/master/smbms.sql(好人一生平安)。

二十三、MVC三层架构

什么是MVC:Model View Controller

模型(实体类)

视图(JSP)

控制器(Servlet)

image

用户直接访问控制层,控制层直接操控数据库

servlet--->CRUD --->数据库

弊端:程序臃肿,不利于维护

servlet中:处理请求、响应、视图跳转、处理jdbc、处理业务代码、处理逻辑代码

架构:没有什么是加一层解决不了的

JDBC

Mysql、Oracle、Sql Server

演进 三层架构MVC

image

Model:

  • 业务处理:业务逻辑(Service)
  • 数据持久层(CRUD)DAO层

View:

  • 展示数据
  • 提供链接发起servlet请求

Controller(Servlet)

  • 接受用户请求

  • 交给业务层处理相应代码

  • 控制视图跳转

    登录--->接收用户请求--->处理用户请求(获取用户登录参数,username,password....)--->交给业务层登录业务(判断用户名密码是否正确:事务)--->DAO层查询用户名和密码是否正确--->数据库

二十四、过滤器Filter(重点)

用来过滤网站的数据

  • 处理中文乱码
  • 登录验证
  • ....

开发步骤:

  1. 导包
  2. 编写过滤器

web.xml:

<filter>
    <filter-name>encoding</filter-name>
    <filter-class>com.xiaowei99.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>encoding</filter-name>
    <!--url-pattern指定的路径  servlet下的所有都过滤-->
    <url-pattern>/servlet/*</url-pattern>
    <!--servlet-name指定的已经注册了的servlet的名字-->
    <servlet-name>TestServlet</servlet-name>
</filter-mapping>

Filter:

package com.xiaowei99.filter;

import javax.servlet.*;
import java.io.IOException;

public class CharacterEncodingFilter implements Filter {//servlet下的Filter,不要加错了

    //初始化
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
        System.out.println("Filter初始化了");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("GBK");
        servletResponse.setCharacterEncoding("GBK");
        System.out.println("Filter执行前");
        filterChain.doFilter(servletRequest,servletResponse);
        //放行程序,不然程序就停止了,当有多个过滤器的时候,把请求和响应信息传递给下一个过滤器
        System.out.println("Filter执行后");
    }

    //销毁
    @Override
    public void destroy() {
        Filter.super.destroy();
        System.out.println("Filter销毁了");
    }
}

二十五、监听器Listener

实现一个监听器的接口,有很多种

编写监听器

package com.xiaowei99.listener;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

//统计在线人数
public class OnlineCountListener implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println(se.getSession().getId());
        ServletContext sc = se.getSession().getServletContext();
        Integer onlineCount = (Integer) sc.getAttribute("onlineCount");
        if (onlineCount==null){
            onlineCount = new Integer(1);
        }else {
            onlineCount+=1;
        }
        sc.setAttribute("onlineCount",onlineCount);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {

        ServletContext sc = se.getSession().getServletContext();
        Integer onlineCount = (Integer) sc.getAttribute("onlineCount");
        if (onlineCount==null){
            onlineCount = new Integer(0);
        }else {
            onlineCount-=1;
        }

        sc.setAttribute("onlineCount",onlineCount);

        /*
        * Session销毁:
        * 手动销毁:se.getSession().invalidate();
        * 自动销毁:配置session-config
        * <session-config>
        * <session-timeout></session-timeout>
        * </session-config>
        * */
    }
}

配置web.xml

<listener>
    <listener-class>com.xiaowei99.listener.OnlineCountListener</listener-class>
</listener>

看情况是否使用

二十六、监听器GUI中理解

回顾GUI部分

二十七、Filter实现权限拦截

登录拦截

使用的常量:

package com.xiaowei99.util;

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

过滤器class:没有SessionID不能登录

package com.xiaowei99.filter;

import com.xiaowei99.util.Constant;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

public class LoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;

        if (req.getSession().getAttribute(Constant.USER_SESSION)==null){
            resp.sendRedirect("/index.jsp");
        }

        chain.doFilter(request,response);
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}

web.xml中对主页注册过滤器:

<filter>
    <filter-name>loginfil</filter-name>
    <filter-class>com.xiaowei99.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>loginfil</filter-name>
    <url-pattern>/sys/*</url-pattern>
</filter-mapping>

二十八、JDBC复习

Maven导入包,其他回顾MySQL数据库阶段

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>

二十九、JDBC事务

测试方法,使用junit依赖

在方法上加入@Test注解即可执行

@Test
public void aVoid(){
    System.out.println("hello");
}

三十、smbms项目搭建

项目数据表结构

image

  1. 新建一个mavenweb项目

  2. 配置tomcat

  3. 测试项目是否能够跑起来

  4. 导入jar包(Maven依赖):JSP、Servlet、mysql、jstl、standard

  5. 创建项目包结构

    image

  6. 编写实体类

    ORM

  7. 编写基础公共类

    1. 编写数据库配置文件

      driver=com.mysql.jdbc.Driver
      url=jdbc:mysql://localhost:3306?useUnicode=true&characterEncoding=utf-8
      username=root
      password=123456
      
    2. 编写数据库公共类

      package com.xiaowei.dao;
      
      
      import java.io.IOException;
      import java.io.InputStream;
      import java.sql.*;
      import java.util.Properties;
      
      public class BaseDao {
          public static String driver;
          public static String url;
          public static String username;
          public static String password;
      
          static {
              //通过类加载器获得资源流
              InputStream inputStream = BaseDao.class.getClassLoader().getResourceAsStream("db.properties");
              Properties properties = new Properties();
              try {
                  properties.load(inputStream);
              } catch (IOException e) {
                  e.printStackTrace();
              }
      
              driver = properties.getProperty("driver");
              url = properties.getProperty("url");
              username = properties.getProperty("username");
              password = properties.getProperty("password");
      
          }
      
          //获取数据库链接
          public static Connection getConnection(){
              Connection conn = null;
              try {
                  Class.forName(driver);
                  conn = DriverManager.getConnection(url, username, password);
              } catch (Exception throwables) {
                  throwables.printStackTrace();
              }
              return conn;
      
          }
      
          //公共查询方法
          public static ResultSet execute(Connection connection,String sql,Object[] params,ResultSet resultSet,PreparedStatement ps) throws SQLException {
              ps = connection.prepareStatement(sql);
              for (int i = 0; i < params.length; i++) {
                  ps.setObject(i+1,params[i]);
              }
              resultSet = ps.executeQuery();
      
              return resultSet;
          }
      
          //公共增删改方法
          public static int execute(Connection connection,String sql,Object[] params,PreparedStatement ps) throws SQLException {
              ps = connection.prepareStatement(sql);
              for (int i = 0; i < params.length; i++) {
                  ps.setObject(i+1,params[i]);
              }
              int i = ps.executeUpdate();
              return i;
          }
      
          //释放资源
          public static boolean release(Connection connection,
                                     PreparedStatement preparedStatement,
                                     ResultSet resultSet
                                     ){
              boolean flag = true;
              if (connection!=null){
                  try {
                      connection.close();
                      connection=null;
                  } catch (SQLException throwables) {
                      throwables.printStackTrace();
                      flag=false;
                  }
              }
              if (preparedStatement!=null){
                  try {
                      preparedStatement.close();
                      preparedStatement=null;
                  } catch (SQLException throwables) {
                      throwables.printStackTrace();
                      flag=false;
                  }
              }
              if (resultSet!=null){
                  try {
                      resultSet.close();
                      resultSet=null;
                  } catch (SQLException throwables) {
                      throwables.printStackTrace();
                      flag=false;
                  }
              }
              return flag;
          }
      
      
      
      }
      
    3. 编写字符过滤器

      package com.xiaowei.filter;
      
      import javax.servlet.*;
      import java.io.IOException;
      
      public class CharacterEncodingFilter implements Filter {
          public void init(FilterConfig filterConfig) throws ServletException {
          }
      
          public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
              request.setCharacterEncoding("GBK");
              response.setCharacterEncoding("GBK");
              response.setContentType("text/html; charset=utf-8");
      
              chain.doFilter(request,response);
          }
      
          public void destroy() {
          }
      }
      
    4. 导入静态资源

      链接: https://pan.baidu.com/s/1oJKGW3a0GfODguH75a8jeg 提取码: cvia

三十一、smbms登录实现流程

  1. 设置首页

    <welcome-file-list>
        <welcome-file>login.jsp</welcome-file>
    </welcome-file-list>
    
  2. 编写dao层获取登录用户接口

    public interface UserDao {
        public User getLoginUser(Connection connection,String userCode,String userPassword) throws SQLException;
    }
    
  3. 编写dao接口的实现类(接入数据库)

    package com.xiaowei.dao.user;
    
    import com.mysql.jdbc.PreparedStatement;
    import com.xiaowei.dao.BaseDao;
    import com.xiaowei.pojo.User;
    
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    public class UserDaoImpl implements UserDao {
        public User getLoginUser(Connection connection, String userCode, String userPassword) throws SQLException {
            User user = new User();
            if (connection != null) {
                String sql = "select * from smbms_user where userCode=? and userPassword=?";
                PreparedStatement ps = null;
                ResultSet rs = null;
                Object[] params = {userCode,userPassword};
    
    
                rs = BaseDao.execute(connection, sql, params, rs, ps);
                if (rs.next()) {
                    user.setId(rs.getInt("id"));
                    user.setUserCode(rs.getString("userCode"));
                    user.setUserName(rs.getString("userName"));
                    user.setUserPassword(rs.getString("userPassword"));
                    user.setGender(rs.getInt("gender"));
                    user.setBirthday(rs.getDate("birthday"));
                    user.setPhone(rs.getString("phone"));
                    user.setAddress(rs.getString("address"));
                    user.setUserRole(rs.getInt("userRole"));
                    user.setCreatedBy(rs.getInt("createdBy"));
                    user.setCreationDate(rs.getDate("creationDate"));
                    user.setModifyBy(rs.getInt("modifyBy"));
                    user.setModifyDate(rs.getDate("modifyDate"));
                    BaseDao.release(null,ps,rs);
                    return user;
                }
    
            }
            return null;
        }
    }
    
  4. 业务层接口及业务层实现类

    public interface UserService {
        public User login(String userCode, String userPassword);
    }
    

    实现类(调用dao层)

    package com.xiaowei.service.user;
    
    import com.xiaowei.dao.BaseDao;
    import com.xiaowei.dao.user.UserDaoImpl;
    import com.xiaowei.pojo.User;
    import org.junit.Test;
    
    import java.sql.Connection;
    import java.sql.SQLException;
    
    public class UserServiceImpl implements UserService{
        //引入Dao层
        public UserDaoImpl userDao;
    
        public UserServiceImpl(){
            userDao = new UserDaoImpl();
        }
        public User login( String userCode,String userPassword) {
            User user = null;
            Connection connection = BaseDao.getConnection();
            try {
                //调用Dao层
                user = userDao.getLoginUser(connection, userCode, userPassword);
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally {
                BaseDao.release(connection,null,null);
            }
            return user;
        }
    
    
    }
    
  5. servlet编写(调用业务层)

    package com.xiaowei.servlet.user;
    
    import com.xiaowei.pojo.User;
    import com.xiaowei.service.user.UserService;
    import com.xiaowei.service.user.UserServiceImpl;
    import com.xiaowei.util.Constant;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class LoginServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            UserService userService = new UserServiceImpl();
            String userCode = req.getParameter("userCode");
            String userPassword = req.getParameter("userPassword");
            User login = userService.login(userCode, userPassword);
            if (login==null){
                req.setAttribute("error","查无此人,用户名或密码错误");
                req.getRequestDispatcher("login.jsp").forward(req,resp);
            }else {
                req.getSession().setAttribute(Constant.USER_SESSION,login);
                resp.sendRedirect("jsp/frame.jsp");
            }
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    

三十二、smbms注销及权限过滤

注销:移除session,返回login.jsp页面只需要在servlet中完成即可

注销:记得在web.xml中注册servlet

package com.xiaowei.servlet.user;

import com.xiaowei.util.Constant;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        session.removeAttribute(Constant.USER_SESSION);
        req.removeAttribute("error");
        System.out.println(req.getAttribute("error"));
        req.getRequestDispatcher("login.jsp").forward(req,resp);
    }

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

登录状态权限拦截:

package com.xiaowei.filter;

import com.xiaowei.util.Constant;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class LoginFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        Object attribute = req.getSession().getAttribute(Constant.USER_SESSION);
        if (attribute==null){
            resp.sendRedirect(req.getContextPath()+"/error.jsp");
        }


        chain.doFilter(request, response);
    }

    public void destroy() {
    }
}

三十三、smbms密码修改实现

从底层往前端

Dao层:

public int updatePassword(Connection connection,int id,String newPassword) throws SQLException;

实现:

public int updatePassword(Connection connection, int id, String newPassword) throws SQLException {
    String sql ="update smbms_user set userPassword=? where id=?";
    PreparedStatement ps = null;
    Object[] params = {newPassword,id};
    int execute = 0;
    if (connection!=null){
        execute = BaseDao.execute(connection, sql, params, ps);
        BaseDao.release(null,ps,null);
    }
    return execute;

}

Service层:

public boolean updatePassword(int id,String newPassword);

实现:

public boolean updatePassword(int id, String newPassword) {
    Connection connection = null;
    boolean flag = false;

    try {
        connection = BaseDao.getConnection();
        int i = userDao.updatePassword(connection, id, newPassword);
        if (i>0){
            flag=true;
        }

    } catch (SQLException throwables) {
        throwables.printStackTrace();
    }finally {
        BaseDao.release(connection,null,null);
    }


    return flag;
}

Servlet层:

public void updatePwd(HttpServletRequest req, HttpServletResponse resp){
    Object o = req.getSession().getAttribute(Constant.USER_SESSION);

    String newpassword = req.getParameter("newpassword");
    if (o!=null&&newpassword!=null){
        UserService userService = new UserServiceImpl();
        boolean b = userService.updatePassword(((User) o).getId(), newpassword);
        if (b){
            req.setAttribute("message","修改密码成功,请重新登录!");
            //清除session
            req.getSession().removeAttribute(Constant.USER_SESSION);
            try {

                req.getRequestDispatcher("/jsp/pwdmodify.jsp").forward(req,resp);
                //resp.sendRedirect(req.getContextPath()+"/login.jsp");
                return;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else {
            req.setAttribute("message","密码修改失败");
        }
    }else {
        req.setAttribute("message","新密码出错!");
    }

    try {
        req.getRequestDispatcher("/jsp/pwdmodify.jsp").forward(req,resp);
    } catch (ServletException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

三十四、Ajax验证旧密码实现

前端:

oldpassword.on("blur",function(){
   $.ajax({
      type:"GET",
      url:path+"/user/user.do",
      data:{method:"pwdmodify",oldpassword:oldpassword.val()},
         success:function(data){
         if(data.result == "true"){//旧密码正确
            validateTip(oldpassword.next(),{"color":"green"},imgYes,true);
         }else if(data.result == "false"){//旧密码输入不正确
            validateTip(oldpassword.next(),{"color":"red"},imgNo + " 原密码输入不正确",false);
         }else if(data.result == "sessionerror"){//当前用户session过期,请重新登录
            validateTip(oldpassword.next(),{"color":"red"},imgNo + " 当前用户session过期,请重新登录",false);
         }else if(data.result == "error"){//旧密码输入为空
            validateTip(oldpassword.next(),{"color":"red"},imgNo + " 请输入旧密码",false);
         }
      },
      error:function(data){
         //请求出错
         validateTip(oldpassword.next(),{"color":"red"},imgNo + " 请求错误",false);
      }
   });


}).on("focus",function(){
   validateTip(oldpassword.next(),{"color":"#666666"},"* 请输入原密码",false);
});

Ajax处理请求地址中的方法:(使用json传递数据)

public void pwdModify(HttpServletRequest req, HttpServletResponse resp){
    Object o = req.getSession().getAttribute(Constant.USER_SESSION);
    String oldpassword = req.getParameter("oldpassword");
    HashMap<String, String> resultMap = new HashMap<String, String>();

    if (o!=null && oldpassword!=null){
        User user = (User) o;
        if (user.getUserPassword().equals(oldpassword)){
            resultMap.put("result","true");
        }else if(!user.getUserPassword().equals(oldpassword)){
            resultMap.put("result","false");
        }
    }
    if (oldpassword==null){
        resultMap.put("result","error");
    }
    if (o==null){
        resultMap.put("result","sessionerror");
    }
    String jsonString = JSONArray.toJSONString(resultMap);


    PrintWriter writer = null;
    try {
        resp.setContentType("application/json");
        writer = resp.getWriter();
        writer.write(jsonString);
        writer.flush();
        writer.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

三十五、smbms用户管理底层实现

image

这里只完成用户列表的分页和总数:接口就不写出来的了

用户列表+分页

Dao层:

public List<User> getUserList(Connection connection, String username, int userRole, int currentPageNo, int pageSize) throws SQLException {
    PreparedStatement ps = null;
    ResultSet rs = null;
    ArrayList<Object> params = new ArrayList<Object>();
    StringBuffer sql =null;
    int pageBegin = (currentPageNo-1)*pageSize;
    ArrayList<User> users = null;

    if(connection!=null){
        sql = new StringBuffer();
        sql.append("select * from smbms_user u ,smbms_role r " +
                "where u.userRole=r.id");
        if (!StringUtils.isNullOrEmpty(username)){
            sql.append(" and u.userName = ?");
            params.add(username);
        }
        if (userRole>0&&userRole<4){
            sql.append(" and u.userRole = ? ");
            params.add(userRole);
        }
        sql.append("order by u.creationDate asc " +
                "limit ?,?");
        params.add(pageBegin);
        params.add(pageSize);

    }
    System.out.println(sql.toString());
    rs = BaseDao.execute(connection, sql.toString(), params.toArray(), rs, ps);
    users = new ArrayList<User>();
    while (rs.next()){
        User user = new User();
        user.setId(rs.getInt("id"));
        user.setUserCode(rs.getString("userCode"));
        user.setUserName(rs.getString("userName"));
        user.setUserPassword(rs.getString("userPassword"));
        user.setGender(rs.getInt("gender"));
        user.setBirthday(rs.getDate("birthday"));
        user.setPhone(rs.getString("phone"));
        user.setAddress(rs.getString("address"));
        user.setUserRole(rs.getInt("userRole"));
        user.setCreatedBy(rs.getInt("createdBy"));
        user.setCreationDate(rs.getDate("creationDate"));
        user.setModifyBy(rs.getInt("modifyBy"));
        user.setModifyDate(rs.getDate("modifyDate"));
        users.add(user);
    }
    BaseDao.release(null,ps,rs);
    return users;
}

Service层:

public List<User> getUserList(String userName, int userRole, int currentPageNo, int pageSize) {
    Connection connection = BaseDao.getConnection();
    List<User> userList = null;
    try {
        userList = userDao.getUserList(connection, userName, userRole,currentPageNo,pageSize);
    } catch (SQLException throwables) {
        throwables.printStackTrace();
    }finally {
        BaseDao.release(connection,null,null);
    }
    return userList;
}

总数

Dao层:

public int getUserCount(Connection connection, String username, int userRole) throws SQLException {
    PreparedStatement ps = null;
    ResultSet rs = null;
    ArrayList<Object> params = new ArrayList<Object>();
    StringBuffer sql =null;
    int count = 0;

    if(connection!=null){
        sql = new StringBuffer();
        sql.append("select count(1) from smbms_user u ,smbms_role r " +
                "where u.userRole=r.id");
        if (!StringUtils.isNullOrEmpty(username)){
            sql.append(" and u.userName = ?");
            params.add(username);
        }
        if (userRole>0&&userRole<4){
            sql.append(" and u.userRole = ?");
            params.add(userRole);
        }
    }
    rs = BaseDao.execute(connection, sql.toString(), params.toArray(), rs, ps);
    if (rs.next()){
        count = rs.getInt(1);
    }
    BaseDao.release(null,ps,rs);
    return count;

}

Service层:

public int getUserCount(String userName, int userRole) {
    Connection connection = BaseDao.getConnection();
    int userCount = 0;
    try {
        userCount = userDao.getUserCount(connection, userName, userRole);
    } catch (SQLException throwables) {
        throwables.printStackTrace();
    }finally {
        BaseDao.release(connection,null,null);
    }
    return userCount;
}

三十六、smbms用户管理分页OK

分页!

分页底层是用户列表Service和角色列表Service支撑!

servlet方法!

private void query(HttpServletRequest req, HttpServletResponse resp) {
    //取数据
    String queryname = req.getParameter("queryname");
    String temp = req.getParameter("queryUserRole");
    String totalCount = req.getParameter("totalCount");
    String currentPageNo = req.getParameter("currentPageNo");
    String totalPageCount = req.getParameter("totalPageCount");
    String pageIndex = req.getParameter("pageIndex");
    int pageSize = 5;

    //第一次进入,我们没有数据如何做?
    int queryUserRole = 0;
    if (StringUtils.isNullOrEmpty(queryname)){
        queryname = "";
    }
    if (!StringUtils.isNullOrEmpty(temp)){
        queryUserRole=Integer.parseInt(temp);
    }
    UserServiceImpl userService = new UserServiceImpl();
    if (StringUtils.isNullOrEmpty(totalCount)){
        totalCount = userService.getUserCount(null,0)+"";
    }
    if (StringUtils.isNullOrEmpty(currentPageNo) ){
        currentPageNo = 1+"";
    }
    if (StringUtils.isNullOrEmpty(pageIndex)){
        pageIndex = 1+"";
    }
    if (StringUtils.isNullOrEmpty(totalPageCount)){
        totalPageCount = Double.valueOf(Math.ceil(Double.parseDouble(totalCount)/pageSize)).intValue()+"";
    }


    //去数据库数据
    List<User> userList = userService.getUserList(queryname, queryUserRole, Integer.parseInt(pageIndex), pageSize);
    RoleServiceImpl roleService = new RoleServiceImpl();
    List<Role> roleList = roleService.getRoleList();
    //存入数据,改变当前页
    currentPageNo=pageIndex;//前端传回现在的页,需要更新!
    req.setAttribute("queryUserName",queryname);
    req.setAttribute("roleList",roleList);
    req.setAttribute("userList",userList);
    req.setAttribute("queryUserRole",queryUserRole+"");
    req.setAttribute("totalCount",totalCount+"");
    req.setAttribute("currentPageNo",currentPageNo+"");
    req.setAttribute("totalPageCount",totalPageCount+"");
    req.setAttribute("pageIndex",pageIndex+"");


    try {
        req.getRequestDispatcher("/jsp/userlist.jsp").forward(req,resp);
    } catch (ServletException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

下面这两个就是要做合格的CV工程师了属于是,拿来直接用,这两玩意真的yue

三十七、smbms架构分析及方法学习

一切的增删改操作都要处理事务

  • connection.setAutoCommit(false)
  • sql
  • connection.commit()
  • 如果失败:connection.rollback

三十八、文件上传

package com.xiaowei.servlet;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;

public class UploadServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
     *      response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {


        // 判断上传的文件普通表单还是带文件的表单
        if (!ServletFileUpload.isMultipartContent(request)) {
            return;//终止方法运行,说明这是一个普通的表单,直接返回
        }
        
        //创建上传文件的保存路径,建议在WEB-INF路径下,安全,用户无法直接访间上传的文件;
        String uploadPath =this.getServletContext().getRealPath("/WEB-INF/upload");
        File uploadFile = new File(uploadPath);
        if (!uploadFile.exists()){
            uploadFile.mkdir(); //创建这个月录
        }

        // 创建上传文件的保存路径,建议在WEB-INF路径下,安全,用户无法直接访问上传的文件
        String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
        File file = new File(tmpPath);
        if (!file.exists()) {
            file.mkdir();//创建临时目录
        }

        // 处理上传的文件,一般都需要通过流来获取,我们可以使用 request, getInputstream(),原生态的文件上传流获取,十分麻烦
        // 但是我们都建议使用 Apache的文件上传组件来实现, common-fileupload,它需要旅 commons-io组件;
        try {
            //1、创建DiskFileItemFactory对象,处理文件路径或者大小限制(对接磁盘获得工厂)
            DiskFileItemFactory factory = getDiskFileItemFactory(file);
            /*
             * 通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,
             * 将他放到临时文件 factory.setSizeThreshold(1024 *1024); 
             * 缓存区大小为1M factory.setRepository (file);
             * 临时目录的保存目录,需要一个File
             */

            // 2、获取ServletFileUpload(通过工厂过的上传对象)
            ServletFileUpload upload = getServletFileUpload(factory);

            // 3、处理上传文件(上传!)
            // 把前端请求解析,封装成FileItem对象,需要从ServletFileUpload对象中获取
            String msg = uploadParseRequest(upload, request, uploadPath);

            // Servlet请求转发消息
            System.out.println(msg);
            if(msg == "文件上传成功!") {
                // Servlet请求转发消息
                request.setAttribute("msg",msg);
                request.getRequestDispatcher("info.jsp").forward(request, response);
            }else {
                msg ="请上传文件";
                request.setAttribute("msg",msg);
                request.getRequestDispatcher("info.jsp").forward(request, response);
            }

        } catch (FileUploadException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }
    }

    public static DiskFileItemFactory getDiskFileItemFactory(File file) {
        DiskFileItemFactory factory = new DiskFileItemFactory();
        // 通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件中;
        factory.setSizeThreshold(1024 * 1024);// 缓冲区大小为1M
        factory.setRepository(file);// 临时目录的保存目录,需要一个file
        return factory;
    }

    public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
        ServletFileUpload upload = new ServletFileUpload(factory);
        // 监听长传进度
        upload.setProgressListener(new ProgressListener() {

            // pBYtesRead:已读取到的文件大小
            // pContextLength:文件大小
            public void update(long pBytesRead, long pContentLength, int pItems) {
                System.out.println("总大小:" + pContentLength + "已上传:" + pBytesRead);
            }
        });

        // 处理乱码问题
        upload.setHeaderEncoding("UTF-8");
        // 设置单个文件的最大值
        upload.setFileSizeMax(1024 * 1024 * 10);
        // 设置总共能够上传文件的大小
        // 1024 = 1kb * 1024 = 1M * 10 = 10м

        return upload;
    }

    public static String uploadParseRequest(ServletFileUpload upload, HttpServletRequest request, String uploadPath)
            throws FileUploadException, IOException {

        String msg = "";

        // 把前端请求解析,封装成FileItem对象
        List<FileItem> fileItems = upload.parseRequest(request);
        for (FileItem fileItem : fileItems) {
            if (fileItem.isFormField()) {// 如果是表单
                // getFieldName指的是前端表单控件的name属性;
                String name = fileItem.getFieldName();
                String value = fileItem.getString("UTF-8"); // 处理乱码
                System.out.println(name + ": " + value);
            } else {// 判断它是上传的文件

                // ============处理文件==============

                String uploadFileName = fileItem.getName();// 拿到文件名
                System.out.println("上传的文件名: " + uploadFileName);
                if (uploadFileName.trim().equals("") || uploadFileName == null) {
                    continue;
                }

                // 获得上传的文件名/images/girl/paojie.png
                String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
                // 获得文件的后缀名
                String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);

                /*
                 * 如果文件后缀名fileExtName不是我们所需要的 就直按return.不处理,告诉用户文件类型不对。
                 */

                System.out.println("文件信息[件名: " + fileName + " ---文件类型" + fileExtName + "]");
                // 可以使用UID(唯一识别的通用码),保证文件名唯
                // 0UID. randomUUID(),随机生一个唯一识别的通用码;
                String uuidPath = UUID.randomUUID().toString();

                // ================处理文件完毕==============

                // 存到哪? uploadPath
                // 文件真实存在的路径realPath
                String realPath = uploadPath + "/" + uuidPath;
                // 给每个文件创建一个对应的文件夹
                File realPathFile = new File(realPath);
                if (!realPathFile.exists()) {
                    realPathFile.mkdir();
                }
                // ==============存放地址完毕==============


                // 获得文件上传的流
                InputStream inputStream = fileItem.getInputStream();//获得文件
                // 创建一个文件输出流
                // realPath =真实的文件夹;
                // 差了一个文件;加上翰出文件的名产"/"+uuidFileName
                FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName);

                //写文件
                byte[] buffer = new byte[1024 * 1024];
                int len = 0;
                while ((len = inputStream.read(buffer)) > 0) {
                    fos.write(buffer, 0, len);
                }
                // 关闭流
                fos.close();
                inputStream.close();

                msg = "文件上传成功!";
                fileItem.delete(); // 上传成功,清除临时文件
                //=============文件传输完成=============
            }
        }
        return msg;

    }

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

三九、邮件发送

纯文本邮件

  • 设置服务器
  • 设置SSL加密
  • Session.getDefaultInstance
  • session.getTransport();
  • 指定邮件内容MimeMessage.*
  • 发邮件
  • 关transport
package com.xiaowei.test;

import com.sun.mail.util.MailSSLSocketFactory;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;

public class MailDemo01 {
    public static void main(String[] args) throws Exception {
        Properties prop=new Properties();
        prop.setProperty("mail.host","smtp.qq.com");///设置QQ邮件服务器
        prop.setProperty("mail.transport.protocol","smtp");///邮件发送协议
        prop.setProperty("mail.smtp.auth","true");//需要验证用户密码
        //QQ邮箱需要设置SSL加密
        MailSSLSocketFactory sf=new MailSSLSocketFactory();
        sf.setTrustAllHosts(true);
        prop.put("mail.smtp.ssl.enable","true");
        prop.put("mail.smtp.ssl.socketFactory",sf);

        //使用javaMail发送邮件的5个步骤
        //1.创建定义整个应用程序所需要的环境信息的session对象
        Session session=Session.getDefaultInstance(prop, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("XXXX@qq.com","授权码");
            }
        });
        //开启session的debug模式,这样可以查看到程序发送Email的运行状态
        session.setDebug(true);
        //2.通过session得到transport对象
        Transport ts=session.getTransport();
        //3.使用邮箱的用户名和授权码连上邮件服务器
        ts.connect("smtp.qq.com","XXXX@qq.com","授权码");
        //4.创建邮件:写文件
        //注意需要传递session
        MimeMessage message=new MimeMessage(session);
        //指明邮件的发件人
        message.setFrom(new InternetAddress("XXXX@qq.com"));
        //指明邮件的收件人
        message.setRecipient(Message.RecipientType.TO,new InternetAddress("XXXX@qq.com"));
        //邮件标题
        message.setSubject("发送的标题");
        //邮件的文本内容
        message.setContent("内容","text/html;charset=UTF-8");
        //5.发送邮件
        ts.sendMessage(message,message.getAllRecipients());

        //6.关闭连接
        ts.close();

    }
}

图片邮件:本质还是文本,但是,img标签中的源需要处理

  • 设置服务器
  • 设置SSL加密
  • Session.getDefaultInstance
  • session.getTransport();
  • 指定邮件内容MimeMessage.*
  • 准备图片数据
    • image=new MimeBodyPart();
    • dh=new DataHandler(new FileDataSource("D:\Bert\1594126632(1).jpg"));
    • image.setDataHandler(dh);
    • image.setContentID("bz.jpg");
  • 描写数据关系
    • MimeMultipart mm=new MimeMultipart();
    • mm.addBodyPart(text);
    • mm.addBodyPart(image);
    • mm.setSubType("related");
  • 发邮件
  • 关transport
package com.xiaowei.test;

import com.sun.mail.util.MailSSLSocketFactory;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.util.Properties;

public class MailDemo02 {
    public static void main(String[] args) throws Exception {
        Properties prop=new Properties();
        prop.setProperty("mail.host","smtp.qq.com");///设置QQ邮件服务器
        prop.setProperty("mail.transport.protocol","smtp");///邮件发送协议
        prop.setProperty("mail.smtp.auth","true");//需要验证用户密码
        //QQ邮箱需要设置SSL加密
        MailSSLSocketFactory sf=new MailSSLSocketFactory();
        sf.setTrustAllHosts(true);
        prop.put("mail.smtp.ssl.enable","true");
        prop.put("mail.smtp.ssl.socketFactory",sf);

        //使用javaMail发送邮件的5个步骤
        //1.创建定义整个应用程序所需要的环境信息的session对象
        Session session=Session.getDefaultInstance(prop, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("11927XXX@qq.com","授权码");
            }
        });
        //开启session的debug模式,这样可以查看到程序发送Email的运行状态
        session.setDebug(true);
        //2.通过session得到transport对象
        Transport ts=session.getTransport();
        //3.使用邮箱的用户名和授权码连上邮件服务器
        ts.connect("smtp.qq.com","11927XXX@qq.com","授权码");
        //4.创建邮件:写文件
        //注意需要传递session
        MimeMessage message=new MimeMessage(session);
        //指明邮件的发件人
        message.setFrom(new InternetAddress("11927XXX@qq.com"));
        //指明邮件的收件人
        message.setRecipient(Message.RecipientType.TO,new InternetAddress("11927XXX@qq.com"));
        //邮件标题
        message.setSubject("java发出");

        //邮件的文本内容
        //=================================准备图片数据=======================================
        MimeBodyPart image=new MimeBodyPart();
        //图片需要经过数据化的处理
        DataHandler dh=new DataHandler(new FileDataSource("D:\\Bert\\1594126632(1).jpg"));
        //在part中放入这个处理过图片的数据
        image.setDataHandler(dh);
        //给这个part设置一个ID名字
        image.setContentID("bz.jpg");

        //准备正文的数据
        MimeBodyPart text=new MimeBodyPart();
        text.setContent("这是一张正文<img src='cid:bz.jpg'>","text/html;charset=UTF-8");

        //描述数据关系
        MimeMultipart mm=new MimeMultipart();
        mm.addBodyPart(text);
        mm.addBodyPart(image);
        mm.setSubType("related");

        //设置到消息中,保存修改
        message.setContent(mm);
        message.saveChanges();
        //5.发送邮件
        ts.sendMessage(message,message.getAllRecipients());

        //6.关闭连接
        ts.close();

    }
}

附件邮件:

  • 设置服务器
  • 设置SSL加密
  • Session.getDefaultInstance
  • session.getTransport();
  • 指定邮件内容MimeMessage.*
  • 准备图片数据
    • image=new MimeBodyPart();
    • dh=new DataHandler(new FileDataSource("D:\Bert\1594126632(1).jpg"));
    • image.setDataHandler(dh);
    • image.setContentID("bz.jpg");
  • 准备附件数据
    • MimeBodyPart body1= new MimeBodyPart();
    • body1.setDataHandler(new DataHandler(new FileDataSource("D:\Bert\cmd.txt")));
    • body1.setFileName("1.txt");
  • 描写数据关系
    • MimeMultipart mm=new MimeMultipart();
    • mm.addBodyPart(body1);
    • mm.addBodyPart(text);
    • mm.addBodyPart(image);
    • mm.setSubType("mixed");
  • 发邮件
  • 关transport
package com.xiaowei.test;

import com.sun.mail.util.MailSSLSocketFactory;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.*;
import java.util.Properties;

public class MailDemo03 {
    public static void main(String[] args) throws Exception {
        Properties prop=new Properties();
        prop.setProperty("mail.host","smtp.qq.com");///设置QQ邮件服务器
        prop.setProperty("mail.transport.protocol","smtp");///邮件发送协议
        prop.setProperty("mail.smtp.auth","true");//需要验证用户密码
        //QQ邮箱需要设置SSL加密
        MailSSLSocketFactory sf=new MailSSLSocketFactory();
        sf.setTrustAllHosts(true);
        prop.put("mail.smtp.ssl.enable","true");
        prop.put("mail.smtp.ssl.socketFactory",sf);

        //使用javaMail发送邮件的5个步骤
        //1.创建定义整个应用程序所需要的环境信息的session对象
        Session session=Session.getDefaultInstance(prop, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("1192XXXX@qq.com","授权码");
            }
        });
        //开启session的debug模式,这样可以查看到程序发送Email的运行状态
        session.setDebug(true);
        //2.通过session得到transport对象
        Transport ts=session.getTransport();
        //3.使用邮箱的用户名和授权码连上邮件服务器
        ts.connect("smtp.qq.com","1192XXXX@qq.com","授权码");
        //4.创建邮件:写文件
        //注意需要传递session
        MimeMessage message=new MimeMessage(session);
        //指明邮件的发件人
        message.setFrom(new InternetAddress("1192XXXX@qq.com"));
        //指明邮件的收件人
        message.setRecipient(Message.RecipientType.TO,new InternetAddress("1192XXXX@qq.com"));
        //邮件标题
        message.setSubject("java发出");

        //邮件的文本内容
        //=================================准备图片数据
        MimeBodyPart image=new MimeBodyPart();
        //图片需要经过数据化的处理
        DataHandler dh=new DataHandler(new FileDataSource("D:\\Bert\\1594126632(1).jpg"));
        //在part中放入这个处理过图片的数据
        image.setDataHandler(dh);
        //给这个part设置一个ID名字
        image.setContentID("bz.jpg");

        //=================================准备正文数据
        MimeBodyPart text=new MimeBodyPart();
        text.setContent("这是一张正文<img src='cid:bz.jpg'>","text/html;charset=UTF-8");

        //=================================准备附件数据
        MimeBodyPart body1= new MimeBodyPart();
        body1.setDataHandler(new DataHandler(new FileDataSource("D:\\Bert\\cmd.txt")));
        body1.setFileName("1.txt");

        //描述数据关系
        MimeMultipart mm=new MimeMultipart();
        mm.addBodyPart(body1);
        mm.addBodyPart(text);
        mm.addBodyPart(image);
        mm.setSubType("mixed");

        //设置到消息中,保存修改
        message.setContent(mm);
        message.saveChanges();
        //5.发送邮件
        ts.sendMessage(message,message.getAllRecipients());

        //6.关闭连接
        ts.close();

    }
}
posted @ 2021-11-02 20:38  小阴辨  阅读(80)  评论(0)    收藏  举报