servlet的引入和介绍
1.什么是Servlet?
Servlet其实就是服务器能够识别的java类,我们将业务逻辑处理规则放入Servlet中,然后将Servlet放入服务器中,服务器根据请求调用调用相应的Servlet进行处理,Servlet可以成为后台处理程序的入口。
2.为什么需要Servlet?
服务器在接收到浏览器的请求后,会自动调用对应的逻辑代码进行请求处理。但是逻辑代码是由程序员编写并放到服务器中,那么服务器怎么知道该怎么调用并调用哪个类和哪个方法来进行请求处理。
解决: 程序员在编写代码的时候如果能够按照服务器能够识别的规则进行编写,浏览器按照指定的规则进行发送请求,那么服务器就可以调用并执行响应的逻辑代码进行请求处理了。
需要Servlet 技术来实现:
Servlet就是服务器能够识别的类并通过调用里面的service方法进行请求处理。
3.Servlet特点:
1)运行在支持 java的应用服务器上
2)Servlet 的实现遵循了服务器能够识别的规则,也就是服务器会自动的根据请求调用对应的 servlet 进行请求处理。
3)简单方便,可移植性强
4.Servlet的使用:
1、 创建普通的 java 类并继承HttpServlet
2、 覆写 service方法
3、 在service方法中书写逻辑代码即可
4、 在webRoot 下的 WEB-INF 文件夹下的 web.xml文件中配置 servlet
代码示例:
5.打开 tomcat 的安装目录,在 webapps 目录下新建文件夹,文件夹名为 project,并将项目源码webRoot下的内容全部复制到该文件夹下。
6.启动tomcat服务器,并在地址栏中输入:localhost:8080/project/my
结果:
流程分析图:
5.请求urlf分析:localhost:8080/project/my
localhost:8080:根据ip和端口号可以找到对应服务器,同时服务器服务器会去webapps下查找处理此次请求的代码.
project/my:project/s:uri数据,服务器根据uri找到对应的Servlet,去Web.xml中去匹配。
总结:
MyEclipse是开发工具,通过此工具便于程序员的代码编写。真正运行的代码不是 MyEclipse 中编写的代码, 而是tomcat 服务器中部署好的代码。Tomcat 会根据请求自动调用对应的代码进行请求处理。
3.Myeclipse 集成 Tomcat:
1.为什么myeclipse要集成Tomcat
每次在Myeclipse 中更改了代码后,都需要重新复制代码到服务器中,太过麻烦。
2.集成Tomcat的步骤:
第一步: 选中window---->preferences
第二步:
第三步:
第四步:
注意:
部署好的项目,每次在Myeclipse中进行更改后只要点击ctrl+s进行保存并重新启动服务器,Myeclipse 会自动重新复制文件到服务器,并覆盖原有在服务器中的文件。
发布项目:
在 Myeclipse 的 servers 窗口中选择集成的 tomcat 然后点击启动按钮启动即可:
更改项目部署名:
选择要部署的项目然后右键,选择 properties。然后按图修改部署名即可。
4.Servlet 的 web.xml 配置:
配置方式一:精确配置
<url-pattern>/别名</url-pattern>
注意:
"/"是必须声明的,别名不可以为中文
此种配置方式可以配置多个
配置方式二:模糊配置
<url-pattern>*.后缀名</url-pattern>
注意:
*表示任意个数的任意字符
所有以指定的后缀名结尾的请求都会调用该servlet进行处理
作用:
进行模块化开发的划分等
配置方式三:拦截所有请求
<url-pattern>/*</url-pattern>
注意:
会拦截所有类型的请求,包括静态资源请求(css、js、图片等)和jsp请求。
配置方式四:
<url-pattern>/one/*</url-pattern>
注意:
会拦截处理所有Servlet的别名以one开头的路径的请求
注意:
一个Servlet可以配置多个url-pattern
不同的Servlet不允许配置相同的url-pattern,如果配置了在服务器启动的时候就会报错。
服务器启动的时候就会将部署的项目中的web.xml文件加载进内存
5.服务器中的servlet创建是单例的
1.为什么Servlet只会创建一个?
1.创建过多的Servlet会使用服务器的性能降低。
2.不安全。
注意:1.服务器接收到请求之后,会开辟一个线程处理此次请求,在线程中调用对应的Servlet进行处理。
2.服务器调用Servlet处理请求时,只会创建一个Servlet对象,此对象是线程共享的
Servlet 的生命周期:
从第一次被调用到服务器关闭
验证:
init方法 :servlet被初始化创建的时候调用
service方法:处理请求的时候
destory 方法 :servlet 被销毁的时候。
当服务器关闭的时候销毁 servlet,触发destroy方法的执行
代码验证:
第一次请求时:
关闭服务器后:
6.Service 和 doGet 和 doPost 方法的区别
Service方法:
不管是 get 方式还是 post 方式的请求,如果 Servlet 类中有service方法,则优先调用 Service方法。
doGet方法:
在没有service方法的情况下如果是get方式的请求所调用的处理请求的方法
doPost方法:
在没有 service 方法的情况下如果是 post 方式的请求所调用的处理请求的方法
代码示例:
7.Servlet 的常见错误总结:
1)404错误:资源未找到
原因一:在请求地址中的servlet的别名书写错误。
原因二:虚拟项目名称拼写错误
2) 500错误:内部服务器错误
错误一:
java.lang.ClassNotFoundException:com.bjsxt.servlet.ServletMothod
解决:
在web.xml中校验servlet类的全限定路径是否拼写错误。
错误二:
因为service方法体的代码执行错误导致
解决:
根据错误提示对service方法体中的代码进行错误更改。
3) 405错误:请求方式不支持
原因:
请求方式和servlet中的方法不匹配所造成的。
解决: 尽量使用 service 方法进行请求处理,并且不要再 service 方法中调用父类的service。
8:HTTPServletRequest的介绍和特点
1.什么是HTTPServletRequest?
HTTPServletRequest是一个接口,其实现了ServletRequest接口,实现类为Request,
Request是服务器创建并封装用户请求数据的类。
服务器在接收到请求后,会给此次请求创建个request对象,此对象中封存了此次请求相关的数据。
2.Requst作用:存储请求数据
注意:每次请求都会创建新的request对象存储请求数据.
3Requst特点:
1)request对象由服务器创建
2)一次请求创建一个request对象
3)生命周期为一次请求内,请求结束即销毁此次请求的request对象
4.request对象获取请求数据的方法:
请求行:请求方式 请求URL 协议
* getMethod(); 返回请求方式
* getRequestUrl(); 返回请求url
* getRequestUri(); 返回请求uri
* getQueryString(); 返回get请求中的URL中的用户数据 注意:post请求中没有此方法。
* getSchema(); 返回协议
* 请求头
* getHeader(String name) 根据键名获取请求头信息
* 注意:如果获取的请求头信息不存在返回null。
* getHeaderNames() 返回存储了请求头键名的枚举集合。
* 请求实体
* getParameter(String name) 根据键名获取数据
* 注意:
* 键名其实就是前端页面中的表单标签的name属性的值或者前端页面其他方式提交数据的键的名字
* 如果请求中没有对应的请求数据,则返回null.
* getParameterValues(String name) 根据键名获取同名不同的值,返回数组
* 注意:如果没有对应的键名,则返回null
* getParameterNames() 返回实体数据中键名的枚举
* 请求网络相关数据
* getRemoteAddr() 获取客户端的IP地址
* getRemotePort() 获取客户端端口号
* getLocalAddr() 获取服务器端的ip
* getLocalPort() 获取服务器端的端口号
代码如下:
9.HttpServletResponse对象的介绍:
如上图可知,HttpServletResponse为继承了 ServletResponse 接口的java接口;被服务器创建。
9.1为什么需要HttpServletResponse?
用来进行响应浏览器的请求。
9.2HttpServletResponse对象的使用?
设置响应头
设置响应编码格式
设置响应实体
9.3 HttpServletResponse对象的方法?
设置响应行: 协议 状态码 状态消息
resp.sendError(int status); 作用:可以自主的响应状态给浏览器
设置响应头
* addHeader(String name,String value) 添加响应头信息,同名数据不会覆盖
* setHeader(String nanme,String value) 设置响应头信息,会覆盖原有信息。如果没有此响应头则添加该信息。
* 设置响应实体(处理结果)
* resp.getWriter().write("实体内容");
注意:(1)实体内容可以分开进行响应。
(2)一旦使用resp对象作出了请求响应,则意味着此次请求处理完毕。服务器在响应后会将此次请求相关的req对象和resp对象销毁。
详细见代码:
10、请求乱码问题解决:
10.1、post请求方式乱码:
* req.setCharacterEncoding("utf-8");
10.2、 get请求方式乱码解决:
* 方式一:每个数据都要单独的进行转换
* String uname=req.getParameter("uname");
* String uname2=new String(uname.getBytes("iso-8859-1"), "utf-8");
* 方式二:
* req.setCharacterEncoding("utf-8");
* 在tomcat的server.xml文件中的Connector标签中增加属性: useBodyEncodingForURI="true"
10.3、响应乱码问题:浏览器中显示的服务器响应数据乱码
* resp.setContentType("text/html;charset=utf-8");
10.4、service代码编写流程:
* 设置请求编码格式
* 设置响应编码格式
* 获取请求信息
* 处理请求信息
* 响应处理结果
代码示例:
简单的登录实现:
11.Servlet中的请求转发和重定向
11.1、请求转发。
11.1.1、为什么需要请求转发?
服务器在接收到浏览器的请求后,仅仅使用一个Servlet 进行请求处理,会造成不同的 Servlet 逻辑代码冗余,Servlet的职责不明确。就需要用到请求转发技术。
11.1.2、原理图:
11.1.3、请求转发的使用:
req.getRequestDispatcher("servlet别名").forward(req, resp);
11.1.4、请求转发中Request对象的作用域:
问题:使用请求转发后,不同的Servlet之间怎么进行数据的共享呢?或者说数据怎么从一个 servlet流转给另外一个 Servlet呢?
解决:使用request对象的作用域
Request作用域:基于请求转发,一次请求中的所有 Servlet共享。
使用:
添加数据:(以键值对的形式)
request.setAttribute(object name,Object value);
request.getAttribute(Object obj) 根据键获取值。
特点:
a. 服务器创建
b. 每次请求都会创建
c.生命周期一次请求
11.2、重定向的介绍
11.2.1、为什么需要重定向?
问题: 如果当前的请求,Servlet无法进行处理怎么办?
如果使用请求转发,造成表单数据重复提交怎么办?
11.2.2、原理图:
11.2.3、使用:
response.sendRedirect(“路径”).
11.2.4、特点:
a.两次请求
b.浏览器地址栏信息改变
c.避免表单重复提交
登录优化: