admin管理员组

文章数量:1646247

本文需要结合【HTTP】阅读:
https://blog.csdn/weixin_42915286/article/details/84871898

https://www.bilibili/video/av40697944?from=search&seid=9275670543812089695

说在前面

JavaEE是一个开放的平台,包含的技术很多,主要有13种;
需要强调的是:不是每个技术都要用到,实际上需要有选择地使用;

实际上,把每一种JavaEE技术都精通是不现实的,有人则认为,若能够成为JavaEE程序员,必须掌握的技术是:Java、Servlet、JSP;若这三门没学好就去追求spring等web【框架】,也只是空中楼阁,华而不实的;

—————————————————————————————

Servlet 3.0

Servlet = Java服务器小程序
Applet = Java客户端小程序(严重过时)

Servlet是一个供其他 Java程序(【Servlet引擎】或【Web服务器】或【Tomcat】)调用的Java类,他不能独立运行,它的运行完全由Servlet引擎来控制和调度;

针对客户端的多次Servlet请求,通常情况下,【服务器只会创建一个Servlet实例对象(单例模式)】,也就是说Servlet实例对象一旦创建,也就是说Servlet实例对象一旦创建,他就会潴留在内存中,为后续的其他请求服务,直至Web容器退出或者reload该web应用,Servlet实例对象才会被销毁;

重要部分:页面搜索:Servlet的单例问题

  • 提问:为什么会出现Servlet?
    需求:请你用现有的JavaEE技术开发一个动态网页,比如让用户留言,其他人可回复交互;
    用普通的Java技术完成不了,那么Sun就开发了Servlet技术供程序员使用;
    Servlet是JavaEE中出现较早的一项技术,在Struts、Spring出现前,动态网页技术都采用Servlet,在1999-2000大行其道;
    Servlet是JSP的基础,是Spring Controller的本质;是JavaWeb的基础,到2019年的今天仍然有重要性;

  • 提问:Servlet特点?
    1.服务器端(直接说Tomcat也没问题)调用和执行的;(非客户端!)
    2.Java编写;(Servlet就是一个Java写的类)
    3.按照Servlet规范开发的;(规范需要花时间学习下)
    4.功能强大,几乎可以完成所有网站功能(很多老程序员仍然喜欢用Servlet写整个网站)
    5.Spring Controller的基础;


【Servlet有规范】!
必须放在Tomcat - webapps - examples - ??? - WEB-INF - classes文件夹
因为Servlet说到底是Java程序,Java程序不能直接运行,要编译成classes;
另外,还要部署web.xml文件,一个Sevlet类对应一个<servlet><servlet-mapping>
(项目中所有Servlet类的配置都写在同一个web.xml中)

需求:
通过一个用户管理系统来讲解Servlet,单纯用Servlet来实现,是一个很好练习Servlet技术的案例;
操作人员:
管理员;普通用户;
同时还需要完成:
分页、网站计数器、保存用户访问网站的习惯、追踪用户的来源;

Internet上供外接访问的Web资源有:
静态Web资源(HTML):web页面中工人们浏览的数据始终是不变的;
动态Web资源(JSP/Servlet):web页面中工人们浏览的数据是有程序产生的,不同时间点访问web页面看到的内容各不相同;

Java中,动态web资源开发技术统称为JavaWeb;

——————————————

b/s结构和c/s结构的比较

这部分的选择,程序员一般不参与,由项目经理说了算;

b/s
即:browser/server 浏览器 服务器
优势:
1.开发成本低;
2.管理维护简单;(浏览器安装就可以用)
3.产品升级便利;(比如新浪想要新增一个调查功能,开个会加个模块就可以了;但如果微信想要添加一个新模块,需要对全世界的客户端添加该功能)
4.对用户的培训费用低;
5.用户使用方便,出现故障几率小;(比如使用c/s制作了一款软件给珠宝开发商,正式使用时,老板和与员工却发现彼此看不到对方上线的情况,后来开发终于找到原因所在:网管的防火墙只开放了80端口,且不允许开放其他端口,那么开发就努力使用防火墙穿透tunnel技术解决了问题)
不足:
1.安全性不足;(因为浏览器是别人写的;浏览器大多是开源的,可被大众研究)
2.客户端不能随心变化,受到浏览器的限制;

c/s 用tcp/ip协议(socket)
即:client/server 客户端(往往是程序员开发的) 服务器;

b/s和c/s从本质上来说没有区别,只是表现形式不一样:
b/s:客户端用浏览器,是现有的工具,程序员无需自己再包装;
c/s:客户端自己来开发,程序员要自己包装tcp/ip;

——————————————

实现Servlet

  • 提问:实现Servlet有几种方式?
    三种;
  • 1.implements Servlet接口;(稍微重要,已废弃)
    但通过此方式很好理解Servlet生命周期,而Servlet生命周期必须掌握!!!
  • 2.extends GenericServlet类;(高不成低不就,已废弃)
  • 3.extends HttpServlet类;(唯一选择,最重要!!!)

需求:
用实现接口的方式开发一个Servlet,要求该Servlet可以显示HelloWorld,同时显示当前时间;
(用静态文件HTML是做不到的,动态文件可以实现)

如何新建?
页面搜索:TODO

implements Servlet

查阅JavaEE API,可知里面就五个方法:
而既然需要继承一个接口,那么这五个方法就都要实现;

  • init()
    初始化Servlet,就是把该Servlet装载到内存中,只会被调用一次;
  • getServletConfig()
    得到ServletConfig对象;(之后会讲)
  • service()
    核心;服务函数,写业务逻辑代码,该函数每次都会被调用;
  • getServletInfo()
    得到Servlet的配置信息;
  • destroy()
    销毁,从内存中清除,只会被调用一次;
    (和init()相对应,都只加载一次)

tips:
若Servlet被访问十次,init()只会被调用一次,service()会被调用十次,destroy()会被调用一次;

——————————————
Servlet01 implements Servlet

package com.yau.Servlet;

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

public class Servlet01 implements Servlet{

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null; // 为空时肯定编译失败
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("Hello,World!!!" + new Date());
        // 浏览器输出 servletResponse.getWriter().println("Hello,World!!!"+new Date());
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

配置web.xml
映射:对已注册的Servlet进行映射;


这么配置只能在IDE的console返回语句;
浏览器访问:http://localhost:8080/Servlet01
IDE可返回语句;(浏览器无返回)
(注意:默认浏览器访问http://localhost:8080,浏览器返回$END$;记得注意修改URL,才能正确访问)

没看完:
https://www.bilibili/video/av40697944/?p=10
——————————————

Servlet生命周期(重要)

必须搞得很明白!!!


—————————————————————————————

extends HttpServlet

Servlet 3.0

市面上的公司,90%都是通过HttpServlet的方式来开发Servlet;
追踪源码,会发现doGet()doPost()都源自于service(),等于对此方法进行了包装而已;
Servlet3.0开始,配置Servlet支持注解方式,但还是保留了配置web.xml方式;

HttpServlet指能够处理HTTP请求的Servlet,他在原有Servlet接口上添加了一些与HTTP协议进行处理的方法,他比Servlet接口的功能更为强大,因此开发人员在编写Servlet时,通常应该implements这个类,避免直接去实现Servlet接口;
HttpServlet在实现Servlet接口时,Override了service(),该方法内的代码会自动判断用户的请求方式,若为GET请求,则调用HttpServlet的doGet方法,若为Post请求,则调用doPost方法;
因此客服人员在编写Servlet时,通常只需要Override doGet或者doPost方法,而不需要Override service方法;

配置Servlet的nameurlPatterns有两种方式:

1.web.xml文件中配置
2.Servlet类上使用@WebServlet注解进行配置(此方法不用web.xml)

——————————————
@WebServlet常用属性

属性	               类型	        是否必须	说明
asyncSupported	   boolean	      否	指定Servlet是否支持异步操作模式
displayName	       String	      否	指定Servlet显示名称
initParams	       WebInitParam[] 否	配置初始化参数
loadOnStartup	   int	          否	标记容器是否在应用启动时就加载这个Servlet
name	           String	      否	指定Servlet名称
urlPatterns/value  String[]	      否	这两个属性作用相同,指定Servlet处理的url

——————————————
方法1
Servlet02
(注意:此方法我采用的是Web Application模版,非Spring Boot)

public class Servlet02 extends HttpServlet {
    protected void doPost(HttpServletRequest request,
                          HttpServletResponse response)
                          throws ServletException, IOException {
        response.getWriter().println("I am httpservlet doGet()");
    }

    protected void doGet(HttpServletRequest request,
                         HttpServletResponse response)
                         throws ServletException, IOException {
        response.getWriter().println("I am httpservlet doPost()");
    }
}

web.xml

    <servlet>
        <servlet-name>Servlet02</servlet-name>
        <servlet-class>com.yau.Servlet.Servlet02</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>Servlet02</servlet-name>
        <url-pattern>/Servlet02</url-pattern>
    </servlet-mapping>

访问:http://localhost:8080/Servlet02
——————————————
方法2

MyServlet
(注意:此方法我采用的是Spring Boot 2.0模版,SB特别之处在于在启动项添加@ServletComponentScan

@WebServlet(name="myservlet",urlPatterns = "/myservlet")
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter out = resp.getWriter();
        String str = "doGet() here.";
        out.println(str);
    }

    @Override
    protected void doPost(HttpServletRequest req, 
                          HttpServletResponse resp) 
                          throws ServletException, IOException {
        PrintWriter out = resp.getWriter();
        String str = "doPost() here.";
        out.println(str);
    }
}
@SpringBootApplication
@ServletComponentScan("com.yau.sb_servlet.Servlet")
public class ServletApp {

    public static void main(String[] args) {
        SpringApplication.run(ServletApp.class, args);
    }
}

访问:http://localhost:8080/myservlet
——————————————
默认返回doGet方法:

doGet() here.

doGet方法的参数都写在URL中,比如
localhost:8080/myservlet?username=haha
存储在HTTP报文的第一行,且其数据容量一般不能超过1K;

GET / myservlet?username=haha HTTP/1.1
User-Agent	Mozilla/5.0 (Macintosh...
Accept	text/html...
Accept-Encoding	gzip, deflate
Connection:Keep-Alive

这样很明显是不安全的,不建议用doGET方法!!!
——————————————
如何返回doPost方法?

resources - static (一定是static文件夹)下新建一个html文件,比如login.html
他的form action要指明Servlet的name,本html才可以指向指定Servlet;

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Test</title>
</head>
<body>
<form action="myservlet" method="post">
    u:<input type="text" name="username"/>
    <input type="submit" name="btnLogin" value="Login"/>
</form>
</body>
</html>

访问该html:http://localhost:8080/login.html

返回该Servlet的doPost方法内容:

doPost() here.

doPost方法的请求参数都存储在HTTP请求包中;

GET / myservlet HTTP/1.1
User-Agent	Mozilla/5.0 (Macintosh...
Accept	text/html...
Accept-Encoding	gzip, deflate
Connection:Keep-Alive

username=haha

传送的数据量无限制,POST提交的参数后台更容易解析(即使是中文数据也更容易解决);
对比doGet,建议用doPost;
————————————————————————————
getParameter()
来自:public interface ServletRequest
getParameter(java.lang.String name)
Returns the value of a request parameter as a String, or null if the parameter does not exist.
会以String形式返回request参数,如果属性不存在,会返回null

myservlet:

resp.getWriter().println("the post name = "
               +req.getParameter("username"));

html中配置mthod=post

——————————————
总结:
通过HttpServlet去开发Servlet,需要重写doGet和doPost方法,这种方法最为流行;

表单提交get请求和post请求的区别:
1.从安全来看,get<post,get提交的数据会在浏览器的地址栏显示;
2.从提交的内容大小来看,get<post,但是get提交的数据不能大于1K,而post提交的数据理论上不受限制,但是集中建议不要大于64K;
3.请求响应速度来看,get>post,get要求服务器立即处理请求,而post可能形成一个队列请求;

————————————————————————————

Servlet细节(重要)

——————————————
由于客户端是通过URL访问web服务器中的资源,所以Servlet若想被外界访问,必须把Servlet映射到一个URL上,此部分工作在
(1)web.xml中由<servlet>``<servlet-mapping>
或者 (2)@WebServlet(name = "", urlPatterns = "")来完成;

————————————————————————————
同一个已注册的Servlet可指定多个urlPattern
同一个已注册的Servlet可映射到多个URL上

  • web.xml:
  • @WebServlet:
    web.xml里的urlPattern在@WebServlet中叫做:urlPatterns,是复数;
    那么可以猜想,这个属性本身就支持填写多个urlPattern???
    查看源码,果然,urlPatterns是一个String数组,那么在@WebService写多个URL的格式就很明朗了;

    ————————————————————————————
    映射一个Servlet时可以写多层

比如:
<url-pattern>/one/two.html</url-pattern>
(这里的.html只是url的一部分,不代表是真的html文件!!)

比如:
@WebServlet(name="myservlet",urlPatterns = {"/myservlet/haha/yoyo"})
————————————————————————————
Servlet映射到的URL中可以使用通配符*,很有用!!

只能有两种固定格式
(1).*.扩展名
(2).以/开头,以/*结尾

易错:
这两种方式注意区分格式,第一种星点do前面不能添加斜杠;

通配符的优先级问题总结

——————————————
/*

这里有个很有意思的点:可以直接写/*,代表所有请求都映射给他;
那么意思是:当用户乱输入URL后缀时,/*就可以把这个不存在的URL映射到,返回用户我们指定的错误页面,不会返回一个让用户看不懂的报错页面;

但这样又来了一个问题:
如果我们精心配制的urlPa

本文标签: 框架servletAPI