Servlet

Servlet简介

Servlet是sun公司开发的一款动态Web技术

把实现了Servlet接口的java程序叫Servlet

构建Servlet

新建一个Maven项目,删掉里面的src文件夹,这个空的工程就是Maven的主工程

image-20210429215244032

去导入相关的包

image-20210429215558868

image-20210429215920469

放入pom.xml中,有红色报错就刷新

image-20210429215645180

由于是Servlet项目需要建一个Webapp

image-20210429224707547

这里路径每次都需要重新设置的话,可以参考https://blog.csdn.net/tanghuan0827/article/details/107023594

image-20210429224844845

image-20210429225056243

关于Maven父子工程的理解:

在父项目中会有

  <modelVersion>4.0.0</modelVersion>

父项目中的JAR包子项目可以直接使用

再新建两个文件夹

image-20210429225555346

Maven环境优化

1.修改web.xml为最新的

2.将maven架构搭建完整

编写一个Servlet程序

新建一个package里面新建java文件

1.编写普通类

2.实现Servlet接口,直接继承httpServlet

以下是他们直接的关系

public class HelloServlet extends HttpServlet {
}
public abstract class HttpServlet extends GenericServlet {
}
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
}
public interface Servlet {
    void init(ServletConfig var1) throws ServletException;
    ServletConfig getServletConfig();
    //主要方法
    void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
    String getServletInfo();
    void destroy();
}

为什么我们的程序是Servlet程序,因为继承了HttpServlet

HttpServlet抽象类 继承了GenericServletGenericServlet实现了Servlet接口,因此我们自己的类只需要继承HttpServlet既可以。

Servlet接口包含在GenericServlet中实现了,判断调用了什么类型方法,然后去调用默认实现

image-20210429231742018

最后类的编写为:

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter();
        writer.print("Hello Servlet");
    }

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

3.编写Servlet的映射

我们写的java程序,需要浏览器访问,浏览器需要连接Web服务器,所以我们需要在Web服务中注册我们写的Servlet,还需要浏览器能够访问的路径

  <!--注册Servlet-->
  <servlet>
      <!--名字和下面的相同就行-->
    <servlet-name>Hello</servlet-name>
     <!--项目下的类-->
    <servlet-class>com.ylc.HelloServlet</servlet-class> 
  </servlet>
  <servlet-mapping>
       <!--Servlet请求路径-->
    <servlet-name>Hello</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>

4.配置Tomcat

image-20210429235151662

image-20210429235323155

5.测试tomcat运行成功

image-20210429235545373

6.接下来访问映射的那个请求路径

image-20210429235704527

Servlet实现原理

Serlvet是由Web服务器调用,Web服务器其收到六零看起请求之后会:

image-20210503143547899

Mapping

匹配请求路径

  <servlet-mapping>
    <servlet-name>Hello</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>Hello</servlet-name>
    <url-pattern>/hello/*</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>Hello</servlet-name>
    <url-pattern>.ylc</url-pattern><!--自定义后缀请求路径-->
  </servlet-mapping>

*前面不能加任何项目路径

优先级问题:指定了固定路径优先级最高

ServletContext对象

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

共享数据

在这个ServletContext保存的数据,在其他servlet可以拿到

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    ServletContext servletContext=this.getServletContext();
    String username="ylc";
    servletContext.setAttribute("username",username);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    ServletContext servletContext= this.getServletContext();
    resp.setContentType("text/html");
    resp.setCharacterEncoding("utf-8");
    String username=(String) servletContext.getAttribute("username");
    resp.getWriter().print("名字:"+username);
}
<servlet>
  <servlet-name>GetC</servlet-name>
  <servlet-class>GetServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>GetC</servlet-name>
  <url-pattern>/getc</url-pattern>
</servlet-mapping>
<servlet>
  <servlet-name>hello</servlet-name>
  <servlet-class>helloServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/helloServlet</url-pattern>
</servlet-mapping>

运行结果:

image-20210506213639053

请求转发

A想要从C那里拿到东西,但是不能直接连接到C,只能通过B从C那里拿到东西,C给B,B再给A。

这样A和C就不用会面,路径也不需要发生改变,这就是转发的概念

重定向就是A找B要一个资源,B告诉A要去C那里拿,然后B就请求C资源

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    ServletContext servletContext = this.getServletContext();
    System.out.println("请求转发");
    servletContext.getRequestDispatcher("/getc").forward(req,resp);
}

读取资源文件

<context-param>
  <param-name>url</param-name>
  <param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        String url = servletContext.getInitParameter("url");
        resp.getWriter().print(url);
    }

image-20210506220514339

读取资源文件

Properties

username="ylc"
passworld=123

在Java目录和resources中新建Properties都被打包到了同一个目录下:classes,俗称:classpath

需要一个文件流

读取不到资源是因为限定了资源的格式

<build>
  <resources>
    <resource>
      <directory>src/main/resources</directory>
      <includes>
        <include>**/*.properties</include>
        <include>**/*.xml</include>
      </includes>
      <filtering>true</filtering>
    </resource>
    <resource>
      <directory>src/main/java</directory>
      <includes>
        <include>**/*.properties</include>
        <include>**/*.xml</include>
      </includes>
      <filtering>true</filtering>
    </resource>
  </resources>
</build>
public class ServletText04  extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        InputStream resourceAsStream = servletContext.getResourceAsStream("/WEB-INF/classes/db.properties");
        Properties properties = new Properties();
        properties.load(resourceAsStream);
        String user=properties.getProperty("username");
        String passworld=properties.getProperty("passworld");
        resp.getWriter().print(user+":"+passworld);
    }
}
<servlet>
  <servlet-name>Pro</servlet-name>
  <servlet-class>ServletText04</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>Pro</servlet-name>
  <url-pattern>/Pro</url-pattern>
</servlet-mapping>

image-20210506224140855

HttpServletRequest

HttpServletResponse

Web服务器接收到客户端的请求,如果要给客户端一些响应的消息用HttpServletResponse

负责向浏览器发送数据的方法

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 setDateHeader(String var1, long var2);
void addDateHeader(String var1, long var2);
void setHeader(String var1, String var2);
void addHeader(String var1, String var2);
void setIntHeader(String var1, int var2);
void addIntHeader(String var1, int var2);

响应的状态码

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;

Response下载图片

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <servlet>
    <servlet-name>fileServlet</servlet-name>
    <servlet-class>FileServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>fileServlet</servlet-name>
    <url-pattern>/fileServlet</url-pattern>
  </servlet-mapping>
</web-app>
public class FileServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取要下载文件的路径
        String path="E:\javaweb-servlet\FileServletText\src\resourse\1.jpg";
        //加载的文件名
        String filename=path.substring(path.lastIndexOf("\")+1);
        //让浏览器支持下载
        resp.setHeader("Content-Disposition","attachment; filename="+ URLEncoder.encode(filename,"UTF-8"));
        //获取下载的文件
        FileInputStream stream=new FileInputStream(path);
        //建立缓冲区
        int len=0;
        byte[] bytes=new byte[1024];
        //获取outputstream 向客户端写入数据
        ServletOutputStream outputStream = resp.getOutputStream();
        //将fileputputstream写入缓冲区
        while ((len=stream.read(bytes))>0)
        {
            outputStream.write(bytes,0,len);
        }
        stream.close();
        outputStream.close();
    }
}

image-20210508000438014

重定向

resp.sendRedirect();

请求转发和重定向的区别:

相同点:页面都会跳转

不同点:

重定向的时候url会发生变化 302

转发的时候url不会发生变化 307

原文地址:https://www.cnblogs.com/cg-ww/p/14825724.html