目 录CONTENT

文章目录

Servlet

FatFish1
2025-02-13 / 0 评论 / 0 点赞 / 77 阅读 / 0 字 / 正在检测是否收录...

servlet与tomcat

servlet的定义

servlet实际上就是由java便携的代码段,承接输入,返回输出

它用于把前端接收到的数据进行处理,返回一个web可识别的内容。既然是通过web做交互,肯定就不能随便定义一些入参返回值,要有一个统一规范,因此java提供了servlet接口

狭义的Servlet是指Java提供的servlet接口jdk,广义的Servlet是指任何实现了这个Servlet接口的类

servlet与tomcat的关系

tomcat是web服务器的运行环境,是servlet的容器,也就是java代码的运行环境

负责接收web来的请求(例如HTTP请求),包装成servlet可识别的request,同时创建一个servletResponse用于接收servlet处理结果,调用servlet的serviceAPI进行处理,最终把response包装成web可识别的返回(例如HTTP返回),最终返回给客户端

tomcat搭建了协议格式与servlet开发协议之间的桥梁

tomcat还负责从磁盘中加载对应的servlet

java.servlet的开发规范

java.servlet的架构

Servlet API 包含以下4个Java包:

  • javax.servlet 其中包含定义servlet和servlet容器之间契约的类和接口。

  • javax.servlet.http 其中包含定义HTTP Servlet 和Servlet容器之间的关系。

  • javax.servlet.annotation 其中包含标注servlet,Filter,Listener的标注。它还为被标注元件定义元数据。

  • javax.servlet.descriptor,其中包含提供程序化登录Web应用程序的配置信息的类型。

servlet包中的接口及抽象类

servlet接口

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的生命周期及对应的方法:初始化init()、运行service()、销毁destory()

  • 初始化阶段承担的事务包括:

    • servlet容器加载servlet类,把servlet类的.class文件读取到内存

    • servlet容器创建一个servletConfig对象,包含servlet的初始化信息

    • servlet容器创建一个servlet对象

    • servlet容器调用servlet对象的init方法进行初始化(根据配置决定)

    • init():init方法的调用时机是由<load-on-startup>配置决定的,当配置值大于等于0,则在servlet实例化的时候执行,值越大越迟执行,如果小于0或没配置,则在Servlet第一次被请求时调用。init方法仅调用一次。

  • 运行阶段承担的事务包括:

    • servlet容器收到请求,针对这个请求创建servletRequest和servletResponse对象,然后调用并传递给service⽅法

    • service()方法:通过servletRequest对象获得请求的信息。并处理该请求。再通过servletResponse对象⽣成这个请求的响应结果。然后销毁servletRequest和servletResponse对象。不管请求是get还是post还是其他的,都是由service方法统一承接。

  • 销毁阶段承担的事务包括:

    • 当web应用被终止时,servlet容器会先调用servlet对象的destrory⽅法,然后再销毁servlet对象,同时也会销毁与servlet对象相关联的servletConfig对象。

    • destroy()方法,当要销毁Servlet时,Servlet容器就会调用这个方法,一般在这个方法中会写一些清除代码,例如释放servlet所占用的资源,如关闭数据库连接,关闭文件输⼊输出流等

除了生命周期方法之外,getServletInfo(),这个方法会返回Servlet的一段描述,可以返回一段字符串

getServletConfig(),这个方法会返回由Servlet容器传给init()方法的ServletConfig对象

ServletConfig接口

当Servlet容器初始化Servlet时,Servlet容器会给Servlet的init( )方式传入一个ServletConfig对象,提供了以下接口方法:

String getServletName(); // 获得servlet在web.xml中配置的name值
String getInitParameter(String name); // 获得servlet的初始化参数
Enumeration getInitParameterNames(); // 获得所有的servlet初始化参数名称

GenericServlet抽象类

GenericServlet实现了Servlet和ServletConfig接口,对servlet的各个方法提供了默认实现。

ServletRequest接口

提供了servlet的入参的统一规范,接口方法包括:

    int getContentLength();//返回请求主体的字节数
    String getContentType();//返回主体的MIME类型
    String getParameter(String var1);//返回请求参数的值

ServletResponse接口

这里需要注意的是servletResponose是由servlet容器创建的而不是servlet自己创建

在调用Servlet的service( )方法前,Servlet容器会先创建一个ServletResponse对象,并把它作为第二个参数传给service( )方法。ServletResponse隐藏了向浏览器发送响应的复杂过程

而servletResponse提供的主要是一些流输入输出的方法,比如:

PrintWriter getWriter() throws IOException;

返回了一个可以向客户端发送文本的的Java.io.PrintWriter对象,默认情况下,PrintWriter对象使用ISO-8859-1编码(该编码在输入中文时会发生乱码)

这里可以参考IO部分

http://www.chymfatfish.cn/archives/io#printwriter---%E5%AD%97%E7%AC%A6%E8%BE%93%E5%87%BA%E6%B5%81

ServletContext对象

ServletContext对象表示Servlet应用程序。每个Web应用程序都只有一个ServletContext对象在将一个应用程序同时部署到多个容器的分布式环境中,每台Java虚拟机上的Web应用都会有一个ServletContext对象

有了ServletContext对象,就可以共享从应用程序中的所有资料处访问到的信息,并且可以动态注册Web对象。前者将对象保存在ServletContext中的一个内部Map中。保存在ServletContext中的对象被称作属性

servletContext提供的接口如下:

Object getAttribute(String var1);
Enumeration<String> getAttributeNames();
void setAttribute(String var1, Object var2);
void removeAttribute(String var1);

servlet.http包中的接口及抽象类

专门用于处理http请求的servletAPI

HttpServlet抽象类

继承自GnenericServlet抽象类,HttpServlet抽象类覆盖了GenericServlet抽象类中的service()方法,并且添加了一个自己独有的service

protected void service(HttpServletRequest req, HttpServletResponse resp) {
	if (method.equals("GET")) {
		……
		this.doGet(req, resp);
……
}

可以见专门处理了HTTP请求中的GET、HEAD、POST、PUT、DELETE、OPTIONS、TRACE方法。最常用的四大方法GET、HEAD、POST、PUT、DELETE这里都有了

以doGet举例:

protected void doGet(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException
{
    String protocol = req.getProtocol();
    String msg = lStrings.getString("http.method_get_not_supported");
    if (protocol.endsWith("1.1")) {
        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
    } else {
        resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
    }
}

可以看到,HttpServlet默认实现的doGet方法竟然是返回不支持该方法的msg,即我们自行开发servlet时,需要基于HttpServlet重写HTTP方法的对应处理方法,如果不重写,默认判定为不支持

spring-MVC架构就重写了这些方法,参考FrameworkServlet

http://www.chymfatfish.cn/archives/spring-mvc#service

HttpServletRequest

httpServletRequest是表示Http环境中的Servlet请求。它扩展于javax.servlet.ServletRequest接口,并添加了几个方法:

String getContextPath();//返回请求上下文的请求URI部分
Cookie[] getCookies();//返回一个cookie对象数组
String getHeader(String var1);//返回指定HTTP标题的值
String getMethod();//返回生成这个请求HTTP的方法名称
String getQueryString();//返回请求URL中的查询字符串
HttpSession getSession();//返回与这个请求相关的会话对象

通过httpServletRequest可以获取HTTP协议传递的请求,HTTP协议可见HTTP部分

HttpServletResponse

HttpServletResponse接口,它继承自ServletResponse接口,专门用来封装HTTP响应消息。由于HTTP请求消息分为状态行,响应消息头,响应消息体三部分,因此,在HttpServletResponse接口中定义了向客户端发送响应状态码,响应消息头,响应消息体的方法

void addCookie(Cookie var1);//给这个响应添加一个cookie
void addHeader(String var1, String var2);//给这个请求添加一个响应头
void sendRedirect(String var1) throws IOException;//发送一条响应码,讲浏览器跳转到指定的位置
void setStatus(int var1);//设置响应行的状态码

servlet开发案例

重写servlet

这里基于httpServlet重写,这样就可以省去了写service方法的过程

public class MyServlet extends HttpServlet {
    public void init() {
        System.out.println("this is init method");
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) {
        handleLogic(request, response);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) {
        handleLogic(request, response);
    }

    private void handleLogic(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("handle myLogic");
        ServletContext sc = getServletContext();
        RequestDispatcher rd = null;
        rd = sc.getRequestDispatcher("/index.jsp"); //定向的⻚⾯
        try {
            rd.forward(request, response);
        } catch (ServletException | IOException e) {
            e.printStackTrace();
        }
    }
}

重写的servlet方法包括init方法,确保在初始化时做一些事情,同时将Http的doGet和doPost方法重定向到hanleLogic方法中

添加配置

<servlet>
    <servlet-name>myservlet</servlet-name>
    <servlet-class>test.servlet.MyServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>myservlet</servlet-name>
    <url-pattern>*.htm</url-pattern>
</servlet-mapping>

HTTP开发案例

HttpURLConnection类

HttpURLConnection 是 Java 标准库中用来发送 HTTP 请求和接收 HTTP 响应的类。它预先定义了一些方法,如 setRequestMethod()setRequestProperty()getResponseCode(),方便开发者自由地控制请求和响应。示例代码:

import java.net.*;
import java.io.*;
public class HttpURLConnectionExample {
    private static HttpURLConnection con;
    public static void main(String[] args) throws Exception {
        URL url = new URL("https://www.example.com");
        con = (HttpURLConnection) url.openConnection();
        con.setRequestMethod("GET");
        BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
        String inputLine;
        StringBuffer content = new StringBuffer();
        while ((inputLine = in.readLine()) != null) {
            content.append(inputLine);
        }
        in.close();
        con.disconnect();
        System.out.println(content.toString());
    }
}

HttpClient库

HttpClient 是一个 HTTP 客户端库,提供了向 HTTP 服务器发送请求和处理响应的方法。它支持多种请求协议,如 GET、POST 等,并允许开发者自由地设置请求头、请求参数、连接池等。HttpClient 还提供了基于线程池的异步请求处理方式。示例代码:

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
public class HttpClientExample {
    public static void main(String[] args) throws Exception {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpGet httpget = new HttpGet("https://www.example.com");
        CloseableHttpResponse response = httpclient.execute(httpget);
        try {
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity);
            EntityUtils.consume(entity);
            System.out.println(result);
        } finally {
            response.close();
        }
    }
}

使用 Spring 的 RestTemplate

RestTemplate是 Spring 库中用于访问 REST API 的类,它基于 HttpMessageConverter 接口,可以将 Java 对象转换为请求参数或响应内容。RestTemplate 还支持各种 HTTP 请求方法、请求头部定制、文件上传和下载等操作。

RestTemplate源码参考spring-RestTemplate部分

补链接

示例代码:

public class HttpTemplate {
    public static String httpGet(String url) {
        RestTemplate restTemplate = new RestTemplate();
        String result = restTemplate.exchange(url, HttpMethod.GET, null, String.class).getBody();
        return result;
    }
    public static String httpPost(String url, String name) {
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.postForEntity(url, name, String.class).getBody();
    }
    public static void main(String str[]) {
        System.out.println(HttpTemplate.httpGet("https://www.example.com"));
        System.out.println(HttpTemplate.httpPost("https://www.example.com", "ming"));
    }
}

在实际应用中,需要对发送失败异常进行捕获和处理

spring+servlet开发案例

spring+servlet开发案例

spring集成servlet实际上就是springMVC模式的应用,其核心是通过web.xml配置让spring通过servlet拦截所有URL来达到控制的⽬的因此在springMVC项目中,web.xml的配置是必须的

除此之外,web.xml⽂件⽤来初始化配置信息,⽐如Welcome⻚⾯、servlet、servlet-mapping、filter、listener、启动加载级别等。下面分步骤完成一套springMVC的架构代码

配置web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.5" xmlns=http://java.sun.com/xml/ns/javaee
        xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
        xsi:schemaLocation="http://java.sun. com/
        xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <display-name>Springmvc</display-name>

    <!-- 使⽤ContextLoaderListener配置时,需要告诉它Spring配置⽂件的位置 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</paramvalue>
    </context-param>

    <!-- SpringMVC的前端控制器 -->
    <!-- 当DispatcherServlet载⼊后,它将从⼀个XML⽂件中载⼊Spring的应⽤上下⽂,该XML⽂件的名字取决于<servlet-name> -->
    <!-- 这⾥DispatcherServlet将试图从⼀个叫作Springmvc-servlet.xml的⽂件中载⼊应⽤上下⽂,其默认位于WEB-INF⽬录下 -->
    <servlet>
        <servlet-name>Springmvc</servlet-name>
        <servlet-class>org.Springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Springmvc</servlet-name>
        <url-pattern>*.htm</url-pattern>
    </servlet-mapping>

    <!-- 配置上下文载⼊器 -->
    <!-- 上下文载入器载入除DispatcherServlet载⼊的配置文件之外的其他上下文配置⽂件 -->
    <!-- 最常用的上下文载⼊器是⼀个Servlet监听器,其名称为ContextLoaderListener -->
    <listener>
        <listener-class>org.Springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

</web-app>

web.xml的核心配置在于三个点:

  • <context-param>中的contextConfigLocation配置。

  • <servlet>配置:配置请求拦截器

  • <listener>配置:配置了监听器

spring的applicationContext.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.Springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:tx="http://www.Springframework.org/schema/tx"
        xsi:schemaLocation="http://www.Springframework.org/schema/beans
        http://www.Springframework.org/schema/beans/Spring-beans-2.5.xsd
        http://www.Springframework.org/schema/tx
        http://www.Springframework.org/schema/tx/Spring-tx-2.5.xsd">
    <bean id="viewResolver" class="org.Springframework.web.servlet.view. Internal ResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!-- 下面就是spring-servlet相关配置,也可以基于模块化思想,单独拿出去一个xml配置 -->
    <bean id="simpleUrlMapping" class="org.Springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/userlist.htm">userController</prop>
            </props>
        </property>
    </bean>

    <!-- 这⾥的id="userController"对应的是<beanid="simpleUrlMapping">中的<prop>⾥⾯的value -->
    <bean id="userController" class="test.controller.UserController" />
</beans>

在beans标签中注册了一个InternalResourceViewResolver的bean,它的作用是会在ModelAndView返回的视图名前加上prefix指定的前缀,再在最后加上suffix指定的后缀,例如:由于XXController返回的ModelAndView中的视图名是testview,故该视图解析器将在/WEB-INF/jsp/testview.jsp处查找视图。

创建MVC中的model

public class User {
    private String username;
    private Integer age;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

MVC中的M是model,它的作用是为了承载数据,实际上就是dto

创建MVC中的controller

public class UserController extends AbstractController {
	@Override
	protected ModelAndView handleRequestInternal(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {
		List<User> userList = new ArrayList<User>();
		User userA = new User();
		User userB = new User();
		userA.setUsername("张三");
		userA.setAge(27);
		userB.setUsername("李四");
		userB.setAge(37);
		userList.add(userA);
		userList.add(userB);
		return new ModelAndView("userlist", "users", userList);
	}
}

MVC中的C是controller,也就是如何处理响应的请求,对model做什么操作。

  • 返回值:ModelAndView类型的实例,保存了视图以及视图显示的模型数据

    • 参数1:userlist是视图组件的逻辑名称,视图解析器通过查找此名称解析试图

    • 参数2:users是传递给视图的模型对象的名称

    • 参数3:userList:传给试图模型的真实对象

在web项目中,可以在controller中通过@RequestMapping注解请求路径,例如:

@RequestMapping("/hello")
public String hello(@RequestParam(name = "name", defaultValue = "unknown user") String name) {
    return "Hello " + name;
}

在web项目中默认暴露端口是application.properties中配置的

# 应用服务 WEB 访问端口
server.port=8080

如果这里再加上springboot项目内嵌的tomcat启动时,访问localhost:8080/hello?name=gty就可以返回hello gty的结果

创建MVC中的V - 视图文件

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<h2>This is SpringMVC demo page</h2>
    <c:forEach items="${users}" var="user">
        <c:out value="${user.username}"/><br/>
        <c:out value="${user.age}"/><br/>
    </c:forEach>

视图文件用于展现请求处理结果,通过对JSTL的⽀持,可以很⽅便地展现在控制器中放⼊ModelAndView中的处理结果数据。

这里的users代表上一步中创建的ModelAndView对象中的users

启动服务器验证

至此完成了springMVC的服务器搭建流程,启动服务器,输入网址http://localhost:8080/Springmvc/userlist.htm

0

评论区