Servlet

Servlet

  • Servlet 是 Java提供的一门动态web资源开发技术

  • Servlet 是 JavaEE 规范之一,其实就是一个接口,将来我们需要定义Servlet类实现Servlet接口,并由web服务器运行Servlet

快速入门

  1. 创建 web 项目,导入 Servlet 依赖坐标

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

  2. 创建:定义一个类,实现 Servlet 接口,并重写接口中所有方法,并在service方法中输入一句话

  3. 配置:在类上使用@WebServlet 注解,配置该 Servlet的访问路径

  4. 访问:启动Tomcat,浏览输入URL 访问该Servlet

package com.wen;
​
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
​
@WebServlet("/demo1")
public class ServletDemo1 implements Servlet {
​
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("Servlet hello world...");
    }
​
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {}
    @Override
    public ServletConfig getServletConfig() {return null;}
    @Override
    public String getServletInfo() {return null;}
    @Override
    public void destroy() {}
}

Servlet体系

Servlet urlPattern配置

  1. 一个Servlet,可以配置多个 urlPattern

    @WebServlet(urlPattern = {"/demo1", "/demo2"})

  2. urlPattern 配置规则

XML 配置方式编写 Servlet

  • Servlet 从3.0版本后开启支持使用注解配置,3.0版本前只支持 XML 配置文件的配置方式

  • 步骤:

    1. 编写 Servlet 类

    2. 在 web.xml 中配置该 Servlet

      <!--Servlet 全类名-->
      <servlet>
          <servlet-name>demo4</servlet-name>
          <servlet-class>com.wen.ServletDemo4</servlet-class>
      </servlet>
      ​
      <!--Servlet 访问路径-->
      <servlet-mapping>
          <servlet-name>demo4</servlet-name>
          <url-pattern>/demo4</url-pattern>
      </servlet-mapping>


Request

  • 请求数据分为3部分:

    1. 请求行:

      // 请求行:GET/request-demo/req1?username=zhangsan HTTP/1.1
      String getMethod():获取请求方式:GET
      String getContextPath():获取虚拟目录(项目访问路径):/request-demo
      StringBuffer getRequestURL():获取URL(统一资源定位符):
                              http://localhost:8080/request-demo/req1
      String getRequestURI():获取URL(统一资源标识符:/request-demo/req1
      String getQueryString():获取请求参数(GET方式):username=zhangsan&password=123

    2. 请求头:

      // 请求头:User-Agent:Mozilla/5.0 Chrome/91.0.4472.106
      String getHeader(String name):根据请求头名称,获取值

    3. 请求体:

      // 请求体:username=lishi&password=123
      ServletInputStream getInputStream():获取字节输入流
      BufferedReader getReader():获取字符输入流

Request 通用方式获取请求参数

Map<String,String[]> getParameterMap():获取所有参数Map集合
String[] getParameterValues(String name):根据名称获取参数值(数组)
String getParameter(String name):根据名称获取参数值(单个值)
Map<String, String[]> map = request.getParameterMap();
for (String key:map.keySet()){
    System.out.print(key+":");
    String[] values = map.get(key);
    for (String value:values){
        System.out.print(value+" ");
    }
    System.out.println();
}

请求参数中文乱码解决

// POST 获取参数的方式,getReader()
// POST解决方法:设置输入流编码
request.setCharacterEncoding("UTF-8");  // 设置字符输入流的编码
​
// GET 获取参数的方式,getQueryString()
// 乱码原因:tomcat进行URL解码,默认的字符集ISO-8859-1
// 通用方法(GET/POST):先编译,再解码
String username = request.getParameter("username");
username = new String(username.getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8);

Tomcat 8.0 之后,已将GET请求乱码问题解决,设置默认的解码方式为UTF-8

URL编码实现

// 编码
URLEncoder.encode(str,"UTF-8");
// 解码
URLDecoder.decode(s,"ISO-8859-1");

请求转发

  • 请求转发(forward):一种在服务器内部的资源跳转

  • 实现方式

    request.getRequestDispatcher("资源B路径").forward(request,response);
  • 请求转发资源间共享数据:使用Request对象

    void setAttribute(String name,Object o):存储数据到 request 域中
    Object getAttribute(String name):根据 Key,获取值
    void removeAttribute(String name):根据 key,删除该键值对
  • 特点:

    • 浏览器地址栏路径不发生变化

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

    • 一次请求,可以在转发的资源间使用request共享数据


Response

  • 响应数据分为3部分:

    1. 响应行:

      // 请求行:HTTP/1.1 200 OK
      void setStatus(int sc):设置响应状态码
    2. 响应头:

      // 请求头:Content-Type:text/html
      void setHeader(String name,String value):设置响应头键值对
    3. 响应体:

      // 请求体:<html><head></head><body></body></html>
      PrintWriter getWriter():获取字符输出流
      ServletOutputStream getOutputStream():获取字节输出流

Response 完成重定向

  • 重定向(Redirect):一种资源跳转方式

  • 实现方式:

    resp.setStatus(302);
    resp.setHeader("Location","资源B的虚拟路径");
    ​
    // 简化方式完成重定向
    resp.sendRedirect("资源B的虚拟路径");
  • 特点:

    • 浏览器地址栏路径发生变化

    • 可以重定向到任意位置的资源(服务器内部、外部均可)

    • 两次请求,不能在多个资源使用request共享数据

路径问题

  • 明确路径谁使用

    • 浏览器使用:需要加虚拟目录(项目访问路径)

    • 服务端使用:不需要加虚拟目录


Response 响应字符数据

// 解析html,并解决中文乱码问题
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
// response.setHeader("content-type","text/html");  // 可以解析html,但有中文乱码问题
​
writer.write("<h1>中文</h1>");
// 流不需要关闭,随着响应结束,response 对象销毁,由服务器关闭
// 注意中文乱码问题

Response 响应字节数据

// 读取文件
FileInputStream fis = new FileInputStream("E:\\File\\1.png");
// 获取response 字节输出流
ServletOutputStream os = response.getOutputStream();
​
IOUtils.copy(fis,os);
<!--复制工具类-->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>

HttpServlet原理伪实现

public class MyHttpServlet2 implements Servlet {
        @Override
    public void service(ServletRequest req, ServletResponse res) 
                        throws ServletException, IOException {
​
        HttpServletRequest request = (HttpServletRequest) req;
        // 1. 获取请求方式
        String method = request.getMethod();
        // 2. 判断
        if("GET".equals(method)){
            // get方式的处理逻辑
            doGet(req,res);
        }else if("POST".equals(method)){
            // POST方式的处理逻辑
            doPost(req,res);
        }
    }
}
​
​
public class ServletDemo2 extends MyHttpServlet2 {
    @Override
    protected void doGet(ServletRequest req, ServletResponse res) {
        System.out.println("get...");
    }
    @Override
    protected void doPost(ServletRequest req, ServletResponse res) {
        System.out.println("post...");
    }
}

注册

package com.wen.web;
​
import com.wen.mapper.UserMapper;
import com.wen.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
​
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
​
@WebServlet(name = "RegisterServlet", value = "/registerServlet")
public class RegisterServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1. 接收数据
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        User user = new User();
        user.setUsername(username);
        user.setPassword(password);
​
        // 调用MyBatis完成查询
        // 获取 SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        // 获取SqlSession对象,用它来执行SQL
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 获取Mapper
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // UserMapper 接口的代理对象, 调用方法
        // 判断用户名是否存在
        User user01 = userMapper.selectByUsername(username);
​
        if (user01 == null) {
            userMapper.add(user);
            // 提交事务
            sqlSession.commit();
        } else {
            // 获取字符输出流,并设置content type
            response.setContentType("text/html;charset=utf-8");
            response.getWriter().write("用户名存在");
        }
        // 释放资源
        sqlSession.close();
    }
​
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值