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部分
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
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
评论区