JAVAWEB - Servlet原理及其使用>从零开始学JAVA系列
2021/5/24 20:55:01
本文主要是介绍JAVAWEB - Servlet原理及其使用>从零开始学JAVA系列,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
目录- Servlet原理及其使用
- 什么是Servlet
- Servlet的使用
- 编写一个Servlet,使用继承HttpServlet的方式
- 配置web.xml
- 很简单的几个JSP文件
- 小提示,如果继承HttpServlet发现找不到类的时候,引入一个jar包添加到类路径(必须放在WEB-INF目录下)
- Servlet读取配置(自身Servlet配置、全局配置)
- 获得Servlet自己的配置信息
- 获得全局配置信息
- 解决HTTP请求当中的乱码问题(get、post、response)
- response响应乱码
- post请求时接收参数乱码
- get请求时,接收浏览器的url中的参数时乱码
- Servlet的注解支持(代替xml配置servlet方式)
- Servlet的原理
- Servlet的响应原理
- Servlet的生命周期
- Servlet的加载时机
- Servlet的API关系
- 为什么继承了HTTPServlet不重写Service访问时会出现405报错?
- HTTPServlet为什么要这么处理?
- 为什么service()方法是处理请求的,但是重写doGet、doPost()等方法也有效?
- 为什么继承了HTTPServlet不重写Service访问时会出现405报错?
- Servlet运行的Web项目中的4种路径问题
- 1、绝对路径(访问任何资源)
- 2、根路径(访问当前服务器的任何资源)
- 3、相对路径(访问当前服务器的资源)、不推荐
- 4、相对路径(基于base标签,访问当前项目,其实实质还是绝对路径或根路径)
- 使用idea配置模板
- 不同路径的使用场景
- 转发与重定向的原理及区别
- 原理不同
- 语法实现方式不同
- 获取request作用域数据问题
- 跳转页面后,网址的显示不同
- 书写代码时,使用“ / ”的意义不同
- 支持书写的路径不同
- 使用表单时重复提交问题
- 效率问题
- 是否经过配置的过滤器
- 小提示,如何在项目中访问到Servlet
Servlet原理及其使用
什么是Servlet
是JAVA的基于WEB服务器的完成动态网页开发的一种技术
Servlet的使用
编写一个Servlet,使用继承HttpServlet的方式
package com.it.servlet; import javax.servlet.ServletException; import javax.servlet.http.*; import java.io.IOException; public class MyFirstServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 获取表单提交的参数,填写的参数是表单对应数据的name属性 String username = req.getParameter("username"); String password = req.getParameter("password"); if(username.equals("dqx") && password.equals("123")) { // 转发到/success.jsp req.getRequestDispatcher("/success.jsp").forward(req,resp); }else { // 在request作用域中存入一个 key value req.setAttribute("msg", "用户名或密码错误"); req.getRequestDispatcher("/login.jsp").forward(req, resp); } } }
配置web.xml
<servlet> <servlet-name>loginServlet</servlet-name> <servlet-class>com.it.servlet.MyFirstServlet</servlet-class> <!-- 配置在服务器启动时加载Servlet --> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>loginServlet</servlet-name> <!-- 处理的请求 --> <url-pattern>/doLogin</url-pattern> </servlet-mapping>
很简单的几个JSP文件
- login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <!DOCTYPE html> <html lang="zh-CN"> <head> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <base href="<%=basePath%>"> </head> <body> <form action="doLogin" method="post"> <% String msg = (String) request.getAttribute("msg"); System.out.println("---------"); if(msg != null) { out.print(msg); } %> <hr> 用户名:<input type="text" name="username"> <br> 密码:<input type="password" name="password"> <br> <input type="submit" value="登录"> </form> </body> </html>
- success.jsp
<h1>登录成功</h1>
小提示,如果继承HttpServlet发现找不到类的时候,引入一个jar包添加到类路径(必须放在WEB-INF目录下)
——————————————————————————————————
Servlet读取配置(自身Servlet配置、全局配置)
为什么需要读取配置?
答:因为有些配置是固定的(例如编码),许多地方都要使用到,而如果硬编码的话,一旦编码改变,则需要更改多处,影响维护。
获得Servlet自己的配置信息
- 在web.xml中配置参数
<servlet> <servlet-name>myConfigServlet</servlet-name> <servlet-class>com.it.servlet.MyConfigServlet</servlet-class> <!-- 配置Servlet配置参数 --> <init-param> <param-name>charset</param-name> <param-value>UTF-8</param-value> </init-param> </servlet>
- 在Servlet中获取配置信息(可以在构造函数、init()方法、等等地方都能获取到)
public class MyConfigServlet extends HttpServlet { private String charset; @Override public void init() throws ServletException { // 获得Servlet参数,这两种方式是一样的 charset = this.getInitParameter("charset"); charset = this.getServletConfig().getInitParameter("charset"); }
获得全局配置信息
- 在web.xml中配置全局参数
<context-param> <param-name>globalCharset</param-name> <param-value>GBK</param-value> </context-param>
- 在Servlet中获取
public class MyConfigServlet extends HttpServlet { private String globalCharset; @Override public void init() throws ServletException { // 获得全局配置参数 globalCharset = this.getServletContext().getInitParameter("globalCharset"); System.out.println(globalCharset); }
解决HTTP请求当中的乱码问题(get、post、response)
response响应乱码
- response响应乱码出现的原因?
答:由于浏览器不知道服务器响应的内容是什么编码的,浏览器默认使用GBK编码,而如果服务器响应的数据是不是GBK编码的时候,浏览器就会乱码 - 解决方法
答:在响应中告知浏览器以什么编码来解析数据
// 注意,这里是因为演示,所以硬编码了,实际编码应该从配置中读取 // 这句话就是告知浏览器接收到响应数据时以何种类型处理,以何种编码解析 resp.setContentType("text/html;charset=UTF-8");
post请求时接收参数乱码
- post请求出现乱码的原因
答:浏览器进行post请求时(表单提交),浏览器的页面编码与服务器接收处理参数的编码不一致时,就会出现乱码。 - 解决方法,设置request处理请求参数的编码
request.setCharacterEncoding("UTF-8");
get请求时,接收浏览器的url中的参数时乱码
- get请求出现乱码的原因
答:浏览器进行get请求(参数是在URI上)时,浏览器的页面编码(例如浏览器该页面是UTF-8编码)与服务器接收处理URI参数的编码(tomcat默认是IOS-8895-1)不一致时,就会出现乱码。 - 解决方案有2种
- 通过修改tomcat服务器中的conf目录中的server.xml文件,添加URIEncoding配置
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="utf-8" />
- 在接受参数后,将数据转换为与页面提交的数据一致的编码
byte[] bytes = username.getBytes("ISO-8859-1"); String newUsername = new String(bytes,"UTF-8");
Servlet的注解支持(代替xml配置servlet方式)
可以在Servlet类上使用注解的方式代替在web.xml中的配置
import javax.servlet.annotation.WebInitParam; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; @WebServlet(loadOnStartup = 0, initParams = {@WebInitParam(name = "charset",value = "UTF-8"),@WebInitParam(name = "key2",value = "value2")}, urlPatterns = "/AnnoServlet") public class AnnoServlet extends HttpServlet { }
Servlet的原理
Servlet的响应原理
- 浏览器发送请求到服务器
- 服务器通过web.xml中配置的servlet-mapping找到对应的映射
- 通过匹配到映射找到对应的servlet,通过反射创建其对象
- 调用该对象中的service方法处理请求
- 处理请求后使用将响应结果传输给浏览器
Servlet的生命周期
- 类加载(Servlet加载)
- 实例化(利用反射创建对象,单例)
- init初始化
- service 处理请求
- destroy 销毁
Servlet的加载时机
- 在Servlet第一次处理请求时加载(默认)
- 在服务器启动时就进行加载,在web.xml中对应的servlet标签中添加load-on-startup标签(一般值为0-10),优先级从大到小
Servlet的API关系
- javax.servlet.Servlet接口
- javax.servlet.GenericServlet 抽象类,实现了Servlet接口
- javax.servlet.http.HttpServlet 普通类,继承了GenericServlet抽象类
所以,想要编写一个Servlet必须要实现或者间接实现Servlet接口,一般使用最多的就是继承HttpServlet - 常用方法
// Servlet接口中的方法 void service(ServletRequest var1, ServletResponse var2);//核心方法,用于处理浏览器发送的请求 ServletConfig getServletConfig(); //用于获取Servlet的配置信息
为什么继承了HTTPServlet不重写Service访问时会出现405报错?
答:因为继承了HTTPServlet方法没有重写service()方法或doGet()、doPost()方法
HTTPServlet为什么要这么处理?
答:因为本身我们开发者编写一个Servlet类就是为了处理请求,而既没有service()方法处理请求,也没有doGet()、doPost(),那这个Servlet存在的意义就缺失了。所以HttpServlet处理时就直接报错,是为了告知调用者重写service()或者doGet()、doPost()等方法
为什么service()方法是处理请求的,但是重写doGet、doPost()等方法也有效?
- HttpServlet中通过获得请求的方式(get、post)后,还是会调用doGet、doPost等方法
- 如果继承了HttpServlet的类重写了doGet方法,那么最后HttpServlet中的service方法在执行时判断了请求的方式是get请求后,会执行子类重写的doGet方法(多态)。
Servlet运行的Web项目中的4种路径问题
1、绝对路径(访问任何资源)
// 格式: 协议://IP地址:端口号/资源路径 <a href="http://127.0.0.1:8080/myProject1/path1/update.jsp">同一个项目下同一个文件夹中的文件update.jsp</a> <br/> <a href="http://127.0.0.1:8080/myProject1/path1/subpath/delete.jsp">同一个项目下同子文件夹中的文件delete.jsp</a> <br/> <a href="http://127.0.0.1:8080/myProject1/path2/add.jsp">同一个项目下同级文件夹中的文件add.jsp</a> <br/> <a href="http://127.0.0.1:8080/myProject1/index.jsp">同一个项目下父级文件夹中的文件index.jsp</a> <br/> <a href="http://127.0.0.1:8080/myProject1/servlet/DoLogin2">访问servlet的路径</a> <br/> <a href="http://127.0.0.1:8080/myProject1/index.jsp">同一个服务器中不同项目中的文件servlet01/index.jsp</a> <br/> <a href="http://192.168.121.33:8080/demo/a.jsp">同一个局域网中不同服务器中的项目</a> <br/> <a href="http://www.baidu.com">外网服务器的项目</a> <br/>
2、根路径(访问当前服务器的任何资源)
提示:只能访问当前服务器的任何资源
<a href="/webdemo01/path1/update.jsp">同一个项目下同一个文件夹中的文件update.jsp</a> <br/> <a href="/webdemo01/path1/subpath/delete.jsp">同一个项目下同子文件夹中的文件delete.jsp</a> <br/> <a href="/webdemo01/path2/add.jsp">同一个项目下同级文件夹中的文件add.jsp</a> <br/> <a href="/webdemo01/index.jsp">同一个项目下父级文件夹中的文件index.jsp</a> <br/> <a href="/webdemo01/servlet/DoLogin2">访问servlet的路径</a> <br/> <a href="/webdemo01/index.jsp">同一个服务器中不同项目中的文件servlet01/index.jsp</a> <br/> <%--不行--%> <a href="/demo/a.jsp">同一个局域网中不同服务器中的项目</a> <br/>
3、相对路径(访问当前服务器的资源)、不推荐
<a href="update.jsp">同一个项目下同一个文件夹中的文件update.jsp</a> <br/> <a href="subpath/delete.jsp">同一个项目下同子文件夹中的文件delete.jsp</a> <br/> <a href="../path2/add.jsp">同一个项目下同级文件夹中的文件add.jsp</a> <br/> <a href="../index.jsp">同一个项目下父级文件夹中的文件index.jsp</a> <br/> <a href="../servlet/DoLogin2">访问servlet的路径</a> <br/> <a href="../../myProject2/index.jsp">同一个服务器中不同项目中的文件
4、相对路径(基于base标签,访问当前项目,其实实质还是绝对路径或根路径)
<head> <% // 这是绝对路径的base标签 String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; // 根路径的base标签 String genBasePath = request.getContextPath() + "/"; %> <base href="<%=genBasePath%>"> </head> <body> <%-- 注意,这里不要在写一个/了,不然就变成根路径与base标签无关了了 --%> <a href="index.jsp">访问index.jsp</a> </body>
使用idea配置模板
不同路径的使用场景
- 路径适用于jsp页面中的 a、form、src、link等等
- 访问其他服务器时:绝对路径
- 访问自己服务器其他项目时: 根路径
- 访问当前项目:base路径
转发与重定向的原理及区别
原理不同
-
转发,指的是在服务器跳转
服务器在内部接收到第一个请求时,转发到其他servlet或页面处理,然后返回数据给用户。
这个过程用户是不可见的,所以转发时,浏览器只会向服务器发出一个请求 -
重定向,客户端跳转
服务器在运行到重定向的语句时,将重定向请求发回给浏览器,其状态码为302(并携带者需要重定向的资源路径)
浏览器在接收到这个302的重定向响应后,用其中的资源路径地址再次向服务器发送一个请求。
所以这个过程中涉及到了2个请求。所以重定向是用户可见的。
语法实现方式不同
// 转发(这里使用的是相对路径) req.getRequestDispatcher("index.jsp").forward(req, resp); // 重定向(这里使用的是相对路径) resp.sendRedirect("index.jsp");
获取request作用域数据问题
转发能够获取request作用域中的数据,因为其转发的原理就是至始至终都只有一个请求,而request作用域的范围就是一个请求当中,所以能够获取
重定向不能获取request中的数据,因为重定向时,涉及到了2个请求,所以第二个请求已经不在第一个请求的作用范围内了,所以无法获取。
跳转页面后,网址的显示不同
转发跳转后,由于是服务器内部跳转,浏览器无法察觉,所以还是显示的浏览器访问的资源路径。
重定向跳转后,由于是客户端跳转,跳转对浏览器是可见的,所以显示的路径是重定向的路径。
书写代码时,使用“ / ”的意义不同
转发时候的字符串时候由于路径最前面会加上/项目名,所以写 / 代表着当前项目,这也意味着。转发只能转发到当前的项目资源。
支持书写的路径不同
绝对路径
转发:不支持
重定向:支持
相对路径(不推荐)
转发:支持
重定向:支持
根路径
转发:支持(当前项目)
重定向:支持(代表当前服务器,与在jsp中使用根路径是一样的)
使用表单时重复提交问题
效率问题
是否经过配置的过滤器
小提示,如何在项目中访问到Servlet
其实每编写一个Servlet并使用web.xml配置好、或者使用注解的方式配置了一个Servlet时。
就相当于在Web根路径下放入了这个Servlet。
这篇关于JAVAWEB - Servlet原理及其使用>从零开始学JAVA系列的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-07-04TiDB 资源管控的对撞测试以及最佳实践架构
- 2024-07-03万字长文聊聊Web3的组成架构
- 2024-07-02springboot项目无法注册到nacos-icode9专业技术文章分享
- 2024-06-26结对编程到底难不难?答案在这里
- 2024-06-19《2023版Java工程师》课程升级公告
- 2024-06-15matplotlib作图不显示3D图,怎么办?
- 2024-06-1503-Loki 日志监控
- 2024-06-1504-让LLM理解知识 -Prompt
- 2024-06-05做软件测试需要懂代码吗?
- 2024-06-0514-ShardingSphere的分布式主键实现