本章源码:Github
html版
html版本极其简单,顶部标题栏,左侧菜单栏,右侧具体内容。例如:
点击全体通知跳转到的nav.html网页:
<body>
<div id="head">
<img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="bank.png"" alt=" 山南银行">
山南银行讯息
</div>
<div id="left">
<ul>
<li><a href="nav.html">全体通知</a></li>
<li><a href="company.html">公司业务</a></li>
<li><a>个人业务</a></li>
<li><a>文体活动</a></li>
</ul>
</div>
<div id="content">
<table>
<tr>
<td>2019-02-04 10:00</td>
<td>祝大家新春愉快</td>
</tr>
</table>
</div>
</body>
点击公司业务跳转到的company.html网页:
<body>
<div id="head">
<img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="bank.png"" alt=" 山南银行">
山南银行讯息
</div>
<div id="left">
<ul>
<li><a href="nav.html">全体通知</a></li>
<li><a href="company.html">公司业务</a></li>
<li><a>个人业务</a></li>
<li><a>文体活动</a></li>
</ul>
</div>
<div id="content">
<table>
<tr>
<td>2019-02-04 10:00</td>
<td>公司业务部今天晚上聚餐</td>
</tr>
</table>
</div>
</body>
html版的业务逻辑就是,点击菜单后,直接跳到另外一个网页,看似顶部标题栏和左侧菜单栏没有变化,实际上根本就不是一个网页了。只不过这几个网页顶部和左侧内容一模一样(仅替换了右侧内容区域的代码),显得好像没变而已。
Servlet第一版,这个版本有点傻
分析需求,其实很简单,就是点击全体通知菜单,显示全体通知内容;点击公司业务菜单,显示公司业务内容。
那就做2个Servlet就好了啊,分别输出这两种内容的网页。核心代码如下:(注意此处为了便于演示,CSS等代码没有列出,如果想看完整的请参考Github)
代码结构:
//全体通知页Servlet
@WebServlet("/NavServlet")
public class NavServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决上篇遗留的中文乱码问题
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
//输出全体通知页面内容
out.println("<body>" +
" <div id='head'>" +
" <img src='bank.png'' alt=' 山南银行'>" +
" 山南银行讯息" +
" </div>" +
" <div id='left'>" +
" <ul>" +
" <li><a href='/NoticeSite/NavServlet'>全体通知</a></li>" +
" <li><a href='/NoticeSite/CompanyServlet'>公司业务</a></li>" +
" <li><a>个人业务</a></li>" +
" <li><a>文体活动</a></li>" +
" </ul>" +
" </div>" +
" <div id='content'>" +
" <table>" +
" <tr>" +
" <td>2019-02-04 10:00</td>" +
" <td>祝大家新春愉快</td>" +
" </tr>" +
" </table>" +
" </div>" +
"</body>");
}
}
//公司通知页Servlet
@WebServlet("/CompanyServlet")
public class CompanyServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决上篇遗留的中文乱码问题
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
//输出全体通知页面内容
out.println("<body>" +
" <div id='head'>" +
" <img src='bank.png'' alt=' 山南银行'>" +
" 山南银行讯息" +
" </div>" +
" <div id='left'>" +
" <ul>" +
" <li><a href='/NoticeSite/NavServlet'>全体通知</a></li>" +
" <li><a href='/NoticeSite/CompanyServlet'>公司业务</a></li>" +
" <li><a>个人业务</a></li>" +
" <li><a>文体活动</a></li>" +
" </ul>" +
" </div>" +
" <div id='content'>" +
" <table>" +
" <tr>" +
" <td>2019-02-04 10:00</td>" +
" <td>公司业务部今天晚上聚餐</td>" +
" </tr>" +
" </table>" +
" </div>" +
"</body>");
}
}
这两段代码需要注意几点:
- 因为网页要作为字符串输出,而字符串需要用双引号包裹,恰好网页中也有需要用到双引号。为了区分双引号是表示字符串开始结束标记还是真实的字符串内容,需要使用转义字符。上面的代码为了简单,直接将表示实际内容的双引号转换为了单引号,因为html一样可以识别单引号。这样的好处是代码看起来比较干净整洁,不信你用转义字符试试,绝对丑爆了。
- 注意
<a href='/NoticeSite/NavServlet'>全体通知</a>
,表示点击这个超级链接跳转到/NoticeSite/NavServlet
,其中NoticeSite是项目名,NavServlet是Servlet访问名,所以点击该超链接就跳转到NavServlet动态生成的网页了。同理点击公司业务就会跳转到CompanyServlet生成网页。
这个代码看起来很傻,因为重复的代码实在太多,相比html也没看到任何好处?臃肿的代码,着实令人心碎。
Servlet第二版 对重复代码进行封装
经过分析就可以发现一个问题,实际上这两个网页绝大多数内容都是相同的,只不过是内容部分不同罢了。
所以我们可以定义一个静态字符串保存相同部分的内容,然后每次只需要替换掉内容不同的部分就是了。
此处需要注意因为静态字符串全局共享,实际上是内存中独立的一个空间,在任何类中访问它都是访问的同一个内容。
代码结构:
HtmlData类用来保存网页模板字符串,需要注意我们用 @content 作为占位符,占据了各个网页内容不同的部分。
package com.maoge.notice.version2;
//用来保存Html模板
public class HtmlData {
public static String template=
"<!--导航页,作者:毛哥-->" +
"<html>" +
"<head>" +
" <meta http-equiv='Content-Type' content='text/html;charset=UTF-8' />" +
" <title>山南银行讯息</title>" +
" <style>" +
" /* 星号表示全部 */" +
" * {" +
" margin: 0;" +
" /*外边距为0*/" +
" padding: 0;" +
" /*内边距为0*/" +
" }" +
" #head {" +
" background: linear-gradient(to right, #FFFFFF, #D0E1FF);" +
" height: 64px;" +
" line-height: 64px;" +
" /*通过设置line-height等于height实现文字垂直居中*/" +
" color: #247398;" +
" /*头部文本颜色*/" +
" }" +
" #head img {" +
" vertical-align: middle;" +
" /*图片垂直居中*/" +
" height: 48px;" +
" }" +
" #left {" +
" width: 186px;" +
" float: left;" +
" /*靠左浮动*/" +
" height: 100%;" +
" /*高度铺满浏览器*/" +
" border: 4px solid #89B5E9;" +
" /*边框,颜色是取色器取得哦*/" +
" background-color: #EAF0F6;" +
" /*背景,颜色是取色器取得哦*/" +
" border-radius: 12px;" +
" /*圆角边框*/" +
" padding-left: 8px;" +
" /*设置左侧内边距*/" +
" color: #247398;" +
" /*字体颜色*/" +
" font-size: 1.3em;" +
" /*字体大小*/" +
" font-family: 'STKaiti';" +
" /*百度找了一种楷体*/" +
" }" +
" #left ul li" +
"" +
" /*设置列表项样式*/" +
" {" +
" margin-top: 12px;" +
" /*列表项的上边距*/" +
" }" +
" #content table{" +
" margin-top:24px;" +
" margin-left:224px;/*注意此处因为左侧浮动,设置的是到窗口左边沿的宽度*/" +
" }" +
" #content table tr{" +
" height:48px;" +
" }" +
" " +
" </style>" +
"</head>" +
"<body>" +
" <div id='head'>" +
" <img src='bank.png'' alt=' 山南银行'>" +
" 山南银行讯息" +
" </div>" +
" <div id='left'>" +
" <ul>" +
" <li><a href='/NoticeSite/NavServlet2'>全体通知</a></li>" +
" <li><a href='/NoticeSite/CompanyServlet2'>公司业务</a></li>" +
" <li><a>个人业务</a></li>" +
" <li><a>文体活动</a></li>" +
" </ul>" +
" </div>" +
" <div id='content'>" +
" @content"+
" </div>" +
"</body>" +
"</html>";
}
然后各Servlet只需要把占位符替换为各自想要展示的内容即可:
//全体通知页Servlet
@WebServlet("/NavServlet2")
public class NavServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决上篇遗留的中文乱码问题
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
//本页内容
String myContent=
" <table>" +
" <tr>" +
" <td>2019-02-04 10:00</td>" +
" <td>祝大家新春愉快</td>" +
" </tr>" +
" </table>";
//替换模板字符串占位符为本页内容
String html=HtmlData.template.replace("@content", myContent);
out.println(html);
}
}
//公司通知页Servlet
@WebServlet("/CompanyServlet2")
public class CompanyServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决上篇遗留的中文乱码问题
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
//本页内容
String myContent=
" <table>" +
" <tr>" +
" <td>2019-02-04 10:00</td>" +
" <td>公司业务部今天晚上聚餐</td>" +
" </tr>" +
" </table>";
//替换模板字符串占位符为本页内容
String html=HtmlData.template.replace("@content", myContent);
out.println(html);
}
}
第二版依然需要注意一些问题:
- 因为已经有访问路径
/NavServlet
和/CompanyServlet
,所以第二版的Servlet访问路径改为/NavServlet2
和/CompanyServlet2
。如果重复了服务器就不知道该让哪个Servlet响应了。 - 类名重复无所谓,以为包名不同。
OK,这个版本才开始有点动态网页的意思,起码不像之前html版本有大量重复的代码了。
毛哥想起很久以前听过一个代码设计基本原则,那就是消灭重复,因为重复的代码不好维护啊。举个最简单的例子,如果要修改顶部标题栏的字体颜色,在html版本时就要逐一修改每个html页面,而现在的Servlet版本只需要修改HtmlData中的模板就好了啦。
共同学习,写下你的评论
评论加载中...
作者其他优质文章