本帖最后由 小石姐姐 于 2019-1-4 09:16 编辑
Servlet概念server applet 运行在服务器上的小程序 Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则 将来我们自定义一个类,实现Servlet接口,复写方法
快速入门创建JavaEE项目 定义一个类,实现Servlet接口 实现接口中的抽象方法 配置Servlet:在web.xml中配置
<!--配置Servlet-->
[Java] 纯文本查看 复制代码 <servlet>
<servlet-name>
demo01
</servlet-name>
<servlet-class>
cn.itcast.web.servlet.ServletDemo01
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>demo01</servlet-name>
<url-pattern>/demo01</url-pattern>
</servlet-mapping> 注:一般在IDEA中配置Tmocatd的Application context为/项目名称,再调用时需要用localhost:8080/项目名称/.... Servlet的执行原理当服务器接受到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径 查找web.xml,是否有对应的<url-pattern>标签内容 通过servlet-pattern找到servlet-name,又通过name找到资源的class全类名. tomcat将类加载进内存,通过反射创建对象并调用service方法
Servlet中的生命周期初始化方法,在Servlet被创建时执行,只会执行一次
- Servlet什么时候被创建?
*默认情况下,第一次被访问时,Servlet被创建
*可以在web.xml中配置创建时机
<servlet>
<load-on-startup>
0/正值:服务器启动时创建,值越大优先级越小,一般从2开始,因为1被tomcat占用了
负值:第一次被访问时创建
</load-on-startup>
</servlet>
- Servlet在服务器中只有一个对象,所以说Servlet是单例的
*多个用户同时访问时,可能存在线程安全问题
*解决方案:尽量不要在Servlet中定义成员变量,而是使用局部变量;即使定义了成员变量,也不要对其修改值每一次Servlet被访问一次则执行一次 Servlet被杀死(服务器正常关闭)时执行一次
一般用于释放资源ServletConfig方法 获取ServletConfig对象 ServletInfo方法 获取ServletInfo,如版本.作者,信息等,但一般不实现该方法
Servlet 3.0注解配置-[ ] 好处:支持注解配置,可以不需要web.xml了-[ ] 步骤 @WebServlet("资源路径")
IDEA和tomcat的相关配置
启动后服务器控制台有输出Log:
Using CATALINA_BASE: "C:\Users\Mcdull\.IntelliJIdea2017.3\system\tomcat\Tomcat_8_5_31_webServer_2"
在Edit Configure下就可以修改配置文件和虚拟目录!!!!理解
采用的部署方式为第三种,在config/catalina/下部署
打开Using CATALINA_BASE路径,可以找到config/catalina/day13_servlet.xml
打开servlet.xml,<Context docBase="E:\Projects\webServer\out\artifacts\day13_servlet_war_exploded" \>
里面指明了tomcat项目的路径WEB-INFO目录下的资源不能被浏览器直接访问 断点调试
打断点,后用debug模式启动服务器
Servlet结构体系
GenericServlet
GenericServlet将除了servic()以外的方法都空实现
将来定义Servlet时可以继承GericServlet,只需实现servic类即可.
其他类也可以重写HttpServlet-[ ] 实际上做项目时,我们一般使用GenericServlet的子类HttpServlet,因为HttpServlet封装了Http协议
不使用HttpServlet时,service方法需要实现的功能
判断用户的请求方式(get/post...)
String method = req.getMethod();
if("GET".equals(method)){//get方式获取数据逻辑操作}
else if("POST".equals(methos){//post方式获取数据逻辑操作}
HttpService 将判断请求方式封装起来,并提供doGet()和doPost()方法,分别写在两个逻辑体中1.定义类继承HttpServlet类 2.重写doGet/doPost/...方法
[Java] 纯文本查看 复制代码 @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp){
System.out.println("doGet...");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp){
System.out.println("doGet...");
}
Servlet urlpattern相关配置
一个Servlet可以定义多个访问路径,在注解中使用{"路径1","路径2"...}来配置1)./xxx 以这种方式为主
2)./xxx/xxx
3).*.后缀名
[强制!]开发中后缀名只能用*.do或*.action
HTTP概念
1). 基于TCP/IP的高级协议
2). HTTP的默认端口号为80
当访问资源时,如果服务器端口号为80,则可以省略
3). 基于请求/响应模型的:一次请求对应一次响应
4). 无状态的:每次请求之间相互独立,不能交互数据1.0版本:每一次请求都需要建立一个连接 1.1版本:复用连接
请求消息数据格式 请求行格式:
请求方式 请求url 请求协议/版本
例: GET /login.html http/1.1HTTP协议中有7种请求方式,常用的有2种
*GET:
1.请求参数在请求行中,在url后
2.请求的url长度是有限制的
3.不太安全
*POST:
1.请求参数在请求体中
2.请求的url长度没有限制
3.相对安全 请求头格式:
请求头名称:请求头值常见的请求头:
1.User-Agent**:浏览器告诉服务器,访问者使用的浏览器版本信息
*可以在服务器端获取该头信息,解决浏览器兼容性问
2.Referer**:告诉服务器,当前请求从哪里来(发起请求的页面)
*例:Referer:http://localhost:8080/day_14/login.html
*作用:
1)防盗链:
if(referer.equals()){操作}
else{"想看吗?来XXX网站吧!"}
2)统计工作:
统计工作:统计请求来源
if(refer.eauals("百度"){百度++}
else if(){}...
3.Connection:告诉服务器连接的状态(是否可服用)
4.Host:请求主机的地址
5.Accept:告诉服务器,作为浏览器可以解析什么格式的文件请求空行-用于分割POST请求的请求头和请求体 空行 请求体(正文)-封装post请求消息的请求参数 格式
参数名=参数值
响应消息数据格式
协议/版本 响应状态码 状态码的描述分类:
1xx: 服务器接收客户端消息,没有接收完成,等待一段时间后,发送1xx
2xx: 成功 代表状态码:200
3xx: 重定向 代表状态码:302(重定向) 304(访问缓存)
4xx: 客户端错误 代表状态码:404(请求路径错误) 405(请求方式没有对应的doXXX方法)
5xx: 服务器错误 代表状态码:500(服务器内部出现异常)头名称:值1.Content-Type:服务器告诉客户端响应体数据格式以及编码格式
例:Content-Type:text/html;charset=UTF-8
2.Content-disposition:服务器告诉客户端以什么格式打开响应体数据
*值:
*in-line:默认值,在当前页面内打开
*attachment;filename=xxx:以附件形式打开响应体.文件下载响应字符串格式Request对象Request和Response对象的原理1.tomcat服务器会根据请求url中的资源路径,创建对应的Servlet对象 2.tomcat服务器会创建request和response对象;request对象中封装消息数据 3.tomcat将request和response两个对象传递给service方法,并调用service方法 4.程序员可以通过request对象来获取请求消息数据;可以通过response对象来设置响应数据 5.tomcat在给浏览器作出响应之前,会从response对象中获取消息响应数据并响应给浏览器 注意:
1) request和response对象是由服务器创建的,我们来使用它们
2) request对象是来获取请求消息,response对象来设置响应消息
Requset对象的继承结构
Request对象的功能获取请求消息数据 -请求行数据: GET /day14/demo01?name=zhangsan HTTP/1.1
-获取方法:
1)获取请求方式: GET
*String getMethod()
2)获取虚拟目录**: /day14
*String getContextPath()
3)获取Servlet路径 /demo1
*String getServletPath()
4)获取请求参数 /name=zhangsan
*String getQueryString()
5)获取请求的URI**: /day14/demo1
*String getRquestURI :/day14/demo1
*StringBuffer getRequestURL: http://localhost/day14/demo1
6)获取浏览器的协议及版本 HTTP/1.1
*String getProtocol()
7)获取客户机的IP地址
*String getRemoteAddr()
注意:
URL:统一资源定位符 http://localhost//day14/demo1
URI:统一资源标识符
day14/demo1
URL的范围比URI的范围小1) String getHeader(String name):通过请求头名称获取请求头的值
2) Enumeration<String> getHeadernames():获取所有请求头的名称
Enumberation 和 Iterator类似:
hasMoreElement() <--> hasNext()用于判断
nextElement() <--> next() 用于获取下一下元素步骤:
1).获取流对象
*BufferedReader getReader():获取字符输入流
*ServletInputStream getInputStream():获取字节输入流
2).从流对象中获取数据4.总结:常用的方法 1)获取虚拟目录:getContextPath() 2)获取请求URI:getRequestURI()/getRequestURL() 3)获取请求头:getHeader(String name)
==其他功能== 1)String getParameter(String name):根据参数名称获取参数值
2)String[] getParameterValues(String name): 根据参数名称获取参数值的数组,多用于复选框
如:hobby=xx&hobby=game
3)Enumeration<String> getParameterNames():获取所有请求的参数名称
4)Map<String,String[]> getParameterMap():获取所有参数的map集合
- 中文乱码问题
*get方式: tomcat8 已经将get方式乱码问题解决了
*post方式: 会乱码
解决:在获取参数前,设置request编码
request.setCharacterEncoding("utf-8")1)通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
2)使用RequestDispatcher对象来进行转发:forward(ServletRequest request,ServletResponse)1) 浏览器地址栏路径不发生变化2) 只能转发至当前服务器的内部资源中3) 转发是一次请求
==3.数据共享== 域对象:一个有作用范围的对象,可以在范围内共享数据 request域:代表一次请求的范围,一般用于请求转发的多个资源中去共享数据 request资源共享方法
1) void setAttribute(String name ,Object obj) :存储数据2) Object getAttribute(String name) 通过键来获取值3) void removeAttribute(String name) 通过键来移除键值对
-ServletContext getServletContext()
BeanUtilsJavaBean JavaBean:标准的Java类 类必须被public修饰 必须提供空参的构造器 成员变量必须使用private修饰 提供公共的setter和getter方法 JavaBean的功能:封装数据
概念 成员变量 属性:setter和getter方法截取后的产物
例如:getUsername()-->Username-->username大部分情况下属性和成员变量是一样的
BeanUtils的方法 1.setProperty(javaBean,"属性名","值") 2.getProperty(javaBean,"属性名") 3.populate(javaBean,属性集map)
Response对象设置响应行 1.格式HTTP/1.1 200 ok2.设置状态码setStatus(int sc)
设置响应头 setHeader(String name, String value) 设置响应体 1.获取输出流 *字符输出流:PrintWriter getWriter() *字节输出流:ServletOutputStream getOutputStream()2.使用输出流将数据输出到客户端浏览器
案例完成重定向(redirect) //1.设置状态码为 302response.setStatues(302);//2.设置响应头locationresponse.setHeader("location","/虚拟路径/资源路径")
resonpse.sendRedirect("/虚拟路径/资源路径")
1. 地址栏发生变化2. 重定向可以访问其他服务器的资源3. 重定向是两次请求
1.相对路径: 通过相对路径不可以确定唯一资源 * 以 ./开头 表示当前路径 * 以 ../开头 表示后退一级 *规则: 找到当前资源和目标资源之间的相对位置关系 2.绝对路径: 绝对路径可以确定唯一资源 在这里可以写为/虚拟路径/资源路径
在浏览器输出字符数据 //1.获取字符输出流PrintWriter pw = resp.getWriter();//2.向浏览器写出字符数据pw.write("<h1>你好,response</h1>");此实现会出现乱码,因为获取的流的默认编码为IOS-8859-1
上一个代码实现会出现乱码问题
解决方法:在获取流之前设置编码和web解码方式
//1.设置response的编码格式(默认为IOS-8859-1)
//response.setCharacterEncoding("编码格式")
//2.使用response设置响应头,要求使用特定的编码格式去解码
response.setHeader("content-type","text/html;charset=编码格式")
简单方法:
response.setContentType("text/html;charset=编码格式")
注意:使用语句2,就可以设置编码格式,和浏览器的解码格式.第1步就可以不用写了
|