经过一段时间的学习,对于Servlet有了新的不一样的见解,在这里做一下总结,将近来学习到的知识总结一下。
- **http:**协议名称
- **localhost:**访问的是互联网中的**哪一台计算机**
- **80:**从主机当中找到**对应 80 端口的程序 (这里即为 Tomcat 服务器**)
- **/xxx1:**当前项目的**上下文路径** (即在 server.xml 中配置主机时配置的 **path属性**)
- **/xxx2:**当前**请求的资源名**
- 若找不到,则返回 **404错误**
- 若找到了,则解析该`<Context />`元素,得到`docBase`属性,获取当前访问 Web 项目的跟的绝对路径:`D:\javaPros\test\webapp` 从
- 若找不到,则返回 **404错误**
- 若找到了,则继续**获取该资源对应 Servlet 类的全限名称:** xxx.xxx判断
Map<String,Servlet> cache = ......(Tomcat提供的);
key:存Servlet类的全限定名称
value:该Servlet类的对象.
Servlet obj = cache.get("xxx.xxx");
if(obj==null){
//Servlet实例缓存中没有该类的对象,第一次.
GOTO 6:
}else{
//有对象,非第一次.
GOTO 8:
}
}
obj = Class.forName("xxx.xxx").newInstance();
把当前创建的 Servlet 对象,存放在缓存之中,供给下一次的使用.
cache.put("xxx.xxx",obj);
obj.init(config);
obj.service(req,resp);
在 Web 容器中,Servlet 主要经历 4 个阶段,如下图:
Servlet 生命周期
这一部分参考文章:这里是链接
前面的文章里面提到过,广义上,Servlet 即实现了 Servlet 接口 的类,当我们创建一个自定义类,实现 Servlet 接口 的时候,会发现有 5 个方法需要重写,有init【初始化】,destroy【销毁】,service【服务】,ServletConfig【Servlet配置】,getServletInfo【Serlvet信息】。
这样做的话,我们每次都需要实现 5 个方法,太麻烦了!
我们可以直接继承 HttpServlet 类,该类已经默认实现了 Servlet 接口中的所有方法,在编写 Servlet 的时候,你只需要重写你需要的方法就好了,并且该类还在原有 Servlet 接口上添加了一些与 HTTP 协议处理相关的方法,比 Servlet 接口的功能更强大。
this.doPost(req, resp);
(因为无论是get或post请求提交的数据,处理方式都基本相同,下同)
③ 重写 doGet() 和 doPost() 方法,并在 doPost() 中添加一句this.doGet()(req, resp);
浏览器多次对Servlet的请求,一般情况下,服务器只创建一个Servlet对象,也就是说,Servlet对象一旦创建了,就会驻留在内存中,为后续的请求做服务,直到服务器关闭。
对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service方法再根据请求方式分别调用doXXX方法。
当多个用户访问Servlet的时候,服务器会为每个用户创建一个线程。当多个用户并发访问Servlet共享资源的时候就会出现线程安全问题。
原则:
这一部分参考文章:这里是链接
对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,即 request 和 response 对象。
既然 request 对象代表 http 请求,那么我们获取浏览器提交过来的数据,就找 request 对象 即可。response 对象代表 http 响应,那么我们向浏览器输出数据,找 response 对象即可。
resp.setContentType("text/html;charset=utf-8");
要知道,GET 和 POST 都是请求方式
http://localhost/test.html
?name=wmyskxz&sex=male
这里提交了两个参数,一个是name
属性值为wmyskxz
,另一个是sex
属性值为male
,这是一种直接的请求方式,在请求资源后面跟上 ? 符号与参数连接,其他的参数使用 & 符号连接。http://localhost/test.html#
但并不是所有的数据都需要使用 POST 请求来完成,事实上,GET 请求方式会比 POST 请求更快,当数据小并且安全性要求不是那么高的时候,GET 仍然是很好的选择.(并且 GET 相较 POST 简单)
在 Tomcat 服务器中,接受请求的时候,默认的编码方式为 ISO-8859-1,而该编码方式只占一个字节,不支持中文(两个字节),所以当我们做请求的时候,会出现乱码的问题
byte[] data = name.getBytes("ISO-8859-1");
2.对byte数组重新进行 UTF-8 编码:
name = new String(data,"UTF-8");
但是这样会出现一个问题,那就是当表单数据太多的时候,这样反复解码-编码,会很繁琐。request.setCharacterEncoding("UTF-8");
注意:必须在获取第一个参数之前设置,并且该方式只对 POST 方式有效。
2.对于 GET 请求:
重新设置 Tomcat 的编码方式,修改 Tomcat 的配置文件:
Tomcat根目录/conf/server.xml(修改端口的那一行)
<url-pattern>
,可以使用多个资源名称找到当前的 Servlet*
__表示任意字符
/*
__:可以使用任意的字符*访问当前的 Servlet
*.xxx
:如 wmyskxz.wudi<servlet-name>
不能够为 default ,使用它会造成项目下面的静态资源找不到,在 Tomcat/conf/web.xml
文件中配置一个名字为default的Servlet,该Servlet在负责访问项目下的静态资源
web.xml 中配置的默认项
这是 Servlet 3.0 提出的新特性,支持注解配置,这大大简化了我们的工作。
在之前的开发工作中,我们总是去 web.xml
文件中进行配置,至少会出现8行:
web.xml 中配置 Servlet
而当一个项目中存在很多 Servlet ,那么配置文件就会变得非常臃肿,不便于后期的维护,在 Servlet 3.0 推出之后,我们可以使用注解来配置 Servlet,上面 8 行的配置可以简化为下面的简单的注解:
或者也可以使用属性 value
定义访问的 URL,只有 URL 这个属性是必要的,name
是可以缺省的值,而默认的 value
也可以省略不写,所以可以简写成:
@WebServlet("/foreServlet")
又叫做直接转发方式,客户端和浏览器只发出一次请求,Servlet、HTML、JSP或其它信息资源,由第二个信息资源响应该请求,在请求对象request中,保存的对象对于每个信息资源是共享的。
比如:从 AServlet 请求转发到 BServlet
request.getRequestDispatcher(path).forward(request, response);
参数:path
,要跳转到的资源路径:上下文路径 / 资源路径
request.setAttribute(String var1,Object var2)
设置要共享的数据资源,并通过request.getAttribute(String var1);
来获取传递的资源
4.【可以】访问 WEB-INF 中的资源
WEB-INF 文件夹是 Java Web 应用的默认安全目录,即客户端无法直接访问,只有服务端可以访问的目录。
如果想在页面中直接访问其中的文件,必须通过web.xml文件对要访问的文件进行相应映射才能访问。
注意:在实际的开发中,可以把不希望用户直接访问到(通过浏览器输入地址栏)的网页放在文件夹中通过此方式访问。
5.请求转发【不能】跨域访问
所谓的同域,是指域名,协议,端口均相同 又叫做间接转发方式(Redirect)实际是两次HTTP请求,服务器端在响应第一次请求的时候,让浏览器再向另外一个URL发出请求,从而达到转发的目的。
比如:从AServlet重定向到BServlet
response.sendRedirect(String location);
参数:location
,转发到的资源路径
MVC 是一种分层的设计模式 。
这部分可以参考一下这里