Java EE之Servlet、JSP学习
这个学期开了Java EE的课程,借此机会好好的自学了下Java EE。写几篇博客记录下自己遇到的问题、学习过程。希望能帮到有需要的人,也能供自己日后查阅。文章中有错误之处,还请大家指正,共同进步。参考了很多大牛的博客文章,很是感谢。
使用的一些工具如下:
开发工具:Eclipse neon
服务器:Tomcat 8.5
数据库:MySQL 5.6.17
数据库可视化工具:phpMyAdmin
因为以前学习PHP的缘故,所以习惯了使用phpMyAdmin,在Tomcat服务器上安装phpMyAdmin可以参考我的另一篇文章:http://blog.csdn.net/yc_wj/article/details/69218738
Servlet、JSP简介:
虽然现在Java EE的开发有各种各样的框架可以选择,但个人认为还是应该要先了解Servlet的由来和原理,这样可以更好的帮助我们理解和使用框架,毕竟框架也是在Servlet的基础上再各种封装。
Servlet由来:
在最初B/S模式刚兴起时,用户只能通过浏览器向服务器请求静态资源,但随着因特网发展,用户需要获取动态处理后的资源是必然的。为了满足动态处理的需求,通用网关接口(CGI,Common Gateway Interface)就出现了。CGI是为特定OS编写的,不可移植,对每个请求产生新进程进行处理。
B/S模式的浪潮,Java也想追赶,于是就有了Applet和Servlet,这两者都属于Java EE。
Applet(客户端小程序):一种纯客户端(浏览器)实现方案,Applet作为浏览器的一个Java插件,浏览器通过解释执行Web服务器发过来的Java代码,从而实现动态。但这种方案很不好,浏览器必须安装插件而且还受限于浏览器,同时Web服务器发送过来的Java代码也不能太复杂。(感兴趣的朋友可以自行搜索了解)
Servlet:既然浏览器不方便执行Java代码,那还是交由服务器来执行的好,这也就是Servlet的来由,Servlet就是Server端的Applet的意思。使用Servlet类将Http请求和响应封装在Java类中来实现各种Web应用,Servlet类会被编译成体系结构中立的字节码,由基于Java的Web服务器动态加载和执行。
请求 ——> Servlet 引擎 ——> Servlet 模块
Servlet 模块 ——> Servlet 引擎 ——> 响应
Servlet与CGI:Servlet性能更好、具有平台无关性、可信、可使用整个Java类库,不需要为每个请求创建一个进程来处理。
Servlet发展:
早期的Servlet虽然有很多优点,但存在大量冗余代码,并且输出HTML语句依然是老的CGI方式,要一句一句用out输出,这对于界面设计显然是非常不友好的,难以实现各种页面效果。
所以,Sun就借鉴了ASP,提出了JSP(Servlet1.1)。此时Java程序员可以将服务端代码添加到已经设计好的静态页面上,再由一个JSP容器对JSP文件进行自动解析并转换成Servlet类来交给服务器运行。这也就是Java EE中的Model 1 开发模式(JSP既负责创建HTML页面,又要负责业务逻辑)。
Model 1模式显然也是存在问题的,前端开发者需要看JSP中大量懵逼的后端代码,而后端开发者也要在大量的前段代码中找到能写Servlet代码的地方!随着项目增大,功能越来越复杂,这种交叉的工作流让前后端都很不爽,难以开发啊。
于是,Servlet1.2出现了,该版本开始倡导MVC模式:
JSP(V):视图,用标签封装后端代码,让界面看上去跟清爽,负责显示数据
Servlet(C):控制器,控制请求分发
Model(M):模型,其实就是封装了数据或业务逻辑功能的JavaBean类
这样的MVC模式也就是Java EE中的Model 2 开发模式,此时的Servlet和早期的相比有了极大的简化,应该说通过分层,将早期Servlet的功能分离从而达到了简化效果。
至此,Servlet的大方向就基本固定了,一直到今天,虽然有各种各样优秀的框架出现,但也都是建立在这个Model 2 的基础上的。
Servlet含义:
广义:基于Java技术的Web组件,被容器托管,用于生成动态内容。再详细的说,Servet是JavaEE组件中的Web组件中的一种(还有就是Java Server Faces和JavaServer Page)。
狭义:是JavaEE API 的一个interface,javax.servlet.Servlet。
Servlet容器/引擎:
Servlet容器也可以叫引擎,Container/Enginee,用于执行Servlet。
容器以内嵌或附加组件形式存在Web服务器或应用服务器中。
容器本身(不依赖Web服务器)就提供了基于请求/响应发送模型的网络服务,解码基于MIME的请求,格式化基于MIME的响应。
web.xml = 部署描述符
请求编码:
1、请求以什么编码发送给服务器,由浏览器决定。
2、服务端,Servlet规范规定请求没有指定编码时,容器必须使用iso-8859-1解码,通过getCharacterEncoding返回null知道没有设置编码
3、ServletRequest提供 setCharacterEncoding 修改请求编码
Servlet Context(Servlet 上下文):
一个Web应用对应一个Servlet接口的实例。所有用户公用一个,可看作一个全局存储空间。
ServletContext提供直接访问Web应用中的静态内容:getResource,getResourceAsStream
这两个方法的String参数必须以 “/” 开头,相对于ServletContext Path 的路径
还有几个重要的对象:ServletConfig、ServletRequest、ServletResponse
请求路径元素:
1、Context Path(项目根目录),例 /myApp
2、Servlet Path(与web.xml中的<url-pattern>配置相关,“/”开头)
3、PathInfo(要么为空,要么以“/”开头)
映射请求到Servlet的规则:
http://hostname/myApp/Servlet?xxx,
对于上述路径,需要映射的路径为 /Servlet
匹配有四种次序:精确匹配<url-pattern>,再最长匹配,再扩展名匹配,再低保匹配。
“/”开头,/*结尾,表示路径匹配
*. 开头用于扩展名匹配
只包含 “/” 表示应用default servlet,并不是匹配全部
Tomacat的web.xml中也遵循上述规范:
可以看到践行了上述Servlet的映射规范
对于 .jsp文件:org.apache.jasper.servlet.JspServlet这个Servlet类最终会
- 先将 .jsp 文件转换成 .java 文件
- 然后将 .java 文件 complier成 .class 文件
对于 default:org.apache.catalina.Servlets.DefaultServlet 这个Servlet最终会
- 为所有没有被匹配到的URL做匹配,即“低保”匹配;
- 如果找到了相应的资源了就返回,没有找到或者发生一些异常就返回400/404等状态码机器页面,长相如下
更多有关Servlet知识可以参考下面的博客:
Servlet历史与规范:
http://blog.csdn.net/u010297957/article/details/51498018Java EE之Servlet技术:
http://blog.csdn.net/nicewuranran/article/details/51685821Java Servlet完全教程:
http://www.importnew.com/14621.htmlServlet 工作原理解析:
https://www.ibm.com/developerworks/cn/java/j-lo-servlet/JSP:
JSP(Java Server Pages),和ASP、PHP类似,一种动态网页开发技术,通过使用JSP标签在HTML网页中插入Java代码。
普通脚本标签:<% %>
声明标签:<%! %>,用于声明全局变量和函数,并且声明的变量和函数可供本页面其它java代码调用。会被翻译成servle的成员变量或函数
表达式标签:<%= %>,用于直接在页面输出表达式的值,该标签中不能有分号。经服务器翻译后成 out.print();
JSP生命周期:
1、第一次访问JAP,会验证是否第一次访问,然后将JSP文件转化成Servlet,再编译成class文件
2、生成的class文件会自动生成几个方法:jspInit(),jspDestory(),jspService(),Tomcat仅在第一次请求时,调用jspInit()方法,然后调用jspService()进行处理。
3、之后的每个请求,都会分配一个线程调用jspService()方法
4、如果页面被销毁或关闭,都会调用jspDestory()方法。
(如果项目直接部署在Tomcat服务器的WebApps,那就可以在Tomcat的workDir目录下生成的jsp文件对应的Servlet类,即.java 文件)
JSP指令元素和动作:
<%@ 指令 属性>
<jsp:动作 >
对于具体的指令元素、属性和动作,其它资料上已经有很多介绍了,这里就不再赘述。
易百 JSP教程:
http://www.yiibai.com/jsp/jsp_quick_guide.html
jsp页面通过request对象得到的数据都是String类型,若想转换成int类型,需要使用Integer.parseInt(String xx)方法。不过转换语句必须放在try catch 块中,因为转换可能发生异常 NumberFormatException
JSP页面编码设置:
1、pageEncoding="UTF-8" 的作用是设置JSP编译成Servlet时使用的编码。
2、contentType="text/html;charset=UTF-8" 的作用是指定对服务器响应进行重新编码的编码。
3、request.setCharacterEncoding("UTF-8") 的作用是设置对客户端请求进行重新编码的编码。
4、response.setCharacterEncoding("UTF-8") 的作用是指定对服务器响应进行重新编码的编码。
对于发送数据,服务器按照 response.setCharacterEncoding—>contentType—>pageEncoding的优先顺序,对要发送的数据进行编码
对于接收数据,要分三种情况。一种是浏览器直接用URL提交的数据,另外两种是用表单的GET和POST方式提交的数据。
对于表单中POST方式提交的数据,只要在接收数据的JSP中正确 request.setCharacterEncoding 参数,即将对客户端请求进行重新编码的编码设置成浏览器编码,就可以保证得到的参数编码正确。
那如何得到浏览器编码呢?上面我们提过了,在默认请情况下,浏览器编码就是你在响应该请求的JSP页面中response.setCharacterEncoding设置的值。
所以对于POST表单提交的数据,在获得数据的JSP页面中 request.setCharacterEncoding 要和生成提交该表单的JSP页面的 response.setCharacterEncoding设置成相同的值。
对于URL提交的数据和表单中GET方式提交的数据,在接收数据的JSP中设置 request.setCharacterEncoding 参数是不行的,
因为在Tomcat5.0中,默认情况下使用 ISO- 8859-1 对 URL 提交的数据和表单中 GET 方式提交的数据进行重新编码(解码),而不使用该参数对URL提交的数据和表单中GET方式提交的数据进行重新编码(解码)。
要解决该问题,应该在Tomcat的配置文件的 Connector 标签中设置 useBodyEncodingForURI 或者 URIEncoding 属性,
其中useBodyEncodingForURI参数表示是否用 request.setCharacterEncoding 参数对URL提交的数据和表单中GET方式提交的数据进行重新编码,在默认情况下,该参数为false(Tomcat4.0中该参数默认为true)
URIEncoding 参数指定对所有 GET 方式请求(包括URL提交的数据和表单中GET方式提交的数据)进行统一的重新编码(解码)的编码。
URIEncoding 和 useBodyEncodingForURI 区别是,URIEncoding是对所有GET方式的请求的数据进行统一的重新编码(解码),
而 useBodyEncodingForURI 则是根据响应该请求的页面的 request.setCharacterEncoding 参数对数据进行的重新编码(解码),不同的页面可以有不同的重新编码(解码)的编码。
所以对于URL提交的数据和表单中GET方式提交的数据,可以修改 URIEncoding 参数为浏览器编码或者修改u seBodyEncodingForURI 为true,并且在获得数据的JSP页面中 request.setCharacterEncoding参数设置成浏览器编码。