[JavaWeb教程]第三章-Servlet开发
前面我们介绍到了form表单,其中action属性是把表单数据提交的路径,那么数据在服务器端是怎么处理的呢?我们一起来学习一下java servlet开发实现数据在服务器端的处理。
servlet是程序必须运行在java web服务器中,主要有tomcat, jboss,jetty中,这里我们使用比较常用的tomcat作为java web服务器。下面简单介绍一下tomcat的安装:
1、tomcat下载:http://pan.baidu.com/s/1mho8L1u
2、找一个合适的目录把下载的文件解压就好了,比如我的就是在:”D:\Program Files”,目录为“apache-tomcat-8.0.21”
3、与eclipse集成:windows->preferences->Server->Runtime Environment
选中Apache-Apache Tomcat 8.0 然后Next
4、运行web工程
在项目上点击右键Run As - Run On Server-Apache- tomcat v8.0 Server
Next->Finish
5、通过浏览器查看前面开发的界面
http://localhost:8080/learntestweb/helloworld.html
在浏览器中显示了”Hello World!”,查看本机的ip,把localhost替换成本机ip在局域网内也可以访问的。
这里的”learntestweb”是站点路径,后面的是链接路径。
上面的访问虽然通过浏览器访问服务器路径获取的页面,但是仍然是静态页面,下面我们一起使用servlet输出”当前时间+hello world”。
新创建类com.sunhaojie.learntestweb.web.HelloWorldServlet
publicclassHelloWorldServlet extendsHttpServlet { @Override publicvoiddoGet(HttpServletRequest req, HttpServletResponse resp) throwsServletException, IOException { doPost(req, resp); } @Override publicvoiddoPost(HttpServletRequest req, HttpServletResponse resp) throwsServletException, IOException { DateFormat dateFormat = newSimpleDateFormat("yyyy-MM-dd HH:mm:SS"); Date curDate = newDate(); String curDateStr = dateFormat.format(curDate); String helloWorld = curDateStr + " : hello world!"; resp.getWriter().println(helloWorld); } }
其中doGet和doPost就是对应了form提交方法中的get和post方法。
“resp. getWriter()”获取输出流,println把数据输出到客户端,这里不用调用输出流的close方法。
在web.xml中添加配置
[pre lang=”xml”]
<servlet>
<servlet-class>com.sunhaojie.learntestweb.web.HelloWorldServlet</servlet-class>
<servlet-name>helloWorld</servlet-name>
</servlet>
<servlet-mapping>
<servlet-name>helloWorld</servlet-name>
<url-pattern>/helloWorld</url-pattern>
</servlet-mapping>
[/pre]
这个配置是把url路径映射到类上,这里是把路径“/helloWorld”映射到”com.sunhaojie.learntestweb.web.HelloWorldServlet”上。
我们使用上一章的学生信息表,把学生信息提交到服务器端(因为上传文件比较复杂,并且不常用,这里先不介绍了)。把form.html复制为studentForm.html,然后把file表单删除,并修改action=“/learntestweb/submitStudentInfo”,在web.xml添加submitStudentInfo路径的映射
[pre lang=”xml”]
<servlet>
<servlet-class>com.sunhaojie.learntestweb.web.SubmitStudentInfoServlet</servlet-class>
<servlet-name>submitStudentInfo</servlet-name>
</servlet>
<servlet-mapping>
<servlet-name>submitStudentInfo</servlet-name>
<url-pattern>/submitStudentInfo</url-pattern>
</servlet-mapping>
[/pre]
创建SubmitStudentInfoServlet类,把提交的信息复制给StudentVo类,并保存。
代码如下:
publicclassStudentVo { privateString name; privateString sex; privateString year; privateString month; privateString day; privateString[] hobbys; privateString password; privateString info; } publicclassSubmitStudentInfoServlet extendsHttpServlet { @Override protectedvoiddoGet(HttpServletRequest req, HttpServletResponse resp) throwsServletException, IOException { doPost(req, resp); } @SuppressWarnings("unchecked") @Override protectedvoiddoPost(HttpServletRequest req, HttpServletResponse resp) throwsServletException, IOException { req.setCharacterEncoding("UTF-8"); String name = req.getParameter("name"); String sex = req.getParameter("sex"); String year = req.getParameter("year"); String month = req.getParameter("month"); String day = req.getParameter("day"); String[] hobbys = req.getParameterValues("hobby"); String password = req.getParameter("password"); String info = req.getParameter("info"); StudentVo studentVo = newStudentVo(); studentVo.setName(name); studentVo.setSex(sex); studentVo.setYear(year); studentVo.setMonth(month); studentVo.setDay(day); studentVo.setHobbys(hobbys); studentVo.setPassword(password); studentVo.setInfo(info); List<StudentVo> studentVoList = (List<StudentVo>) req.getSession().getAttribute("studentList"); if(studentVoList == null) { studentVoList = newArrayList<StudentVo>(); req.getSession().setAttribute("studentList", studentVoList); } studentVoList.add(studentVo); resp.setContentType("text/html; charset=UTF-8"); resp.getWriter().print(("当前学生信息总数为:"+ studentVoList.size())); } }
知识点:
1、req.setCharacterEncoding(“UTF-8”);设置入参编码方式,为了处理中文乱码。
2、req.getParameter(“xxx”),获取key为xxx的参数值,这里是form表单中name属性为xxx的值
3、req.getParameterValues(“xxx”),获取key为xxx的参数值数组,用于key相同的多值传输数据。
4、req.getSession(). getAttribute(“xxx”);获取回话session中的属性xxx的值,我们后面再看一下session。
还有一个setAttribute是为session的属性赋值。
5、resp.setContentType设置内容类型,这里为了处理中文乱码问题。
大家多次提交发现学生信息的总数再添加,那么我们使用一个另外的浏览器再次访问(或者关掉当前浏览器,重新打开)发现学生信息数从0开始了。我们提交到同一个服务器,数据应该都在浏览器直接共享才是我们要的效果,否则提交到服务器端没有意义啦。下面我们修改一下功能:
List<StudentVo> studentVoList = (List<StudentVo>) req.getServletContext().getAttribute("studentList"); if(studentVoList == null) { studentVoList = newArrayList<StudentVo>(); req.getServletContext().setAttribute("studentList", studentVoList); }
把getSession替换成getServletContext,重启服务,不同的浏览器提交学生信息个数都在增加。
下面我们来普及几个概念:
request,请求,前面我们学习Socket时,讲到了socket有一个输入流,一个输出流,用于客户端和服务器端之间通信。这里的request就可以理解为输入流的封装,实现了客户端和服务器端的http交互。
response,应答,输出流的封装。
session,每次点击,提交数据都是一次交互,客户端(这里可以理解为浏览器)和服务器端的一段时间内的全部的交互称为回话(session),session有过期时间,两次请求超出了服务器设置(可变更)的session过期时间,第二次请求就会创建新的回话。
cookie,客户端按照域名存储的键值对信息,可以持久化到硬盘。键值对中有一个key sessionId(也可以变更,但是作用类似)是实现session的关键数据。当客户端访问服务器端时,服务器端会查看是否存在sessionId如果存在,则会把本次请求和session关联,如果不存在则创建新的session,并把sessionId赋值给请求的cookie,客户端会把cookie信息在本地保存。大部分的sessionId的cookie信息时内存存储,没有持久化到硬盘,所以重启浏览器会导致创建新的session。
servletContext,实例容器,每个web服务器存在一个servletContext,启动时创建,关闭时销毁,所以我们重启服务后学生信息个数被清空。
我们如果想查看已经提交的学生信息,使用输出流打印一个页面,字符串的拼接太复杂了,所以我们引入一个模板引擎velocity可以更方便的生成页面信息。
添加velocity模板支持,在工程的WEB-INFO下的lib目录(如果不存在,则新建lib目录)中添加以下jar包。
http://pan.baidu.com/s/1eQOwYQ2 velocity-tools-2.0.jar
http://pan.baidu.com/s/1mhfLNz6 velocity-1.7.jar
http://pan.baidu.com/s/1o6P2BJs commons-logging-1.1.jar
http://pan.baidu.com/s/1geqLub5 commons-lang-2.2.jar
http://pan.baidu.com/s/1boiMc0n commons-digester-1.8.jar
http://pan.baidu.com/s/1sk5tVTb commons-collections-3.2.jar
http://pan.baidu.com/s/1i4lX8Nz commons-beanutils-1.7.0.jar
在WEB-INFO下创建文件velocity.properties,内容为:
[pre lang=”xml”]
resource.loader = webapp
webapp.resource.loader.class = org.apache.velocity.tools.view.servlet.WebappLoader
webapp.resource.loader.path=/WEB-INF/vm/
input.encoding=utf-8
output.encoding=utf-8
[/pre]
创建业务处理类StudentListServlet
publicclassStudentListServlet extendsVelocityViewServlet { @Override protectedTemplate handleRequest(HttpServletRequest request, HttpServletResponse response, Context ctx) { List<StudentVo> studentList = (List<StudentVo>) request.getServletContext().getAttribute("studentList"); ctx.put("studentList", studentList); returngetTemplate("studentList.vm"); } }
这里注意继承的是velocity提供的Servlet基类,其中Context.put(“key”, value);表示在模板中可以获取的数据,key为第一个入参。
创建vm模板页面studentList.vm 用于展示学生信息列表
[pre lang=”xml”]
<!DOCTYPE html>
<html>
<head>
<meta charset=”UTF-8″>
<title>学生信息列表</title>
</head>
<body>
<div align=”center”>
<h2>学生信息表</h2>
<table border=”1″ width=”50%”>
<tr>
<th width=”10%”>姓名</th>
<th width=”10%”>性别</th>
<th width=”10%”>生日</th>
<th width=”15%”>爱好</th>
<th width=”15%”>初始密码</th>
<th width=”45%”>自我介绍</th>
</tr>
#foreach( $item in $studentList)
<tr>
<td>$item.name</td>
<td>
#if(“male” == $item.sex)
男
#elseif(“female” == $item.sex)
女
#else
未知
#end
</td>
<td>${item.year}-${item.getMonth()}-${item.day}</td>
<td>
#foreach( $h in $item.hobbys)
$h
#end
</td>
<td>$item.password</td>
<td>$item.info</td>
</tr>
#end
</table>
</div>
</body>
</html>
[/pre]
1、$xxxx或者${xxxx}获取在Context.put的数据,xxxx为第一个入参的值。
2、${xxxx.yyy}获取xxxx对象中的yyy属性,我们也可以使用${xxxx.get()}调用方法获取。
3、foreach方法,foreach( $item in $studentList)遍历集合studentList,$item表示一个元素。结尾使用#end
4、ifelse,分支流程控制,#end结尾
web.xml配置
[pre lang=”xml”]
<servlet>
<servlet-name>StudentListServlet</servlet-name>
<servlet-class>com.sunhaojie.learntestweb.web.StudentListServlet</servlet-class>
<init-param>
<param-name>org.apache.velocity.properties</param-name>
<param-value>/WEB-INF/velocity.properties</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>StudentListServlet</servlet-name>
<url-pattern>/studentList</url-pattern>
</servlet-mapping>
[/pre]
init-param可以理解为构造函数的入参,获取vilocity配置。
浏览器访问:http://localhost:8080/learntestweb/studentList 可以展示出来服务器中保存的学生信息数据了。
页面端的入门开发基本讲完了,服务器端重启数据丢失的问题怎么解决呢?
小练习:
开发学生信息编辑功能,已注册的用户可以更新信息。
以下是工程中使用的代码:
web.xml
[pre lang=”xml”]
<!DOCTYPE web-app PUBLIC
“-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN”
“http://java.sun.com/dtd/web-app_2_3.dtd” >
<web-app>
<display-name>learntestweb</display-name>
<servlet>
<servlet-class>com.sunhaojie.learntestweb.web.HelloWorldServlet</servlet-class>
<servlet-name>helloWorld</servlet-name>
</servlet>
<servlet-mapping>
<servlet-name>helloWorld</servlet-name>
<url-pattern>/helloWorld</url-pattern>
</servlet-mapping>
<servlet>
<servlet-class>com.sunhaojie.learntestweb.web.SubmitStudentInfoServlet</servlet-class>
<servlet-name>submitStudentInfo</servlet-name>
</servlet>
<servlet-mapping>
<servlet-name>submitStudentInfo</servlet-name>
<url-pattern>/submitStudentInfo</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>StudentListServlet</servlet-name>
<servlet-class>com.sunhaojie.learntestweb.web.StudentListServlet</servlet-class>
<init-param>
<param-name>org.apache.velocity.properties</param-name>
<param-value>/WEB-INF/velocity.properties</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>StudentListServlet</servlet-name>
<url-pattern>/studentList</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>helloworld.html</welcome-file>
</welcome-file-list>
</web-app>
[/pre]
velocity.properties:
[pre lang=”xml”]
resource.loader = webapp
webapp.resource.loader.class = org.apache.velocity.tools.view.servlet.WebappLoader
webapp.resource.loader.path=/WEB-INF/vm/
input.encoding=utf-8
output.encoding=utf-8
[/pre]
studentForm.html
[pre lang=”html”]
<!DOCTYPE html>
<html>
<head>
<meta charset=”UTF-8″>
<title>学生信息录入表单</title>
</head>
<body>
<div align=”center”>
<h1>学生信息提交</h1>
<form action=”/learntestweb/submitStudentInfo” method=”post”>
<table border=”1″>
<tr>
<td align=”right” width=”30%”><label for=”nameTextId”>姓名:</label></td>
<td align=”left”><input type=”text” name=”name” id=”nameTextId”/></td>
</tr>
<tr>
<td align=”right”><label>性别:</label></td>
<td align=”left”><input type=”radio” name=”sex” value=”male” /> 男 <input type=”radio” name=”sex” value=”female” /> 女 </td>
</tr>
<tr>
<td align=”right”><label>出生日期:</label></td>
<td align=”left”>
<select name=”year”>
<option selected=”selected”>—-年—-</option>
<option >1990</option>
<option >1991</option>
<option >1992</option>
<option >1993</option>
<option >1994</option>
</select>
<select name=”month”>
<option selected=”selected”>—-月—-</option>
<option >01</option>
<option >02</option>
<option >03</option>
<option >04</option>
<option >05</option>
<option >06</option>
<option >07</option>
<option >08</option>
<option >09</option>
<option >10</option>
<option >11</option>
<option >12</option>
</select>
<select name=”day”>
<option selected=”selected”>—-日—-</option>
<option >01</option>
<option >02</option>
<option >03</option>
<option >04</option>
<option >05</option>
<option >06</option>
<option >07</option>
<option >08</option>
<option >09</option>
<option >10</option>
<option >11</option>
<option >12</option>
<option >13</option>
<option >14</option>
<option >15</option>
<option >16</option>
<option >17</option>
<option >18</option>
<option >19</option>
<option >20</option>
<option >21</option>
<option >22</option>
<option >23</option>
<option >24</option>
<option >25</option>
<option >26</option>
<option >27</option>
<option >28</option>
<option >29</option>
<option >30</option>
<option >31</option>
</select>
</td>
</tr>
<tr>
<td align=”right”><label>兴趣爱好:</label></td>
<td align=”left”>
<input type=”checkbox” name=”hobby” value=”basketball” />篮球
<input type=”checkbox” name=”hobby” value=”football” />足球
<input type=”checkbox” name=”hobby” value=”swim” />游泳
</td>
</tr>
<tr>
<td align=”right”><label>初始密码:</label></td>
<td align=”left”><input type=”password” name=”password”/></td>
</tr>
<tr>
<td align=”right”><label>自我介绍:</label></td>
<td align=”left”><textarea rows=”5″ cols=”20″ name=”info”></textarea></td>
</tr>
<tr>
<td align=”center” colspan=”2″>
<input type=”reset” value=”重置”/> <input type=”submit” value=”提交” /> <input type=”button” value=”按钮” />
</td>
</tr>
</table>
</form>
</div>
</body>
</html>
[/pre]
studentList.vm
[pre lang=”html”]
<!DOCTYPE html>
<html>
<head>
<meta charset=”UTF-8″>
<title>学生信息列表</title>
</head>
<body>
<div align=”center”>
<h2>学生信息表</h2>
<table border=”1″ width=”50%”>
<tr>
<th width=”10%”>姓名</th>
<th width=”10%”>性别</th>
<th width=”10%”>生日</th>
<th width=”15%”>爱好</th>
<th width=”15%”>初始密码</th>
<th width=”45%”>自我介绍</th>
</tr>
#foreach( $item in $studentList)
<tr>
<td>$item.name</td>
<td>
#if(“male” == $item.sex)
男
#elseif(“female” == $item.sex)
女
#else
未知
#end
</td>
<td>${item.year}-${item.month}-${item.day}</td>
<td>
#foreach( $h in $item.hobbys)
$h
#end
</td>
<td>$item.password</td>
<td>$item.info</td>
</tr>
#end
</table>
</div>
</body>
</html>
[/pre]
packagecom.sunhaojie.learntestweb.web; importjava.io.IOException; importjava.text.DateFormat; importjava.text.SimpleDateFormat; importjava.util.Date; importjavax.servlet.ServletException; importjavax.servlet.http.HttpServlet; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; /** * @ClassName HelloWorldServlet * @Description 输出当前时间和hello world的字符串 * * @author sunhaojie 3113751575@qq.com * @date 2016年2月23日 上午10:49:11 */ publicclassHelloWorldServlet extendsHttpServlet { @Override publicvoiddoGet(HttpServletRequest req, HttpServletResponse resp) throwsServletException, IOException { doPost(req, resp); } @Override publicvoiddoPost(HttpServletRequest req, HttpServletResponse resp) throwsServletException, IOException { DateFormat dateFormat = newSimpleDateFormat("yyyy-MM-dd HH:mm:SS"); Date curDate = newDate(); String curDateStr = dateFormat.format(curDate); String helloWorld = curDateStr + " : hello world!"; resp.getWriter().println(helloWorld); } } packagecom.sunhaojie.learntestweb.web; importjava.io.IOException; importjava.util.ArrayList; importjava.util.List; importjavax.servlet.ServletException; importjavax.servlet.http.HttpServlet; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; importcom.sunhaojie.learntestweb.vo.StudentVo; /** * @ClassName SubmitStudentInfoServlet * @Description 学生信息提交 * * @author sunhaojie 3113751575@qq.com * @date 2016年2月23日 下午2:02:08 */ publicclassSubmitStudentInfoServlet extendsHttpServlet { @Override protectedvoiddoGet(HttpServletRequest req, HttpServletResponse resp) throwsServletException, IOException { doPost(req, resp); } @SuppressWarnings("unchecked") @Override protectedvoiddoPost(HttpServletRequest req, HttpServletResponse resp) throwsServletException, IOException { req.setCharacterEncoding("UTF-8"); String name = req.getParameter("name"); String sex = req.getParameter("sex"); String year = req.getParameter("year"); String month = req.getParameter("month"); String day = req.getParameter("day"); String[] hobbys = req.getParameterValues("hobby"); String password = req.getParameter("password"); String info = req.getParameter("info"); System.out.println(name); StudentVo studentVo = newStudentVo(); studentVo.setName(name); studentVo.setSex(sex); studentVo.setYear(year); studentVo.setMonth(month); studentVo.setDay(day); studentVo.setHobbys(hobbys); studentVo.setPassword(password); studentVo.setInfo(info); List<StudentVo> studentVoList = (List<StudentVo>) req.getServletContext().getAttribute("studentList"); if(studentVoList == null) { studentVoList = newArrayList<StudentVo>(); req.getServletContext().setAttribute("studentList", studentVoList); } studentVoList.add(studentVo); resp.setContentType("text/html; charset=UTF-8"); resp.getWriter().print(("当前学生信息总数为:"+ studentVoList.size())); } } packagecom.sunhaojie.learntestweb.web; importjava.util.List; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; importorg.apache.velocity.Template; importorg.apache.velocity.context.Context; importorg.apache.velocity.tools.view.VelocityViewServlet; importcom.sunhaojie.learntestweb.vo.StudentVo; /** * @ClassName StudentListServlet * @Description 学生信息列表 * * @author sunhaojie 3113751575@qq.com * @date 2016年2月23日 下午4:33:28 */ publicclassStudentListServlet extendsVelocityViewServlet { @Override protectedTemplate handleRequest(HttpServletRequest request, HttpServletResponse response, Context ctx) { List<StudentVo> studentList = (List<StudentVo>) request.getServletContext().getAttribute("studentList"); ctx.put("studentList", studentList); returngetTemplate("studentList.vm"); } }
建议继续学习:
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:sunhaojie 来源: 孙豪杰的博客
- 标签: JavaWeb教程 Servlet
- 发布时间:2016-03-07 23:37:40
- [71] Twitter/微博客的学习摘要
- [65] find命令的一点注意事项
- [65] IOS安全–浅谈关于IOS加固的几种方法
- [63] android 开发入门
- [62] Go Reflect 性能
- [62] 如何拿下简短的域名
- [61] Oracle MTS模式下 进程地址与会话信
- [60] 流程管理与用户研究
- [57] 图书馆的世界纪录
- [57] 读书笔记-壹百度:百度十年千倍的29条法则