springWeb——Servlet
6.1、Servlet简介
servlet是sun公司开发动态web的一门技术
sum在这些API中提供了一个接口叫做:Servlet.开发的两个步骤:
- 编写一个类,实现Servlet接口
- 把开发好的Java类部署到web服务器中
把实现了Servlet接口的Java程序叫做Servlet
6.2、Hello Servlet
构建普通的Maven工程,删除src目录
建立子工程
这个子工程选取Maven模板中的webapp
父工程:
<modules>
<module>demo-01</module>
</modules>
子工程:
<parent>
<artifactId>JavaWebLearning</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
父工程与子工程间依赖的关系类似于java的继承关系
Maven环境优化:
修改web.xml
注:web.xml中的内容可以参考对应的Tomcat中的样例并与之相匹配
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app>
<display-name>Archetype Created Web Application</display-name>
</web-app>
将maven的结构搭建完整:添加java和resources目录(注意Mark As)
编写一个Servlet程序
编写一个普通类并继承Http
package com.guan.servlet; import javax.servlet.http.HttpServlet; public class TestServlet extends HttpServlet {
}
注:这里遇到找不到HttpServlet的问题需要导入相关的依赖,可以
Alt+Enter,选择Add Maven dependency,将javax.servlet.http依赖导入(前提本地的Maven仓库里有,否则需要到Maven的中央仓库下载.补充一下查找应该下载什么的思路:我们已经安装了Tomcat,而Tomcat是java开发的,既然javaweb能在里面跑肯定是由对应的jar,因此我们直接点开Tomcat的文件夹看看即可)实现Servlet接口
ctrl+o选择override两个方法:doGet+doPost注:通常两个方法的基本逻辑是一样,所以我们可以选择直接在doPost方法中调用doGet方法
public class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//响应的类型:html
resp.setContentType("text/html");
//获取响应的输出流
PrintWriter writer = resp.getWriter();
writer.println("<html>");
writer.println("<head>");
writer.println("<title>Hello World!</title>");
writer.println("</head>");
writer.println("<body>");
writer.println("<h1>12哈哈</h1>");
writer.println("</body>");
writer.println("</html>");
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
在web.xml中注册servlet的实现类,编写Servlet的映射
为什么要用映射:我们写的Java程序要通过浏览器访问,而浏览器要通过web服务器访问,所以我们要在web服务器中注册我们写的Servlet,还需要给它一个浏览器能访问的路径
<!-- 注册-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.guan.servlet.TestServlet</servlet-class>
</servlet> <!-- 映射-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
此时你会发现程序还无法run(相关的标记是灰色的),配置Tomcat:,直接在模板中选择,有的话直接可以选择,没有的话创建一个,详见之前的博文,注意两点:
- 点击
+才是往里面添加东西 - 需要fix一下deployment
- 点击
测试
在浏览器中查看相应的链接,发现
/hello下的内容有乱码无法正常显示:12??,这是因为Java中默认的字符集是ISO8859-1,我们需要将其改为utf-8public class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//响应的类型:html
resp.setContentType("text/html");
//将输出的编码格式改为utf-8
resp.setCharacterEncoding("utf-8");
//获取响应的输出流
PrintWriter writer = resp.getWriter();
writer.println("<html>");
writer.println("<head>");
writer.println("<title>Hello World!</title>");
writer.println("</head>");
writer.println("<body>");
writer.println("<h1>12哈哈</h1>");
writer.println("</body>");
writer.println("</html>");
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
6.3、分析servlet源码:主要查看post/get方法的运作
结构:
点开HttpServlet:
public abstract class HttpServlet extends GenericServlet我们可以看到它继承了GenericServlet这个类
继续点开GenericServlet:
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable我们可以看到这是一个抽象类,继承了三个接口,其中servletConfig显然是用于配置的,Seralizable是用于实体序列化的接口,所以我们重点看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();
}
好家伙,终于到底了!分析一下几个方法:
- init:显然是用于初始化的
- ServletConfig:显然是用于配置的
- servic:没错和post/get应该就是这个,我们后面回溯主要就看这个方法
- getServletInfo:显然是用于获得Servlet信息的
- destory:显然是用于销毁的
回溯:
查看GenericServlet抽象类:
public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;service方法没有被实现
查看HttpServlet类:
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
long lastModified;
if (method.equals("GET")) {
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
this.doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader("If-Modified-Since");
} catch (IllegalArgumentException var9) {
ifModifiedSince = -1L;
} if (ifModifiedSince < lastModified / 1000L * 1000L) {
this.maybeSetLastModified(resp, lastModified);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("HEAD")) {
lastModified = this.getLastModified(req);
this.maybeSetLastModified(resp, lastModified);
this.doHead(req, resp);
} else if (method.equals("POST")) {
this.doPost(req, resp);
} else if (method.equals("PUT")) {
this.doPut(req, resp);
} else if (method.equals("DELETE")) {
this.doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
this.doOptions(req, resp);
} else if (method.equals("TRACE")) {
this.doTrace(req, resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{method};
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
} }
可以看到正是这个方法完成了Post/Get等方法的实际处理
总结:
HttpServlet继承了GenericServlet抽象类,而GenericServlet又是继承了Servlet接口
HttpServlet中的Post/Get方法实际是对Servlet接口的Service方法的扩充
6.3 Servlet原理
Servlet是由服务器调用,web服务器在收到浏览器请求之后,会:
- 浏览器直接访问的对象是web容器(Tomcat),浏览器发起请求,web容器响应
- 相关的Servlet的class文件只会生成一次,后面会直接调用(所以初始化较慢
- web容器会产生两个对象:请求(Request)和响应(Response)
- 这两个对象会调用2中生成的Servlet对象的doPost/doGet方法,当然本质上是service方法
- Request会从service(请求)拿到请求并且把请求之后的响应交给Response
- 我们重写了doGet/doPost方法,web容器通过调用service方法间接地调用doGet/doPost方法

6.4、Mapping
一个Servlet可以指定一个映射路径
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
一个Servlet可以指定多个映射路径
<!-- 映射-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping> <servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello1</url-pattern>
</servlet-mapping>
一个Servlet可以指定通用映射路径
<!-- 映射-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello/*</url-pattern>
</servlet-mapping>
默认请求路径
<!-- 映射-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/*</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>/hello/*.hello</url-pattern>
</servlet-mapping> <!-- 可以使用-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>*.hello</url-pattern>
</servlet-mapping>
6.5、拦截器
优先级的区别:一对一的最高,通配的其次
写好相应的Error类
public class Test extends HttpServlet { @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
PrintWriter writer = resp.getWriter();
writer.write("<h1>404</h1>");
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
在web.xml中注册
<servlet>
<servlet-name>error</servlet-name>
<servlet-class>com.guan.servlet.Test</servlet-class>
</servlet>
映射
<servlet-mapping>
<servlet-name>error</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
6.6、ServletContext
架构:
获得:this.getServletContext():获得Servlet上下文
web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用:
数据共享
注:这里我们最好用一个全新的module进行演示.但是deployment有需要注意设置的地方:每一个module的deployment应该是独立的,否则如果一个deployment中有多个module,很可能会造成打包的时候把其它module也打包了.显然项目一多,打包就会显得很慢
我们在这个Servlet中保存的数据,可以在另一个Servlet中拿到
public class setContext extends HttpServlet { @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
ServletContext context = req.getServletContext();
String username = (String) context.getAttribute("username");
System.out.println(username);
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
public class getContext extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//响应的类型:html
resp.setContentType("text/html");
//将输出的编码格式改为utf-8
resp.setCharacterEncoding("utf-8");
//获得上下文
ServletContext context = req.getServletContext();
context.setAttribute("username","guan");
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
<servlet>
<servlet-name>set</servlet-name>
<servlet-class>com.guan.servlet.getContext</servlet-class>
</servlet> <servlet>
<servlet-name>get</servlet-name>
<servlet-class>com.guan.servlet.setContext</servlet-class>
</servlet> <!-- 映射--> <servlet-mapping>
<servlet-name>set</servlet-name>
<url-pattern>/set</url-pattern>
</servlet-mapping> <servlet-mapping>
<servlet-name>get</servlet-name>
<url-pattern>/get</url-pattern>
</servlet-mapping>
springWeb——Servlet的更多相关文章
- java jar包收集
activation~与javaMail有关的jar包,使用javaMail时应与mail.jar (mail.jar和activation.jar)一起加入到lib中去,具体负责mail的数据源和类 ...
- 常见 jar包详解
常见 jar包详解 jar包 用途 axis.jar SOAP引擎包 commons-discovery-0.2.jar 用来发现.查找和实现可插入式接口,提供一些一般类实例化.单件的生命周期 ...
- eclipse 用maven创建web项目
Eclipse 用maven构建web项目 (2013-01-27 11:05:31) 转载▼ 标签: it eclipse maven spring web 杂谈 一.背景介绍 对于初学者,用m ...
- Webflux快速入门
SpringWebflux是SpringFramework5.0添加的新功能,WebFlux本身追随当下最火的Reactive Programming而诞生的框架,那么本篇就来简述一下这个框架到底是做 ...
- Eclipse maven构建springmvc项目
原文地址: http://www.cnblogs.com/fangjins/archive/2012/05/06/2485459.html 一.背景介绍 对于初学者,用maven构建项目并不是一件容易 ...
- Spring学习(二)——使用Gradle构建一个简单的Spring MVC Web应用程序
1.新建一个Gradle工程(Project) 在新建工程窗口的左侧中选择 [Gradle],右侧保持默认选择,点击next,模块命名为VelocityDemo. 2.在该工程下新建一个 module ...
- Java常用开源jar包
转:http://blog.csdn.net/kevingao/article/details/8125683 activation~与javaMail有关的jar包,使用javaMail时应与mai ...
- 【Web】Spring WebFlux
阅读目录 一.关于WebFlux 二.SpringMVC与SpringWebFlux 三.Reactive Spring Web 四.实现WebFlux示例 SpringWebflux是SpringF ...
- Spring-web中的web.xml为Servlet提供的配置选项说明
配置Servlet时可以设置的一些初始化参数,总结如下: ContextAttribute: 在ServletContext的属性中,要用作WebApplicationContext的属性名称. Co ...
随机推荐
- 数值分析:最小二乘与岭回归(Pytorch实现)
Chapter 4 1. 最小二乘和正规方程 1.1 最小二乘的两种视角 从数值计算视角看最小二乘法 我们在学习数值线性代数时,学习了当方程的解存在时,如何找到\(\textbf{A}\bm{x}=\ ...
- node Cheerio 获取script脚本里的数据
const cheerio = require('cheerio'); const $ = cheerio.load(html); // your html//如果有多少script脚本标签使用循环来 ...
- Kubernetes家族容器小管家Pod在线答疑?
Kubernetes家族容器小管家Pod在线答疑 不知道学习k8s的小伙伴们有没有跟我一样的疑问? k8s为什么不是直接运行容器,而是让Pod介入? Pod又是什么?为什么在应用容器化如此普遍的情况下 ...
- 帆软报表(finereport)禁用右键
点击模板>模板web属性>(填报,数据分析,分页预览设置),选择为该模板单独设置,在下面的事件设置里面添加一个加载结束事件,完整js代码如下: 这段代码的基本原理是让用户的页面右键点击事件 ...
- Solution -「CF 1349D」Slime and Biscuits
\(\mathcal{Description}\) Link. 有 \(n\) 堆饼干,一开始第 \(i\) 堆有 \(a_i\) 块.每次操作从所有饼干中随机一块,将其随机丢到另外一堆.求所 ...
- 排查log4j不输出日志到文件的问题
问题描述 项目使用Spring Boot框架,在pom文件中添加了如下配置: <dependency> <groupId>org.slf4j</groupId> & ...
- php异步:在php中使用fsockopen curl实现类似异步处理的功能方法
PHP从主流来看,是一门面向过程的语言,它的最大缺点就是无法实现多线程管理,其程序的执行都是从头到尾,按照逻辑一路执行下来,不可能出现分支,这一点是限制php在主流程序语言中往更高级的语言发展的原因之 ...
- transient关键字有何作用
使用对象流保存对象时,将对象的全部信息都保存了,但是有些信息是不希望保存,如密码,该如何避免该信息的保存? 使用transient关键字修饰的属性,在保存对象时,该属性并不会被保存. transien ...
- 【C# .Net GC】GC的类型与工作方式 和配置
.net主要有两种类型垃圾回收器,也可也说是垃圾回收器的两种工作模式. GC的类型主要有两种: 工作模式是针对进程的,程序启动后就不能修改了.只能在配置文件.json .xml进行设置.但是可用通过G ...
- js数组 把竖向数组排列为横向数组
项目中会遇到为了渲染方便要把后台给的竖向数组排列为横向数组 例:后台传回的数组为[2004, 2005, 2006, 2007, 2008] [46890000, 55900500, 33786400 ...