一天学会sevlert基础

创建servlet步骤:

在pom.xml文件里面导入依赖:

<dependencies>
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
  </dependency>
    </dependencies>

scope表示这个依赖【jar包】生效的范围,默认是编译环境也就是complie,如果是test表示只有在测试目录下有效,provided表示在编译环境和测试环境都可以使用这个jar包,运行的时候不会使用这个jar包

java文件夹下面创建java文件,继承servlet类,并且实现servlet的方法:

loadOnStartup默认是-1,代表该内容是第一次访问,如果改成1,表示不是第一次访问了,此时不会调用init方法

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
@WebServlet(urlPatterns="/demo2",loadOnStartup = 1)
public class ServletDemo1 implements Servlet {
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    public ServletConfig getServletConfig() {
        return null;
    }

    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("servlet hello world");
    }

    public String getServletInfo() {
        return null;
    }

    public void destroy() {

    }
}

service(ServletRequest servletRequest, ServletResponse servletResponse)方法里面的方法体是需要写的,这里我写了个输出语句,然后启动tomcat,就可以运行你的java代码了

servlet执行流程$生命周期

执行流程:web项目->tomcat创建servlet对象并且调用里面的service方法

  1. 加载和实例化:当servlet第一次被访问的时候,由容器创建servlet对象
  2. 初始化:完成初始化,默认servlet第一次被访问的时候调用,且只调用一次:init()
  3. 请求处理:每次servlet被访问【刷新】,该方法都会被加载
  4. 服务终止:在servlet被销毁的时候【内存释放/服务器关闭】会被调用destroy方法

servlet接口中的方法介绍:

init(ServletConfig servletConfig):初始化

service(ServletRequest servletRequest, ServletResponse servletResponse):提供服务方法

destroy():销毁

ServletConfig getServletConfig():获取servletconfig对象

String getServletInfo():获取servlet信息

下面的方式使用HttpServlet

@WebServlet(urlPatterns = "/demo3")
public class ServletDemo3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

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

    }
}

相当于:

  1. 创建一个继承servlet的类,在该类中判断请求方式
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    HttpServletRequest request= (HttpServletRequest) servletRequest;
    //得到请求方式
    String method = request.getMethod();
    if("GET".equals(method)){
        doGet();
    }else if("POST".equals(method)){
        doPost();
    }
}
//希望子类可以重写,因此我们用protected
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
}

protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
}
  1. 子类继承的时候可以对方法进行重写
@WebServlet(urlPatterns = "/demo3")
public class ServletDemo3 extends ServletDemo4 {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    }

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

    }
}

servlet urlPatterns 配置

  1. 利用注解的方式:

@WebServlet(urlPatterns = "/demo3",“/demo4”):表示访问这个servlet的时候可以用这几个路径

  1. 不用注解,在web.xml文件中配置该servlet【较老的方法】
<!--获取需要访问的servlet类-->
<servlet>
  <servlet-name>demo3</servlet-name>
  <servlet-class>com.liku.web.ServletDemo3</servlet-class>
</servlet>
<!--配置访问路径-->
<servlet-mapping>
  <servlet-name>demo3</servlet-name>
  <url-pattern>/demo3</url-pattern>
</servlet-mapping>

request:

请求行

String	getMethod():获取请求方式
String	getContextPath():获取虚拟目录
StringBuffer	getRequestURL():获取统一资源定位符
String	getRequestURI():获取统一资源标识符
String getQueryString():获取请求参数(GET方式才有)

写一个页面,提交地址写我们servlet的web地址

<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>部署的第一个网页</title>
</head>
<body>
<form action="/rqd1" method="get">
    <input type="text" name="username"/>
    <br/>
    <input type="text" name="pwd"/><input type="submit"/>
</form>
</body>
</html>
@WebServlet("/rqd1")
public class RequestDemo extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取请求方式:GET
        String method = req.getMethod();
        System.out.println(method);
        //获取虚拟目录
        String contextPath = req.getContextPath();
        System.out.println(contextPath);
        //获取URL:http://localhost:8088/rqd1
        StringBuffer requestURL = req.getRequestURL();
        System.out.println(requestURL);
        //获取URI:/rqd1
        String requestURI = req.getRequestURI();
        System.out.println(requestURI);
        //获取请求参数:username=sad&pwd=asf
        String queryString = req.getQueryString();
        System.out.println(queryString);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    }
}

请求头

String getHeader(String name)

请求体

ServletInputStream getInputStream():获取字节输入流
BufferReader getReader():获取字符输入流【POST方式】
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    BufferedReader reader = req.getReader();
    String s = reader.readLine();
    System.out.println(s);
}

request通用方式获取请求参数:

Map<String,String[]>	getParameterMap():获取所有参数组成的map集合
String[]	getParameterValues(String name):根据名称获取参数值【数组】
String	getParameters(String name)根据名称获取参数值【单个值】

我把页面的请求方式改为get,在get中调用上面的几个方法:

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    resp.getWriter().write("hello,servlet-get");
    Map<String, String[]> parameterMap = req.getParameterMap();
    Set<Map.Entry<String, String[]>> entries = parameterMap.entrySet();
    for (Map.Entry<String, String[]> entry : entries) {
        System.out.println(entry.getKey()+": "+Arrays.toString(entry.getValue()));
    }
    Enumeration<String> parameterNames = req.getParameterNames();
    String str;
    while ((str=parameterNames.nextElement())!=null){
        System.out.println(str);
    }
    String pwd = req.getParameter("pwd");
    System.out.println(pwd);
}

当我把请求方式修改成post,并且在post中调用该方法,发现也是可以的,因此这种方式是通用的请求参数方式

请求参数有中文会出现乱码:

因为tomcat底层的编码格式时URL编码,但是使用的ISO-8859-1解码,因此会出现乱码,乱码处理方式如下:

对于post请求方式,因为post获取参数调用的时writer的方法,把编码格式改一下就可以:直接利用方法来修改编码格式,我这里页面时utf-8,因此servlet也是utf-8

request.setCharacterEncoding("UTF-8");

对于get请求方式:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String username = request.getParameter("username");
    username=new String(username.getBytes(StandardCharsets.ISO-8859-1),StandardCharsets.UTF_8);
    //我这里页面编码格式为utf-8,所以这种方式是没用的
    System.out.println(username);
}

在tomcat8后,如果网页的编码方式是UTF-8,使用GET方法提交请求是不用处理乱码问题的,因为tomcat8后默认编码处理方式是UTF-8,编码形式不冲突,就不会有乱码问题. 如果网页的编码方式不是"utf-8",则可以采取以上两种方式解决乱码问题.

请求转发forword

一种在服务器内部的资源跳转方式:

graph TD 浏览器页面--发送请求-->资源A 资源A--请求转发-->资源B 资源B--响应-->浏览器页面

代码如下【我这里页面的请求方式是get】:

请求转发资源间的共享数据常用的方法:

void setAttribute(String name,Object obj)
Object getAttribute(String name)
void removeAttribute(String name)
@WebServlet("/rqs2")
public class RequestDemo2 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("demo2.get");
        request.setAttribute("username","hello");
        request.getRequestDispatcher("/RequestDemo3").forward(request,response);<br/>
    }
}
@WebServlet("/RequestDemo3")<br/>
public class RequestDemo3 extends HttpServlet {<br/>
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println(request.getAttribute("username"));
    }
}

请求转发的特点:

  1. 请求转发浏览器地址栏路径不会发生变化

  2. 只能转发到当前服务器的内部资源

  3. 只有一次请求,可以在转的资源间使用request共享数据

Response:

响应数据分为三部分:

  1. 响应行
void setStatus(int sc):设置响应状态码
  1. 响应头
void setHeader(String name,String value):设置响应头键值对
  1. 响应体
PrintWriter getWriter():获取字符输出流
ServletOutputStream getOutputStream():获取字节输出流

redirect完成重定向:

也是一种资源跳转方式,但是跟请求转发不一样:

graph TD 浏览器页面--发送请求-->资源A 资源A--响应并告知资源B可以处理-->浏览器页面 浏览器页面--发送请求-->资源B 资源B--响应-->浏览器页面

资源A实现重定向方式:

  1. resp.setStatus(302);
    resp.setHeader("location","资源B的路径")
    
  2. response.sendRedirect("资源B的路径");
    
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    System.out.println("demo2.get");
    response.setStatus(302);
    response.setHeader("location", "/RequestDemo3");
    //这里路径,如果是新版的不需要加项目名称
    response.sendRedirect("/RequestDemo3");
   }

重定向的特点:

  1. 浏览器的地址栏会发生变化
  2. 重定向可以到任意位置的资源
  3. 两次请求,不能在多个资源使用request共享数据

路径问题:

  1. 浏览器使用:需要加虚拟目录
  2. 服务器使用:不需要加虚拟目录

response响应字符数据

PrintWriter a=response.getWriter()
a.writer("aaa"); //向页面上写内容

如果想在页面上写一些标签,需要设置内容类型

如果是中文需要看一下你页面的编码格式,然后解码格式也要设置成相应的格式,我这里中文解码格式是GBK,因此我把编码格式也改成GBK就不会出现乱码

response.setCharacterEncoding("GBK");
response.setHeader("content-type", "text/html");

也可以直接:

response.setContentType("text-html;charset=xx");

Response响应字节数据

ServletOutputStream stream=resp.getOutputStream();
stream.write(字节数据);

从本地上传一张图片:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    ServletOutputStream outputStream = response.getOutputStream();
    InputStream inputStream=new FileInputStream("E:\\欧阳路路\\student\\07欧阳路路\\HbuilderX\\day01\\img/R-C.jpg");
    byte[] bytes=new byte[1024];
    int len;
    while ((len=inputStream.read(bytes))!=-1){
        outputStream.write(bytes,0,len);
    }
}

但是上面的方法是初学io的时候用的方法,我们现在可以直接用工具包,在pom.xml导入依赖:

    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.6</version>
    </dependency>

使用的时候导包别导错了,是下面的包:

import org.apache.commons.io.IOUtils;

上面上传我们就简化成:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    ServletOutputStream outputStream = response.getOutputStream();
    InputStream inputStream=new FileInputStream("E:\\欧阳路路\\student\\07欧阳路路\\HbuilderX\\day01\\img/R-C.jpg");
    IOUtils.copy(inputStream,outputStream);
}
posted @ 2023-01-07 17:35  Liku007  阅读(46)  评论(0编辑  收藏  举报