javawebservlet4-1教学(javaservlet书籍)

生活常识 2023-05-15 19:38生活常识www.xinxueguanw.cn

大兴机场cz8859在第几航站楼 Java Web轻松学36 - 第二个Servlet应用租房网(1)

本系列文章旨在记录和总结自己在Java Web开发之路上的知识点、经验、问题和思考,希望能帮助更多(Java)码农和想成为(Java)码农的人。

目录

介绍开发环境搭建项目总体设计登录页面login.htmlLoginServletHouseServlet中文乱码问题

介绍

还记得我们最早的之一个Servlet应用吗?它实在是有点low了。前面两篇文章我总结了一下自己对Servlet核心原理以及Servlet主要接口的心得体会,本篇文章就使用Servlet技术来做一个有实际意义一点的例子。

开发环境搭建

至于JDK、Eclipse、Tomcat的下载和安装,就不多说了。

然后是在Eclipse中新建Java Web工程以及配置Servlet API库等,可以参考这篇文章。

我比较关注租房中介这一个行业,就做一个租房网吧,项目名就叫house-renter吧。

新建好的工程如下图:

我们的Web应用的上下文根路径是默认的:house-renter

项目总体设计

首先,租房网要有一个用户登录界面,这个界面对所有用户来说都是一样的,所以可以做成静态页面,我们就命名该页面为login.html吧。

然后,用户登录请求需要设计一个Servlet来专门处理,就命名该Servlet为LoginServlet吧(或许也可以叫UserServlet,抑或AccountServlet等等,随你喜欢了)。

用户登录之后,后台系统对该用户进行大数据分析画像、人工智能推荐(总之是采用各种高精尖的前沿技术啦,就这么一说,反正真正的系统是包含这些的,我们这就没有了)、精准匹配到该用户感兴趣的房源,把它们展现给该用户。于是需要一个房源列表页面,但该页面是动态的,即每个用户都有自己感兴趣的房源。所以,我们也需要设计一个Servlet来动态生成该页面,就命名该Servlet为HouseServlet吧。

该用户浏览自己感兴趣的房源列表,可以点击某房源,展示其详细信息,即我们要一个房源详细信息页面。暂时也让HouseServlet来动态生成吧,毕竟是跟房子有关的,以后觉得有问题再逐步优化。

最后,为了演示,我们在房源详细信息页面中增加一个编辑按钮,这样,后台维护人员可以编辑我们的房源详细信息。当然,这样的操作并不是所有用户都有权限执行的,所以需要用户的操作权限认证,不过,我们暂且不实现这个功能。这样,我们还需要房源详细信息的编辑页面以及编辑的提交请求需要处理,暂时也让HouseServlet来动态生成吧,毕竟还是跟房子有关。

然后,我们把房源信息保存在House这个实体类中,即我们需要:

静态页面:login.htmlServlet:LoginServlet、HouseServlet实体类:House

登录页面login.html

我们可以使用Eclipse的New工具建立HTML文件,这样高效很多,当然也可以建立空白文件然后手动敲所有代码。

lt!DOCTYPE htmlgtlthtmlgtltheadgtltmeta charset=\"UTF-8\"gtlttitlegt租房网 - 登录lt/titlegtlt/headgtltbodygt ltform action=\"login.servlet\" method=\"post\"gt ltlabel for=\"user_name\"gt用户名:lt/labelgtltinput type=\"text\" id=\"user_name\" name=\"userName\" /gt ltlabel for=\"password\"gt密码:lt/labelgtltinput type=\"password\" id=\"password\" name=\"password\" /gt ltinput type=\"submit\" value=\"登录\" /gt lt/formgtlt/bodygtlt/htmlgt

我是使用Eclipse的New工具生成HTML 5模板的文件,除了lttitlegt标签和ltbodygt标签的内容作了修改,其他都没有变。

登录页面很简单,就是一个表单,关于HTML的基本知识,参考这篇文章。

将登录页面放在WebContent节点下,这样我们的Web应用可以直接访问到。需要关注的是这个表单提交的路径是login.servlet,这就意味着我们需要将LoginServlet配置成映射到的相对URL为“/login.servlet”。当然,现在我们这个LoginServlet还不存在,因此登录会出错。

在Eclipse中Publish该应用到Tomcat中,并启动Tomcat,然后使用浏览器访问:http://localhost:8080/house-renter/login.html

输入用户名和密码,或者不输入,直接点击登录,提示出错找不到/house-renter/login.servlet对应的展示:

LoginServlet

我们也可以使用Eclipse的New工具直接新建一个Servlet,我把无用的代码删除,并添加登录的业务逻辑之后是这样的:

package houserenter.servletimport java.io.IOExceptionimport javax.servlet.ServletExceptionimport javax.servlet.annotation.WebServletimport javax.servlet.http.HttpServletimport javax.servlet.http.HttpServletRequestimport javax.servlet.http.HttpServletResponse@WebServlet(\"/login.servlet\")public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String userName = request.getParameter(\"userName\") String password = request.getParameter(\"password\") //这里需要验证用户是否已经注册,省略 System.out.println(\"userName: \" + userName + \", password: \" + password) //用户登录成功,重定向到房源列表页面 response.sendRedirect(\"house.html?userName=\" + userName) }}

前面login.html页面中表单有用户名和密码两个参数,我们可以用HttpServletRequest的getParameter() *** 获取它们的值。这样我们就能拿它们来做验证了,如果系统数据库中有表示已经注册过,可以登录;反之则不予登录。

不过我这省略了验证这一步,将页面直接重定向到房源列表页面。关于重定向,我们后面再讨论,可以简单理解为,它会通知浏览器,让它从原来页面的基础上再重新访问新的页面,因此,浏览器地址栏中的地址会自动变成新页面的URL。

这里还需要关注的重要的一点就是:我重定向的新页面URL中是带有参数的,就是问号后面的userName这个参数。为什么要这样呢?这就是为了会话跟踪,因为HTTP协议本身是无状态的,它并不清楚各个请求之间有无关联,而现在我需要让房源列表页面的请求知道是哪一个用户的请求,从而该请求提交到HouseServlet的时候能查找该用户感兴趣的房源。当然,这只是会话跟踪的其中一种技术,由于是在URL上做文章,因此它被称作URL重写

我们现在在Eclipse中重新发布应用并启动Tomcat(实际上可以不用停止Tomcat,Eclipse中只要保存修改,就会自动重新编译并发布应用),像上面那样登录之后,浏览器中提示:

现在提示的是找不到/house-renter/house.html对应的展示,不过浏览器地址栏却已经自动变成了:http://localhost:8080/house-renter/house.html?userName=a

Eclipse控制台中打印出了我们用来调试或者说是测试的日志:

HouseServlet

直接上代码:

package houserenter.servletimport java.io.IOExceptionimport java.io.PrintWriterimport javax.servlet.ServletExceptionimport javax.servlet.annotation.WebServletimport javax.servlet.http.HttpServletimport javax.servlet.http.HttpServletRequestimport javax.servlet.http.HttpServletResponse@WebServlet(\"/house.html\")public class HouseServlet extends HttpServlet { private static final long serialVersionUID = 1L protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String userName = request.getParameter(\"userName\") if (userName == null || userName.isEmpty()) { System.out.println(\"invalid user!\") response.sendRedirect(\"login.html\") } //查找该用户感兴趣的房源,这里省略 System.out.println(\"userName: \" + userName + \" access house.html!\") PrintWriter writer = response.getWriter() //因为我们要返回的是HTML页面 writer.println(\"lt!DOCTYPE htmlgt\") writer.println(\"lthtmlgt\") writer.println(\"ltheadgt\") writer.println(\"ltmeta charset=\\"UTF-8\\"gt\") writer.println(\"lttitlegt租房网lt/titlegt\") writer.println(\"lt/headgt\") writer.println(\"ltbodygt\") writer.println(\"lth1gt你好,\"+userName+\"!欢迎来到租房网! lta href=\\"login.html\\"gt退出lt/agtlt/h1gt\") writer.println(\"ltbrgtltbrgt\") writer.println(\"lth6gt共找到你感兴趣的房源2条lt/h6gt\") writer.println(\"lth2gtltagt大兴区金科嘉苑3-2-1201lt/agtlt/h2gt\") writer.println(\"lth2gtltagt大兴区万科橙9-1-501lt/agtlt/h2gt\") writer.println(\"lt/bodygt\") writer.println(\"lt/htmlgt\") } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response) }}

注意,这里我们配置HouseServlet的URL映射模式是“/house.html”,是与重定向的URL相匹配的。

前面重定向的URL中由于有了用户信息,所以请求分派到此URL中,我们就能得知是哪个用户要请求感兴趣的房源列表。事实上,这种技术来验证用户和跟踪会话实在是不安全,因为它会把数据暴露在URL上。

当然,我这里只是为简单起见而采用这种方式。接下来是如果URL中没有携带用户名,则视为尚未登录,从而重定向到登录页面。

我省略了查找该用户感兴趣的房源,直接HttpServletResponse的getWriter() *** 获取到填充响应内容的IO流,借助它就可以往响应填充HTML页面内容了。

现在在浏览器访问租房网,登录后显示:

虽然能重定向到房源列表页面了,但很不幸,出现了很多乱码,显然这是由于页面中包含中文,是由于字符集的问题引起的。

中文乱码问题

这里,我们重新捋一下导致中文乱码的几个节点:

首先,中文是直接写在代码里的,所以源代码文件(包括任何语言的,Java、HTML、JavaScript等)的存储采用的字符集是一个节点。其次,填充响应的Writer需要从源代码文件读取硬编码的中文字符,因此,它以什么字符集来读取(当然必须是与存储字符集一致才行,除非直接使用面向字节的IO流)又是一个节点。再次,浏览器端收到响应后,如果响应是基于字符的,那响应的报文是采用何种字符集的。这里分两种情况,一种就是Servlet容器直接读取静态资源(比如HTML),Servlet容器读取时采用的字符集就是响应报文的字符集;另一种是上面的Writer动态生成的资源,这时响应报文的字符集就是Writer采用的字符集。最后,浏览器采用何种字符集来解析响应报文。这里又分两种情况,一种是浏览器一般都有自己默认的字符集配置;另一种是响应报文中告诉浏览器该采用何种字符集,比如HTML中的标签ltmeta charset=\"UTF-8\"gt,或者HTTP首部Content-Type的值是\"text/htmlcharset=UTF-8\"。

好,根据这几个节点因素,我首先确认了自己的源代码文件的存储字符集是UTF-8的,返回的响应报文中已经使用ltmeta charset=\"UTF-8\"gt告诉浏览器要用UTF-8字符集来解析。

现在唯一还有疑问的就是响应报文本身是否就是UTF-8来发送的,通过百度查一下HttpServletResponse返回的Writer默认采用的字符集是ISO-8859-1。

所以我们应该在代码中修改Writer的编码格式为UTF-8:

response.setCharacterEncoding(\"UTF-8\")PrintWriter writer = response.getWriter()

好像还必须在getWriter() *** 之前设置字符集,否则没有效果,这就有点坑了,大家可以试试。

加了这句代码之后,效果如下:

嗯,还真有点像那么回事了,只不过界面丑陋了一点,不过这个可以使用前端三剑客中的CSS来解决。

大家还可以测试一下退出登录的按钮,以及直接在浏览器中手动输入URL“http://localhost:8080/house-renter/house.html”来访问房源列表的效果。

总结

现在租房网的基本雏形已经有了,还剩下房源详细信息页面、房源信息编辑还没有实现,这些留到下一篇文章再继续介绍,现在的工程结构是这样的:

静态页面也是还有用处的,并非所有页面都要动态生成;Servlet的业务职责要分开,比如我们设计了登录的和房源的两个Servlet;会话跟踪可以采用URL重写技术;页面跳转可以采用重定向技术;中文乱码问题都是字符集惹的祸,要考虑整个链条的所有节点,从源代码的存储格式,到工具(Tomcat或API库中的Writer)的读取、报文的传输格式,再到浏览器的配置或者资源告诉浏览器要采用何种字符集;一般Web中采用UTF-8。

javaservlet书籍 javaweb中servlet知识点

Copyright@2015-2025 www.xinxueguanw.cn 心血管健康网版板所有