技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> Java --> [JavaWeb教程]第三章-Servlet开发

[JavaWeb教程]第三章-Servlet开发

浏览:1544次  出处信息

前面我们介绍到了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

tomcat配置3

选中Apache-Apache Tomcat 8.0 然后Next

tomcat配置2

4、运行web工程
在项目上点击右键Run As - Run On Server-Apache- tomcat v8.0 Server

tomcat配置3

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&lt;StudentVo&gt; studentVoList = (List&lt;StudentVo&gt;) req.getSession().getAttribute("studentList");
        if(studentVoList == null) {
            studentVoList = newArrayList&lt;StudentVo&gt;();
            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&lt;StudentVo&gt; studentVoList = (List&lt;StudentVo&gt;) req.getServletContext().getAttribute("studentList");
if(studentVoList == null) {
    studentVoList = newArrayList&lt;StudentVo&gt;();
    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&lt;StudentVo&gt; studentList = (List&lt;StudentVo&gt;) 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&lt;StudentVo&gt; studentVoList = (List&lt;StudentVo&gt;) req.getServletContext().getAttribute("studentList");
        if(studentVoList == null) {
            studentVoList = newArrayList&lt;StudentVo&gt;();
            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&lt;StudentVo&gt; studentList = (List&lt;StudentVo&gt;) request.getServletContext().getAttribute("studentList");
        ctx.put("studentList", studentList);
        returngetTemplate("studentList.vm");
    }
}

建议继续学习:

  1. Servlet线程安全问题    (阅读:4260)
  2. [JavaWeb教程]第四章-java数据库开发    (阅读:1603)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1