JavaWeb(简写篇)

JavaWeb

Servlet学习结构

 

1.JavaWeb基本概念

1.1 web静态和动态

  • 静态web

 

HTML,CSS,提供所有的数据是不会变化的。 缺点:1.web界面无法动态更新,所有用户看到一个界面 2.无法与数据库交互

  • 动态web

 

动态web如淘宝等网站,会根据自己的账号登录,看见自己的信息。 缺点:1.如果服务器崩溃,可能出现停机 2.可以与数据库交互(注册,登录,信息变化)

2.Web服务器

2.1 了解

ASP:
微软:国内最早流行的就是ASP;
1.在HTML中嵌入了VB的脚本,ASP+COM;
2.在ASP开发中,基本一个页面都有几干行的业务代码,页面极其换乱
3.维护成本高!
4.C#
5.IIS
​
php:
1.PHP开发速度很快,功能很强大,跨平台,代码很简单(70%,WP)
2.无法承载大访问量的情况(局限性)
​
jSP/Servlet:
1.B/S;浏览和服务器
2.C/S:客户端和服务器
​
sun公司主推的B/S架构
基于Java语言的(所有的大公司,或者一些开源的组件,都是用Java写的)
可以承载三高问题带来的影响;
语法像ASP,ASP->JSP,加强市场强度;

2.2 tomcat

服务器是一种被动的操作,用来处理用户的一些请求和给用户一些响应信息; lIS 微软的;ASP,Windows中自带的

Tomcat服务器

Tomcat是Apache 软件基金会(Apache Software Foundation)的jakarta项目中的一个核心项目,最新的Servlet 和JSP 规范总是能在Tomcat中得到体现,因为Tomcat 技术先进、性能稳定,而且免费,因而深受lava爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web应用服务器。
tomcat就是运行java程序,提供api接口。

安装步骤

1.官网下载并安装:Apache Tomcat® - Welcome! 2.解压tomcat文件,并在解压目录下‪bin --> startup.bat,双击运行 3.tomcat默认端口8080,在浏览器访问localhost:8080

问题: 1.Java环境没有配置 2.闪出问题:需要配置兼容性 3.乱码问题:配置文件修改:conf-->logging.properties-->java.util.logging.ConsoleHandler.encoding = GBK

了解配置文件和目录

1.目录 1.1 bin-->启动和关闭脚本 1.2 conf-->配置 1.3 lib-->依赖jar包 1.4 webapps-->项目

2.配置文件 2.1 配置端口号(tomcat:8080 mysql:3306 http:80 https:443) 2.2 配置主机名称(这里需要修改电脑配置localhost:C:\Windows\System32\drivers\etc\hosts) 2.3 配置应用项目:webapps

tomcat作用

就是一个服务器。

2.3 网站如何经行访问

 

检查本机的C:\Windows\System32\drivers\etc\hosts配置文件下有没有这个域名映射;
    1.有:直接返回对应的ip地址,这个地址中,有我们需要访问的web程序,可以直接访问
    2.没有:去DNS服务器找,找到的话就返回,找不到就返回找不到;

3. Http

(超文本传输协议)是一个简单的请求-响应协议,它通常运行在TCP之上。
​
文本:html,字符串,…
超文本:图片,音乐,视频,定位,地图.……
端口:80
  • http1.0

    • HTTP/1.0:客户端可以与web服务器连接后,只能获得一个web资源,断开连接

  • http2.0

    • HTTP/1.1:客户端可以与web服务器连接后,可以获得多个web资源。

3.1 Http请求

Request URL:https://www.baidu.com/   请求地址
Request Method:GET    get方法/post方法
Status Code:200 OK    状态码:200
Remote(远程) Address:14.215.177.39:443
​
Accept:text/html  告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码格式
Accept-Language:zh-CN,zh;q=0.9    语言
Cache-Control:缓存控制
Connection:keep-alive
​
  • 请求行 1.请求方式:get/post get请求参数有限制,会在浏览器显示数据,不安全 post请求参数不限,不会在浏览器显示数据,安全

  • 请求头 1.支持的数据类型 2.支持哪种编码格式等等

3.2 http响应

  • 响应体

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

200         请求已成功,请求所希望的响应头或数据体将随此响应返回。出现此状态码是表示正常状态。
400         语义有误,当前请求无法被服务器理解。除非进行修改,否则客户端不应该重复提交这个请求。
401         当前请求需要用户验证,一般表示权限不足的意思。
404         请求失败,请求所希望得到的资源未被在服务器上发现。
405         请求行中指定的请求方法不能被用于请求相应的资源。
500         服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。

4. Maven

Apache Maven是一个(特别是Java编程)项目管理及自动构建工具,由Apache软件基金会所提供。基于项目对象模型(缩写:POM)概念,Maven利用一个中央信息片断能管理一个项目的构建、报告和文档等步骤。Maven核心思想约定大于配置。

安装教程网站:B站---【狂神说Java】JavaWeb入门到实战---笔记夜里的雨的博客-CSDN博客狂神说javaweb笔记 视频教程网站:javaweb-05:Maven环境搭建哔哩哔哩bilibili

1.下载Maven,官网:https://maven.apache.org/
2.配置环境变量
3.修改配置文件(settings.xml):阿里云镜像
    <mirror>
        <id>nexus-aliyun</id>  
        <mirrorOf>*,!jeecg,!jeecg-snapshots</mirrorOf>  
        <name>Nexus aliyun</name>  
        <url>http://maven.aliyun.com/nexus/content/groups/public</url> 
    </mirror>
4.配置自己的本地仓库
    <localRepository>D:\repository</localRepository>

5. 第一个HelloWorld

HttpServlet类需要导入依赖两种方式:
    1.直接在pom.xml中配置
        <dependencies>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>4.0.1</version>
            </dependency>
        </dependencies>
    2.提前配置tomcat.tomcat依赖有servlet依赖

HelloWord

第一步:继承HttpServlet抽象类 第二步:配置Mapping映射

public class HelloWorldServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        //  响应流
        PrintWriter printWriter=resp.getWriter();
        printWriter.write("Hello World !");
    }
​
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        this.doGet(req,resp);
    }
}
<servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.demo.HelloWorldServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>
​

Servlet原理分析(狂神说)

 

5.1 Mapping映射问题

1.一个Servlet可以指定一个映射路径
2.一个servlet可以指定多个映射路径
    <servlet-mapping>
          <servlet-name>hello</servlet-name>
          <url-pattern>/hello/hello1</url-pattern>
      </servlet-mapping>
      <servlet-mapping>
          <servlet-name>hello</servlet-name>
          <url-pattern>/hello/hello2</url-pattern>
      </servlet-mapping>
3.一个servlet可以指定通用映射路径
    <servlet-mapping>
          <servlet-name>hello</servlet-name>
          <url-pattern>/hello/*</url-pattern>
      </servlet-mapping>
4.指定一些后缀或者前缀等等…
    <servlet-mapping>
      <servlet-name>hello</servlet-name>
      <url-pattern>*.do</url-pattern>
  </servlet-mapping>
5./*与/具体路径 相比,/具体路径优先于/*,所以可以根据这个来制作404找不到网页设计。
    <!--404-->
  <servlet>
      <servlet-name>error</servlet-name>
      <servlet-class>com.kuang.servlet.ErrorServlet</servlet-class>
  </servlet>
  <servlet-mapping>
      <servlet-name>error</servlet-name>
      <url-pattern>/*</url-pattern>
  </servlet-mapping>

6.Servlet

Servlet简介

Servlet 是 Server Applet 的缩写,译为“服务器端小程序”,是一种使用 Java 语言来开发动态网站的技术。
Servlet 虽然被称作“小程序”,但是它的功能却异常强大,因为它是基于 Java 的,几乎可以使用所有的 Java API,Java 能做的事情,Servlet 也能做。
您可以这样理解,Servlet 是 Sun 公司推出的一种基于 Java 的动态网站开发技术。
​
严格来说,Servlet 只是一套 Java Web 开发的规范,或者说是一套 Java Web 开发的技术标准。
只有规范并不能做任何事情,必须要有人去实现它。所谓实现 Servlet 规范,就是真正编写代码去实现 Servlet 规范提到的各种功能,包括类、方法、属性等。

6.1 创建Servlet的方式

方式一:实现Servlet接口

我们通过实现Servlet 接口里的方法,就可以开发出动态网页。代码如下:
public class TestServlet implements Servlet {
    在这里去实现方法
}

方式二:继承HttpServlet

直接实现 Servlet 接口比较麻烦,需要实现很多方法,所以 Servlet 规范又提供了两个抽象类,分别是GenericServlet 类和 HttpServlet 类,
它们都实现了 Servlet 接口的很多常用功能。和 GenericServlet 类相比,HttpServlet 类更加方便,所以实际开发中一般都继承自 HttpServlet 类。
我们也可以通过 继续 HttpServlet 类来创建Servlet,代码如下:
public class MyHttpTestServlet extends HttpServlet {
    重写我们需要用到的方法,如:
    doGet()..   专门用于接收get请求
    doPost()..  专门用于接收post请求
}
因为这种方式更简洁,所有更推荐使用这种方式来创建Servlet

6.2 ServletContext上下文对象

Servlet 容器启动时,会为当前项目创建一个唯一的 ServletContext 对象,该对象一般被称为“Servlet 上下文”。
这是一个全局对象,在每个Servlet里面都可以使用,而且使用ServletContext对象它的范围是Servlet容器里面(限于Servlet类),
我们在于ServletContext里面的数据就被保护于Servlet容器之中。
  • 获取ServletContext对象

1. 通过 GenericServlet 提供的 getServletContext() 方法,HttpServlet继承GenericServlet即也有该方法
2. 通过 Servlet接口提供的getServletConfig()返回的对象的getServletContext() 方法

ServletContext对象用处

1.共享数据,每一个Servlet都可以通过ServletContext共享容器中的数据。
2.获取初始化参数,在xml文件中,利用context-param标签,设置初始化参数。
3.请求转发,context.getRequestDispatcher("/gp").forward(req,resp);
4.读取资源文件,getServletContext.getResourceAsStream("xxxxx");
​
 * 1. Class.getResourceAsStream(String path) :
 *  path 不以'/'开头时默认是从此类所在的包下取资源,以'/'开头则是从ClassPath(Src根目录)根下获取。
 *  其只是通过path构造一个绝对路径,最终还是由ClassLoader获取资源。
 * 2. Class.getClassLoader.getResourceAsStream(String path) :
 * 默认则是从ClassPath根下获取,path不能以'/'开头,最终是由ClassLoader获取资源。
 * 
 * 3. ServletContext. getResourceAsStream(String path):
 * 默认从WebAPP根目录下取资源,Tomcat下path是否以’/'开头无所谓,当然这和具体的容器实现有关。

网页浏览人数记录

@WebServlet("/getNumber")
public class BrowsePageOneServlet implements Servlet {
​
    private ServletConfig servletConfig;
​
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        this.servletConfig=servletConfig;
        System.out.println("Servlet初始化......");
    }
​
    @Override
    public ServletConfig getServletConfig() {
        return servletConfig;
    }
​
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse)
            throws ServletException, IOException {
        //根据servletConfig获取servletContent
        ServletContext servletContext=servletConfig.getServletContext();
        visitorNumber(servletContext);
    }
​
    @Override
    public String getServletInfo() {
        return null;
    }
​
    @Override
    public void destroy() {
        System.out.println("Servlet销毁了......");
    }
​
    public static void visitorNumber(ServletContext servletContext){
        //获取xml文件的初始化参数
        Integer count= servletContext.getAttribute("count")==null
                ?null:Integer.parseInt(servletContext.getAttribute("count").toString());
        if(count==null){
            count=Integer.parseInt(servletContext.getInitParameter("count"));
        }else{
            count= Integer.parseInt(servletContext.getAttribute("count").toString());
        }
        //注意自增,容易出错
        servletContext.setAttribute("count",++count);
        System.out.println("访问过的人数:"+count);
    }
}
@WebServlet("/getNumber1")
public class BrowsePageTwoServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        BrowsePageOneServlet.visitorNumber(getServletContext());
    }
​
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        this.doGet(req,resp);
    }
}

文件读取

@WebServlet("/getNumber1")
public class BrowsePageTwoServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
​
        // 通过servletContent获取db.properties文件
        InputStream resourceAsStream1 = getServletContext().getClassLoader().getResourceAsStream("db.properties");
        try{
            byte[] bytes=new byte[1024];
            StringBuffer sb=new StringBuffer();
            int i;
            do{
                i=resourceAsStream1.read(bytes);
                if(i>-1){
                    sb.append(new String(bytes,0,i));
                }
            }while (i>-1);
            resourceAsStream1.close();
            System.out.println(sb.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
​
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        this.doGet(req,resp);
    }
}

6.3 HttpServletRequest

一般情况下,浏览器通过HTTP协议来访问服务器的资源,Servlet主要用来处理这些HTTP请求。
​
1.Servlet容器收到来自客户端的HTTP请求后,容器会针对该每一次请求分别创建一个HttpServletRequest对象和HttpServletResponse对象;
2.HttpServletRequest携带请求相关信息,然后对HTTP进行处理;
3.请求处理完成之后,将响应信息装到HttpServletResponse对象中。
4.Servlet容器将响应信息返回给客户端;
  • 请求行信息的方法

@WebServlet("/request")
public class RequestTest extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
//        getMethod()                 用于获取HTTP请求的方式,返回结果如:GET、POST或者其它
        System.out.println(req.getMethod());
//        getRequestURI()             用于获取请求行中的资源名称部分,就是位于URL的主机和端口之后,参数之前的那部分。
        System.out.println(req.getRequestURI());
//        getQueryString()            用于获取请求行中参数部分,就是URL中“?”后面的部分
        System.out.println(req.getQueryString());
//        getServletPath()            获取Servlet所映射的路径
        System.out.println(req.getServletPath());
//        getRemoteHost()             用于获取客户端的完整主机名,如果无法解析出客户机的完整主机名,则返回客户机的IP地址
        System.out.println(req.getRemoteHost());
//        getRemoteAddr()             用于获取客户端IP地址
        System.out.println(req.getRemoteAddr());
    }
​
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
//        getMethod()                 用于获取HTTP请求的方式,返回结果如:GET、POST或者其它
        System.out.println(req.getMethod());
    }
}
  • 请求头信息的方法

@WebServlet("/request")
public class RequestTest extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
//        getHeader(String name)      用于获取请求头里面的值,参数为请求头的名称
        System.out.println(req.getHeader("token"));
//        getHeaderNames()            用于获取请求头里面所有名称,返回一个字符串枚举集合
        System.out.println(req.getHeaderNames());
//        getContentType()            用于获取Content-Type头字段的值(一般用于用于Ajax请求)
        System.out.println(req.getContentType());
    }
​
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
//        getMethod()                 用于获取HTTP请求的方式,返回结果如:GET、POST或者其它
        System.out.println(req.getMethod());
    }
}
  • 获取参数或者转发使用

获取参数:
getParameter(String name)   获取指定参数名的数值,适用于application/x-www-form-urlencoded类型的参数
getParameterNames()         获取所有参数名称,返回枚举集合
getParameterValues(String name)【弃用】  以字符串数组的形式返回指定参数名的所有参数值,主要合适于checkbox复选框
​
文件上传:
getPart(String name)        获取指定参数名的上传文件,适用于multipart/form-data类型的参数
​
弃用:
getRequestDispatcher(String addr)    其中addr就是给转发器传递的参数,就是表示该转发器要转发到哪个地址
转发器.forward(req, resp)              用于来实现真正的转发

6.4 HttpServletResponse

Servlet容器会针对每次请求创建一个HttpServletResponse对象,并把它作为参数传递给Servlet的doGet或者doPost方法,
Servlet处理请求后,会把响应信息装到HttpServletResponse对象中,并由容器解析后返回给客户端。
​
弃用:
重定向属于客户端行为,服务器在收到客户端请求后,会通知客户端浏览器重新向另外一个新的URL发送请求,这种操作就叫请求重定向。
它本质上就是两次请求,对应的也是两个req对象和两个resp对象。
实现方法:
sendRedirect(String url)        该方法可以实现请求的重定向,重定向参数url这个地址
@WebServlet("/response")
public class ResponseTest extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
//        setStatus(int status)           用于设置HTTP响应消息的状态码
        resp.setStatus(402);
//        setContentType(String type)     用于设置Servlet输出内容的MIME类型,以及编码格式
        resp.setContentType("application/json");
//        getWriter()                     用于获取字符输出流对象(PrintWriter),再通过 PrintWriter 对象的 write("输出的文字内容")将内容输出到页面上
        resp.getWriter().write("hello world!");
    }
​
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        this.doGet(req,resp);
    }
}

7. 过滤器Filter

过滤器(Filter)是对资源路径进行过滤,决定是放行还是拒绝,或者其它的操作。使用过滤器,可以减少我们的代码开发,使功能更加完善。

Filter创建可以实现Filter接口,xml中配置可以根据Servlet的配置一样来配置,只需跟换Servlet为Filter。

  • 配置Filter映射方法(XML、注解)

<filter>
    <filter-name>filter名称</filter-name>
    <filter-class>filter类的全路径</filter-class>
</filter>
<filter-mapping>
    <filter-name>filter名称</filter-name>
    <url-pattern>URL地址</url-pattern>
</filter-mapping>
优点是可以对整个项目的url一目了然
使用@WebFilter("url-pattern")进行配置,该注解是加到我们自己创建的Filter类上面,其中参数就是url-pattern
优点是代码更简洁

简单使用Filter过滤器

@WebFilter("/*")
public class TokenFilter implements Filter {
​
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("初始化过滤器......");
    }
​
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        //如果是请求携带token就放行
        HttpServletRequest httpServletRequest=(HttpServletRequest)servletRequest;
        HttpServletResponse httpServletResponse=(HttpServletResponse)servletResponse;
        String token = httpServletRequest.getHeader("token");
        if(token!=null){
            filterChain.doFilter(servletRequest,servletResponse);
        }else{
            servletResponse.setContentType("text/html;charset=UTF-8");
            httpServletResponse.getWriter().write("token未通过!!!");
            System.out.println("token未通过!!!");
        }
    }
​
    @Override
    public void destroy() {
        System.out.println("过滤器销毁了......");
    }
}
在上一个Filter中,用servletRequest.setAttribute(String name, Object o);来添加属性,
然后,再下一个Filter中,用servletRequest.getAttribute(String name); 来获取传递过来的数据
并可以通过filter来设置黑白名单。

8. Listener监听器

监听器Listener是一个实现特定接口的Java类,这个类专门用于监听另一个Java对象的方法调用或者属性改变,
当被监听对象发生上述事件后,监听器就会自动执行某个方法。
​
1. 事件           Java对象被创建或者销毁、属性被改变的时候触发的事件;
2. 事件源          触发事件的源对象,被监听的对象;
3. 监听器          用于监听事件源对象,事件源对象状态的变化就是触发监听器;
4. 注册监听器       将监听器与事件源进行绑定;

监听器的分类

1. ServletContextListener           用于监听ServletContext对象的创建与销毁
2. ServletContextAttributeListener  用于监听ServletContext对象的属性被更改
3. ServletRequestListener           用于监听ServletRequest对象的创建与销毁
4. ServletRequestAttributeListener  用于监听ServletRequest对象的属性被更改
5. HttpSessionListener              用于监听HttpSession对象的创建与销毁
6. HttpSessionAttributeListener     用于监听HttpSession对象的的属性被更改
7. HttpSessionBindingListener       用于监听JavaBean对象绑定到HttpSession对象,和从HttpSession对象解绑的事件
8. HttpSessionActivationListener    用于监听HttpSession中对象活化和钝化的过程
@WebListener
public class MyListener implements ServletContextListener, ServletContextAttributeListener,
        ServletRequestListener, ServletRequestAttributeListener {
​
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        //在这里写一些项目初始化工作的代码
        ServletContext context = sce.getServletContext();       //通过ServletContext事件对象获取ServletContext源对象
        context.setAttribute("visits", context.getInitParameter("visits")); //将ServletContext初始值中的visits放入ServletContext的属性中
​
        System.out.println("ServletContext创建好了");
    }
​
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        //在这里写一些web容器关闭的时候的一些代码,比如一些资源释放等
        System.out.println("ServletContext销毁了");
    }
​
    @Override
    public void attributeAdded(ServletContextAttributeEvent scae) {
//        System.out.println("ServletContext新增属性了,新增的属性名:" + scae.getName() + ",属性值:" + scae.getValue());
    }
​
    @Override
    public void attributeRemoved(ServletContextAttributeEvent scae) {
//        System.out.println("ServletContext删除属性了,删除的属性名:" + scae.getName() + ",属性值:" + scae.getValue());
    }
​
    @Override
    public void attributeReplaced(ServletContextAttributeEvent scae) {
//        System.out.println("ServletContext替换属性了,替换的属性名:" + scae.getName() + ",属性值:" + scae.getValue());
    }
​
    @Override
    public void attributeAdded(ServletRequestAttributeEvent srae) {
//        System.out.println("ServletRequest新增属性了,新增的属性名:" + srae.getName() + ",属性值:" + srae.getValue());
    }
​
    @Override
    public void attributeRemoved(ServletRequestAttributeEvent srae) {
//        System.out.println("ServletRequest移除属性了,移除的属性名:" + srae.getName() + ",属性值:" + srae.getValue());
    }
​
    @Override
    public void attributeReplaced(ServletRequestAttributeEvent srae) {
//        System.out.println("ServletRequest替换属性了,替换的属性名:" + srae.getName() + ",属性值:" + srae.getValue());
    }
​
    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        //在这里写一些请求初始化的代码
        ServletRequest request = sre.getServletRequest();
        try {
            request.setCharacterEncoding("utf-8");  //设置请求的字符集编码
        } catch (UnsupportedEncodingException exception) {
            exception.printStackTrace();
        }
​
//        System.out.println("ServletRequest创建好了");
    }
​
    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        //在这里写一些请求执行完毕被销毁的代码
//        System.out.println("ServletRequest执行完毕,销毁了");
    }
}

 

9. WebScoket

WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

WebScoket实现步骤

1. 添加依赖
    <dependency>
      <groupId>javax</groupId>
      <artifactId>javaee-api</artifactId>
      <version>8.0</version>
    </dependency>
2. 创建一个类,并添加@ServerEndpoint(URL),其中URL就是WebSocket服务端映射的URL
3. 重写onOpen、onClose、onMessage、onError等方法,并添加其同名注解。
4. 前端实现WebSocket
@ServerEndpoint("/webSocket/{token}")
public class WebSocketServer {
​
    //保存WS客户端会话的集合
    static Map<String, Session> sessionMap = new HashMap<>();
​
​
    /**
     * 当有客户端连接到webSocket服务端时触发的方法
     *
     * @param session 连接webSocket服务端的会话
     */
    @OnOpen
    public void onOpen(@PathParam("token") String token, Session session) {
        String account = TokenUtils.verify(token);
        if (account != null) {
            System.out.println("有新客户端连接进来了,account是:" + account);
            sessionMap.put(account, session);
        }
    }
​
    /**
     * 当客户向webSocket服务器发送消息时触发的方法
     *
     * @param message 就是客户端发送的信息
     */
    @OnMessage
    public void onMessage(@PathParam("token") String token, String message) throws IOException {
        String account = TokenUtils.verify(token);
        System.out.println("account为'" + account + "'客户端发来信息了,信息是:" + message);
        if (message.equals("")) return;
​
        for (String key : sessionMap.keySet()) {
            if (!key.equals(account)) {    //把自己排除掉,不给自己发信息
                Session session = sessionMap.get(key);
                if (session != null) {
                    session.getBasicRemote().sendText(message);
                    System.out.println("给ID为"+key+"发送信息了.");
                }
            }
        }
​
//        sessionMap.get(你要定向发信息的接收者ID).getBasicRemote().sendText("发送内容");
    }
​
    /**
     * 当有客户端关闭/断开webSocket服务端连接时触发的方法
     *
     * @param session
     */
    @OnClose
    public void onClose(@PathParam("token") String token, Session session) {
        String account = TokenUtils.verify(token);
        System.out.println("account为'" + account + "'客户端断开连接了,ID是:" + session.getId());
        sessionMap.remove(account);
    }
​
​
    /**
     * 当有客户端与webSocket服务端连接发生异常/错误时触发的方法
     *
     * @param throwable
     */
    @OnError
    public void onError(Throwable throwable) {
        throwable.printStackTrace();
    }
​
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>学习Socket</title>
    <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
    <h1>学习Socket</h1>
    <div>
        <ul>
            <li v-for="message in divMessages" v-text="message"></li>
        </ul>
    </div>
    <input v-model="message"> <button @click="sendMessageToServer">发送</button>
</div>
​
<script>
    //创建一个vue对象,该app对象包含了vue程序的所有属性和函数
    const app = {
        setup() {
​
            let socket = null;    //定义是个webSocket客户端对象
            const message = Vue.ref("");    //要发送的信息
            const  divMessages = Vue.ref([]);
​
            /**
             * 连接webSocket服务端
             */
            const connectToWebSocket = () => {
​
                //创建一个webSocket客户端对象
                /*
                  http  => ws
                  https => wss
                 */
                socket = new WebSocket(location.protocol.replace("http","ws") + "//" + location.host + "/api/webSocket/" + localStorage.getItem("token"))
                //为socket对象绑定事件
                socket.onopen = ev => {
                    console.log("我连上服务器端了", ev);
​
                    //创建一个定时器,让socket定时循环向服务端发送信息,以保持连接状态
                    setInterval(() =>{
                        socket.send("");
                    }, 30000);
                }
                socket.onmessage = ev => {
                    console.log("服务器端发来消息了,消息是:", ev.data);
                    divMessages.value.push(ev.data);
                }
                socket.onclose = ev => {
                    console.log("断开服务器了,", ev);
                }
                socket.onerror = ev => {
                    console.log("连接服务端时发生了异常,", ev.reason);
                }
​
            }
​
            /**
             * 发送信息到服务端
             */
            const sendMessageToServer = () => {
                socket.send(message.value);
                message.value = "";
            }
​
​
            //调用连接webSocket服务端方法
            connectToWebSocket();
​
​
​
            //要把需要渲染的变量和函数返回出去
            return {
                message,divMessages,
                sendMessageToServer
            }
        }
    }
​
    //调用Vue的创建App方法,并挂载到id为“app”的DIV上面
    Vue.createApp(app).mount("#app");
​
</script>
</body>
</html>

10. ContentType

application/json                    消息主体是序列化后的 JSON 字符串,这个类型越来越多地被大家所使用
application/x-www-form-urlencoded   浏览器的原生form表单,提交的数据按照 key1=val1&key2=val2 的方式进行编码,key和val都进行了URL转码
multipart/form-data                 常见的 POST 数据提交的方式。我们使用表单上传文件时,必须让 form 的 enctype 等于这个值。
text/xml                            是一种使用 HTTP 作为传输协议,XML 作为编码方式的远程调用规范
text/html                           HTML格式
text/plain                          纯文本格式
image/gif                           gif图片格式    
image/jpeg                          jpg图片格式 
image/png                           png图片格式

文件上传

@MultipartConfig
@WebServlet("/fileUpload")
public class FileUploadServlet extends HttpServlet {
​
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("开始上传...");
        Part part = req.getPart("imgFile");   //根据参数获取上传文件部件
//        String fileName = part.getSubmittedFileName();  //获取图片本身的文件名
        String fileName = new Date().getTime() + ".jpg";
        System.out.println("fileName:" + fileName);
        //设置文件保存的路径
        String uploadPath = getServletContext().getInitParameter("uploadPath");
        File fileFolderPath = new File(uploadPath);
        if (!fileFolderPath.exists()) fileFolderPath.mkdirs();  //如果上传路径不存在,则创建上传路径
        System.out.println("uploadPath:" + uploadPath);
        //上传图片到指定的路径
        part.write(uploadPath + "/" + fileName);
​
​
        JSONObject object = new JSONObject(true);
        object.put("state", 200);
        object.put("value", "/upload/" + fileName);
        object.put("timestamp", LocalDateTime.now());
        resp.setContentType("application/json;charset=utf-8");
        resp.getWriter().write(object.toJSONString());
    }
}
<div class="formSubmit">
    <h4>完善个人信息</h4>
    <label>
        <div>生&nbsp;&nbsp;&nbsp;日:</div>
        <input type="date" placeholder="生日" v-model="birthday">
    </label>
    <label>
        <div>电&nbsp;&nbsp;&nbsp;话:</div>
        <input type="text" placeholder="电话" v-model="telephone">
    </label>
    <label>
        <div>头&nbsp;&nbsp;&nbsp;像:</div>
        <input type="file" v-model="imgFile" @change="changePath">
    </label>
    <button class="loginBtn" @click="submitInput">提交</button>
</div>
​
 // 表单提交
const submitInput=()=>{
    const formData=new FormData();
    formData.append("imgFile",imgFile.value);
    axios.post("/api/pictureUpload", formData, {
        headers:{
            Token: sessionStorage.getItem("token"),
            birthday:birthday.value,
            telephone:telephone.value,
            id:user.value.id,
        }
    })
        .then(response=>{
            console.log(response.data);
            user.value.headImage="../image/"+response.data.value;
        }).catch(error=>{
        console.log(error)    
    });
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

我愿为一粒沙

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

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

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

打赏作者

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

抵扣说明:

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

余额充值