servlet介绍
Servlet规范来自于Java EE 规范中的一种。
作用:
在Servlet规范中,制定了【动态资源文件】的开发步骤
在Servlet规范中,制定了http服务器调用动态资源文件规则
在Servlet规范中:制定http服务器管理动态资源文件实例对象规则
Servlet接口实现类
Servlet接口来自于Servlet规范下的一个接口,这个接口存在Http服务器提供jar包。
在Tomcat服务器下lib文件有一个servlet-api.jar存放Servlet接口(javax.servlet.Servlet接口)
Servlet规范中认为,Http服务器能调用的【动态资源文件】必须是一个Servlet接口实现类。
例子:
class Student{
//不是动态资源文件,Tomcat无权调用
}
class Teacher implements Servlet{
//合法动态资源文件,Tomcat有权利调用
Servlet obj = new Teacher();
obj.doGet()
}
Servlet接口实现类开发步骤
第一步:创建一个Java类继承与HttpServlet父类,使之成为一个Servlet接口实现类
抽象类的作用:降低接口实现类对接口实现过程的难度。将接口中不需要使用的抽象方法交给抽象类进行完成,这样接口实现类只需要对接口需要方法进行重写
子类----->父类------>A接口
此时,子类也是A接口的实现类
servlet接口:
init
getServletConfig
getServletInfo
destory
这四个方法对于Servlet接口实现类没用
service() 有用
Tomcat根据Servlet规范调用Servlet接口实现类规则:
1.Tomcat有权创建Servlet接口实现类实例对象
Servlet oneServlet = new OneServlet();
2.Tomcat根据实例对象调用service方法处理当前请求
oneServlet.service(),此时service方法中this指向的就是oneServlet实例对象
第二步:重写HttpServlet父类两个方法。doGet或则doPost
get
浏览器------》oneServlet.doGet()
@Override
protected void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{
super.doGet(req,resq);
}
post
浏览器------》oneServlet.doPost()
@Override
protected void doPost(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{
super.doPost(req,resq);
}
通过父类决定在何种情况下调用子类中方法----在设计模式中,叫做模板设计模式
HttpServlet:
service(){
if(请求方式 == GET){
this.doGet();
}else if(请求方式 == POST){
this.doPost();
}
}
doGet
doPost
OneServlet: doGet doPost
Servlet oneServlet = new OneSerrvlet();
oneServlet.service();
第三步:将Servlet接口实现类信息【注册】到Tomcat服务器
【网站】--->【web】---》【WEB-INF】--->web.xml
写到web.xml中
<!--将Servlet接口实现类类路径地址交给Tomcat-->
<servlet>
<servlet-name>mm</servlet-name> <!--声明一个变量存储servlet接口实现类类路径-->
<servlet-class>com.bjpowernode.controller.OneServlet</servlet-class><!--声明servlet接口实现类类路径-->
</servlet>
//Tomcat String mm = "com.bjpowernode.controller.OneServlet"
<!--为了降低用户访问Servlet接口实现类难度,需要设置简短请求别名-->
<servlet-mapping>
<servlet-name>mm</servlet-name>
<url-pattern>/one</url-pattern> <!--设置简短请求别名,别名在书写时必须以"/"为开头-->
</servlet-mapping>
如果现在浏览器向Tomcat索要OneServlet时地址:http://localhost:8080/myWeb/one
Servlet对象的生命周期
1.网站中所有的Servlet接口实现类的实例对象,只能由Http服务器负责额创建。
开发人员不能手动创建Servlet接口实现类的实例对象
2.在默认的情况下,Http服务器接收到对于当前Servlet接口实现类第一次请求时自动创建这个Servlet接口实现类的实例对象
在手动配置情况下,要求Http服务器在启动时自动创建某个Servlet接口实现类的实例对象
<servlet>
<servlet-name>mm</servlet-name> <!--声明一个变量存储servlet接口实现类类路径-->
<servlet-class>com.bjpowernode.controller.OneServlet</servlet-class>
<load-on-startup>30<load-on-startup><!--填写一个大于0的整数即可-->
</servlet>
3.在Http服务器运行期间,一个Servlet接口实现类只能被创建出一个实例对象
4.在Http服务器关闭时刻,自动将网站中所有的Servlet对象进行销毁
HttpServletResponse接口
1.HttpServletResponse接口来自于Servlet规范中,在Tomcat中存在于servlet-api.jar
2.HttpServletResponse接口实现类由Http服务器负责提供
3.HttpServletResponse接口负责将doGet/doPost方法执行结果写入到【响应体】交给浏览器
4.开发人员习惯于将HttpServletResponse接口修饰的对象称为【响应对象】
主要功能:
- 将执行结果以二进制形式写入到【响应体】
- 设置响应头中[content-type]属性值,从而控制浏览器使用对应编译器将响应体二进制数据编译为【文字,图片,视频,命令】
- 设置响应头中【location】属性,将一个请求地址赋值给location,从而控制浏览器向指定服务器发送请求
public class OneServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{
String result = "Hello World";//执行结果
//--------------响应对象将结果写入到响应体-----------start
//1.通过响应对象,向Tomcat索要输出流
PrintWriter out = response.getWriter();
//2.通过输出流,将执行结果以二进制形式写入到响应体
out.write(result);
//--------------响应对象将结果写入到响应体-----------start
}//doGet执行完毕
//Tomcat将响应包推送给浏览器
}
这就存在一个问题,就是如果我传过去的结果是int类型的50,浏览器接收到的并不是50,而是2.
产生这个问题的原因:
out.write()方法可以将【字符】,【字符串】,【ASCII码】写入到响应体中
在ASCII中:a对应的是97,2对应的是50
怎么解决呢?
使用out.print()方法
在实际开发过程中,都是通过out.print()方法,将真实数据写入到响应体
如果一个字符串,这其中既有文字信息,又有HTML命令,浏览器显示的还是这一串,并没有把br当作命令
String result = “java<br/>mysql<br/>HTML<br/>";
PrintWritr out = response.getWriter();
out.write(result);
问题原因:
浏览器在接收到响应包之后,根据【响应头中content-type】属性的值,来采用对应【编译器】对【响应体中二进制内容】进行编译处理
在默认情况下,content-type属性的值是“text”,content-type="text",此时浏览器将会采用【文本编译器】对响应体二进制数据进行解析
解决方案:
一定要在得到输出流之前,通过响应对象对响应头中content-type属性进行依次重新赋值用于指定浏览器采用正确编译器
String result = “java<br/>mysql<br/>HTML<br/>";
//设置响应头content-type
response.setContentType("text/html;charset=utf-8");
//向Tomcat索要输出流
PrintWritr out = response.getWriter();
//通过输出流将结果写入到响应体
out.print(result);
每次进行修改都要重启一次tomcat服务器,很麻烦。那怎么办呢?
我们【run---Edit Configurations】找到开关,在开关里有一个【server】选项卡,在【server】之下有两个【On 'Update' action】和【On frame deactivation】,这两个都选上【Update classes and resources 】。意思就是当静态资源文件内容或者动态资源文件内容发生变化的时候,idea自动把他更新到tomcat中。
不过,刚才输入的是英文的换成中文的话,又会出现bug了,就是,这个浏览器上显示的换行的确是换了,不过中文文字显示的是问号啊
这时候就需要设置字符集了charset,上一段代码中写出了。不指定字符集的话,charset的默认字符集是ISO-8859-1。
浏览器在接收到响应包之后,如果发现响应头中存在location属性,自动通过地址栏向location指定网站发送请求
String result = "http://www.baidu.com";
//通过响应对象,将地址赋值给响应头中location属性
response.sendRedirect(result);//[响应头 location="http://www.baidu.com"]
sendRedirect方法远程控制浏览器请求行为【请求地址,请求方式,请求参数】
HttpServletRequest接口
HttpServletRequest接口来自于Servlet规范中,在Tomcat中存在servlet-api.jar
HttpServletRequest接口实现类由Http服务器负责提供
HttpServletRequest接口负责在doGet/doPost方法运行时读取Http请求协议包中信息
开发人员习惯于将HttpServletRequest接口修饰的对象称为【请求对象】
作用:
1)可以读取Http请求协议包中【请求行】信息
2)可以读取保存在Http请求协议包中【请求头】或者【请求体】中请求参数信息
3)可以代替浏览器向Http服务器申请资源文件调用
//1.通过请求对象,读取【请求行】中【url】信息
String url = request.getRquestURL().toString();
//2.通过请求对象,读取【请求行】中【method】信息
String method = request.getMethod();
//3.通过请求对象,读取【请求行】中uri信息
String uri = request.getRequestURI();
URI:资源文件精准定位地址,在请求行并没有uri这个属性。
实际上是URL中截取一个字符串,这个字符串的格式:"/网站名/资源文件名"
uri用于Http服务器对被访问的资源文件进行定位
在WEB-INF文件夹下创建一个超链接来访问servlet携带参数
<html>
<body>
<center>
<a href="/myWeb/two?userName=mike&password=123">通过超链接访问TwoServlet所携带请求参数</a>
</center>
</body>
</html>
//1.通过请求对象获得【请求头】中【所有请求参数名】
Enumeration paramNames = request.getParameterNames();//将所有请求参数名称保存到一个枚举对象进行返回
while(paramNames .hasMoreElements()){
String paramName = (String)paramNames .nextElement();
//2.通过请求对象读取指定的请求参数的值
String value = request.getParameter(paramName );
System.out.println("请求参数名:" + paramName + " 请求参数值:" + value);
}
<html>
<body>
<center>
<form action="/myWeb/three" method="get">
请求参数:<input type="text" name="useName"/><br/>
<input type="submit" value="get方式发访问ThreeServlet">
</form>
<form action="/myWeb/three" method="post">
请求参数:<input type="text" name="useName"/><br/>
<input type="submit" value="post方式发访问ThreeServlet">
</form>
</center>
</body>
</html>
在doPost方法里读取请求体,在doGet方法里读取请求头
//doPost方法:
//通知请求对象,使用utf-8字符集请求体二进制内容进行一次重新解码
request.setCharacteEncoding("utf-8");
//通过请求对象,读取【请求体】参数信息
String value = request.getParameter("userName");
//doGet方法:
//通过请求对象,读取【请求头】参数信息
String userName= request.getParameter("userName");
以get方式发送中文参数内容,得到正常结果
以post方式发送中文参数内容,得到乱码
出现这种问题的原因:
浏览器以get方式发送请求,请求参数保存在【请求头】,在Http请求协议包到达Http服务器之后,第一件事就是进行解码,请求头二进制内容由Tomcat负责解码,Tomcat9.0默认使用【utf-8】字符集,可以解释一切国家文字。
浏览器以post方式发送请求,请求参数保存在【请求体】,在Http请求协议包到达Http服务器之后,第一件事就是进行解码,请求体中二进制内容由当前请求对象(request)负责解码,request默认使用的字符集是【ISO-8859-1】,一个东欧语体系字符集,此时如果请求体参数内容是中文,将无法解码只能得到乱码。
解决方案:
在post请求方式下,在读取请求体内容之前,应该通知请求对象使用utf-8字符集对请求体内容进行一次重新解码
请求对象和响应对象生命周期
1.在Http服务器接收到浏览器发送的【Http请求协议包】之后,自动为当前的【Http请求协议包】生成一个【请求对象】和一个【响应对象】
2.在Http服务器调用doGet/doPost方法时,负责将【请求对象】和【响应对象】作为实参传递到方法,确保doGet/doPost正确执行
3.在Http服务器准备推送Http响应协议包之前,负责将本次请求关联的【请求对象】和【响应对象】销毁
【请求对象】和【响应对象】生命周期贯穿一次请求的处理过程中
【请求对象】和【响应对象】相当于用户在服务端的代言人
欢迎资源文件
前提:
用户可以记住网站名,但是不会记住网站资源文件名
默认欢迎资源文件:
用户发送了一个针对某个网站的【默认请求】时,此时由Http服务器自动从当前网站返回的资源文件
正常请求: http://localhost:8080/myWeb/index.html
默认请求: http://localhost:8080/myWeb/
Tomcat对于默认欢迎资源文件定位规则
1)规则位置:Tomcat安装位置/conf/web.xml
2)规则命令:
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
设置当前网站的默认欢迎资源文件规则
1)规则位置: 网站/web/WEB-INF/web.xml
2)规则命令:
<welcome-file-list>
<welcome-file>login.html</welcome-file>
</welcome-file-list>
3)如果网站设置自定义默认文件定位规则,此时Tomcat自带定位规则将失效
网友评论