缘由
以后改为写博客的方式是以阶段性的总结为主,要求至少保证每周一篇,因为之前我坚持了两个月每天一篇,觉得效果不太好。主要是因为如果每天一篇的就有为了发博客而发博客的嫌疑,而且之前学习非常松散,有时候连续几天的博客居然内容并不相关,那么就代表了我连续几天都在东搞一下西搞一下。自然是在浪费精力。所以以后要求
- 每一篇博客主要是连续几天的相关工作以及学习的总结。
- 不限定每周一篇,但是要求每个月至少四篇。
- 尽量发点有价值
上一周的学习
日期:5月1日至5月11日看了两本书:
- Java web 入门经典 王国辉 陈英编著 机械工业出版社:1-15章(借于图书馆)
- java web 典型模块与项目实现大全 常建功 编著 清华大学出版社: 第23章 在线音乐管理系统 (借于图书馆)
- Java web 入门经典 书薄,内容不详细,适合快速了解java web的知识,由于之前学过传智播客的视频,所以这本书的大部分内容都是知道的,只是再次巩固而已,实际证明光看书和视频还是不如自己写写代码的效果好。
- java web 典型模块与项目实现大全:我只看了一章,主要是我要利用它那个音乐网站的例子来学习,并以其构建我们自己的音乐网站,实际上他的例子我觉得并不是特别好,因为它代码都在一个包里,没有做到和很好的以模块功能划分java类。我的打算如果真的要深入学习的话,只要重做,这次先以其为基础随便改了改首页
除了如何使用js插件以外,另外一大部分就是java web的相关内容的总结:这一部分主要是理解几个术语和java web开发之间的关系。
java web总结
从socket讲起
对于一个java web,我只是想从我所知的范围的最基本的情况开始讲,那应该就是socket了。其实无论是B/S还是C/S,只要是网络通信少不了socket的。我相信大家都做过一个实验,至少在我的上过的计算机课中至少有三节课要求我们完成socket通信,无论是windows下的还是linux下的。我们常常在课上所做的就是将一个hello world从客户端发送至服务器端,然后服务器端再通过socket发送过客户端,两台主机就通过socket完成了通信,传输了数据。我倒不是再把socket的内容总结一遍,我只想说说socket与我们这个java web的关系。
这样又不得不说到B/S,因为java web作为B/S一种实现方式,我倒认为所有的B/S只是C/S的衍生而已。C代表的client,客户端,可以对应上面socket的客户端,而B/S中的B是浏览器:browser,它只是无数种client的一种,想想看,玩游戏的时候,我们都要下载游戏的客户端吧?那就是一种C/S的C,而browser也只是C/S的一种。所以在一个socket通信的过程中,浏览器就充当了socket的客户端,而socket服务端呢?其实就是用java web这一套技术来实现。因为上网的浏览器往往就那么几个,chrome或者Firefox,所以作为java web的开发一般是不需要去开发客户端(当然会去适配一下浏览器)。java web主要是指开发socket通信的服务端(准确的说是服务端要返回给客户端的内容)。其他类似的就是lamp和微软的asp.net。
html
在一次socket通信的过程中,我们可以从客户端发送hello world给服务端,也可以让服务端发回任意的字段给客户端。但是B/S系统中,我们发送的不是那么简单的内容。这是因为,我们的网页呈现的内容丰富、形式多彩,比如这个地方要插入一张图片或者一段音频,这个字体要大小,那个字体的颜色要红色。这就是需要一种协议,一种约定方式让客户端和服务器端都知道彼此的发送的内容具体是什么样子。举个例子:我们可以看到,上一幅图中是服务器端发送给客户端的一段内容,在实现的结果图中,也就是下一幅图,一段文字就会大一些。通过这样的约定方式就可以让浏览器实现多种多样,丰富多彩的数据。
此外,html的作用不止如此,比如服务器端那么多东西,服务端怎么知道要发送什么给客户端呢?当浏览器端和服务器端通信出错怎么办呢?所以,客户端首先需要依据html协议的要求,封装好自己要发送的数据,里面说清楚了自己要什么,再发送给服务器端,服务器端根据html协议来解析客户端发送过来的内容,服务器就知道了客户端要什么,再把客户端需要的内容根据html协议的要求封装好,再返回给客户端。
这里,一般我们称客户端发送给服务器端的内容叫 request
把服务端返回给客户端的内容叫作为 response
request与response都具有自己的头部,用于说明特定的信息。而一般来说response还有具有返回的内容(图1的部分),这一部分内容一般的都会在response的头部说明大小之类的信息。利用chrome的开发工具可以很容易查看这一部分信息,使用快捷键ctl+shift+j打开开发工具后,如下图点击的内容,即可查看request和response的相关信息:
解析html与Tomcat
实际上,解析html协议的是不属于java web开发的范畴的。以为java web属于应用层的开发,java web可以认为是开发 服务器端返回给客户端的内容!而解析客户端发来的html内容的部分是交给了Tomcat来完成的。Tomcat作为一个web服务器(另一个我比较熟悉的web服务器就是nginx)。当然除了html解析之外还有更多工作要做,比如说打开端口、建立socket连接之类的。另外,Tomcat是由java编程,运行于虚拟机之上的web服务器。对于java web开发和tomcat的联系有一个例子可以简单的理解:它们之类的关系,我们只需要把利用java web写好的页面放在tomcat的指定目录下,路径是:C:\apache-tomcat-6.0.39\webapps\test(显然这是和安装路径相关的,但是所有从webapps的目录是肯定有的),如下图所示:
结果我们就能在浏览器中访问到了:
再次对Tomcat作深入的理解的话,Tomcat是一个运行环境:
Tomcat是一个超市,那么test就是里面一瓶矿泉水,我们作为客户来到超市买水,超市有水就给了我们。下面还有类似的例子。
动态页面与js
通过html,确实是能够在客户端与服务端交流数据,比如一段文字,如上所示,我们称之为静态页面。随着技术的发展,人们发现这样看腻了,人们总是贪心,人们想要页面更漂亮,更炫。所以诞生了js(javascript,一种脚本语言):把静态页面转变成了支持用户交流并相应的应用事件的动态页面。举个例子来讲:
我们可以看到,当这个页面就略带动感,注意我强调是动感,主要是只鼠标放上去,相框会发生变化这个一个过程,而这个相框制作的也很漂亮(这一部分与css相关)。
对于该实例,如果我们去查看实现其的功能js的代码,就发现就是一堆类似于java、c语言这样的东西(很明显区别于html、css、xml这样有标记的语言),比如有{}、变量、if与else之类。这里是只是简单的说明一下其作用,具体其语法规则大家可以参考:http://www.w3school.com.cn/b.asp。
在我们的项目中,我们通常用一个文件夹存放所有的js文件,而在所需要的该js实现的功能的地方引入其js文件档,在目前看来每一个js文档都像是由一个或多个函数组成,然后供其他文档在合适的时候调用。
下图由一个文件夹存放所有的js文档:
看由js组成的函数,而且在期望的地方被调用:
从我们项目里面来看js的函数写的可不向上面的例子那么简单,其实是异常复杂的。有时候,js里面会使用到jquery,根据w3school的解释:
- jQuery 是一个 JavaScript 库。
- jQuery 极大地简化了 JavaScript 编程。
jsp与serlet
使用java web开发的时候,一般我们都不是去编写html页面(显然我们可以直接编写html页面,但是非常繁琐),我们一般编写的都是jsp页面,并且浏览器是可以直接访问到的。如下图所示,可以看到我们的项目中都以jsp为后缀的jsp页面。从w3school没有介绍jsp但是介绍了asp来看,jsp是用于java web技术中开发网站的技术,而根据w3school对asp的解释:ASP.NET 是一个开发框架,用于通过 HTML、CSS、JavaScript 以及服务器脚本来构建网页和网站。我们大概也能够揣测出jsp的意思。
从书上的解释来看,jsp是基于java的动态网页技术,在jsp页面内可以出现指令标示、html代码、javascrip代码、嵌入的java代码、注释和jsp动作标识。
我认为可以看成jsp基于java技术的网站开发的再一次封装,封装了什么?就是servlet。那servlet又是什么,servlet就是server+applet。也就是运行在服务器端的一个小程序,所谓运行在服务器端就是运行在tomcat这个环境里面的一个程序。Tomcat只是一个平台,web服务的,是为servlet和jsp的运行提供一个运行环境。Tomcat是一座酒店,那么servlet就是里面的厨师你要红烧肉,那么你需要把原料给能作红烧肉的厨师,然后厨师就会给你一盘红烧肉了。意思就是说tomcat只不过是一个平台,一个运行环境,servlet才是一个制作东西的应用程序。在实际的使用中,serlet是一个接口(java语法上的接口),一般我们直接继承其子类Httpservlet。可以简单看看servlet里面做了些什么事,如果我们使用eclipse快速建立一个servlet,整个类代码如下:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class servlet extends HttpServlet {
public servlet() {
super();
}
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out
.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
out.println("<HTML>");
out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>");
out.println(" <BODY>");
out.print(" This is ");
out.print(this.getClass());
out.println(", using the GET method");
out.println(" </BODY>");
out.println("</HTML>");
out.flush();
out.close();
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out
.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
out.println("<HTML>");
out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>");
out.println(" <BODY>");
out.print(" This is ");
out.print(this.getClass());
out.println(", using the POST method");
out.println(" </BODY>");
out.println("</HTML>");
out.flush();
out.close();
}
public void init() throws ServletException {
// Put your code here
}
}
此外,eclipse已经为我们默认在项目的\WebRoot\WEB-INF\web.xml配置了访问路径:
所以我们能够在浏览器中访问到它(注意我们访问的是一个java的类,而不是文件):
我们可以看到代码:
都是类似于:
PrintWriter out = response.getWriter();
out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>");
这样的形式,说简单了,out.println就是往那个客户端和服务器端连接的socket里面塞东西,out对象也是tomcat给我准备好了的,再仔细看我作为例子的那句的内容:<HEAD><TITLE>A Servlet</TITLE></HEAD>,明显就是html语言。所以,我们就通过了这个servlet将把原味的html语言发送了客户端浏览器,浏览器一解析,内容就出来。
既然servlet运行于tomcat上的一个程序,jsp又封装了servlet,请看下图:
可以看到jsp最后到会转变为servlet的类,以java代码的形式存在。作为证明,我们可以看到在以下面目录得到我作为
- C:\apache-tomcat-6.0.39\work\Catalina\localhost
javaBean的出现
上一节我们已经说了在一个jsp页面内可以出现好多的东西,比如:html,js,java等等,很显然html和js是作为在浏览器上显示内容的存在,但是java代码呢?主要是用于逻辑的处理等等,还有数据库的操控,因为很多要显示在浏览器的上的你都需要去数据库里面去取,但是这样,整个页面看起来就特别的混乱。所以由此产生了javaBean。
javaBean其实是对对象实体的属性的一次封装,一种遵循特定规则的java类,如代码所示,比如说一个用户注册,那么注册的时候,就需要填写用户名、密码和确认密码等信息。所以代码如下所示:注意每一个属性都必须要有get和set方法。
//com.default包下
public class NewUser {
private String userName = null;
private String userPwd = null;
private String confirmPwd = null;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPwd() {
return userPwd;
}
public void setUserPwd(String userPwd) {
this.userPwd = userPwd;
}
public String getConfirmPwd() {
return confirmPwd;
}
public void setConfirmPwd(String confirmPwd) {
this.confirmPwd = confirmPwd;
}
}
如此一来我们就可以使得在jsp页面里面没有了java代码的存在,当我们要一个新用户要注册的时候,其肯定是要传送信息给我们的,所以我们必须要在显示的register.jsp页面中制作一个表单:
....
<form action = "showRegister.jsp" method="post">
<ul>
<li>用户名:<input type="text" name = "userName"></li>
<li>密码:<input type="text" name = "userPwd"></li>
<li>确认密码:<input type="text" name = "confirmPwd"></li>
<li><input type="submit" name = "注册"></li>
</ul>
</form>
....
注意name属性要和javabeam里面的属性名一样,这样当跳转到showRegister.jsp页面的时候,我们就可以通过在showRegister.jsp页面写:
<jsp:useBean id="newUser" class="com.default.NewUser" scope="page">
<jsp:setProperty name="newUser" property="*">
</jsp:useBean>
我们可以得到一个NewUser的对象newUser,并且其属性全部都是由在第一个jsp页面中由用户填写的。
也可以通过
<jsp:getProperty property="userName" name="newUser">
获得对象newUser的属性userName的值
这样我们就在jsp页面里面没有写java代码了,主要就是利用jsp的标签。再次强调之所以这样做就是为了在jsp里面少用java代码。java代码作为编程语言稍微复杂一些,比起脚本语言而已。当然我们这样做可以方便的实现在一个页面输入的信息在另一个页面显示,如果要存入数据库就需要使用servlet了(也就是在register.jsp的跳转页面改为一个servlet,由servlet去处理)。但是实际开发中又不太会用到servlet,更用到更为方便的struts2。
jdbc与数据库
上面说到了访问数据,显然用户名、密码之类的,还有用户输入的信息,还有我们存放的歌曲都存放在了数据库。那么jdbc就是中java访问数据库的方式,JDBC是java程序与数据库通信的标准API。其实sun公司并没有实现jdbc,只是说了一套标准,然而要每一个数据库厂商自己去实现JDBC,方便让java开发者使用。所以无论是oracle还是mysql,都有各自的一套jdbc,是按照sun公司的要求实现的。如果要使用对应某个的数据的,一般访问数据库的流程如下所示: try {
// 加载数据库驱动,注册到驱动管理器
Class.forName("com.mysql.jdbc.Driver");
// 数据库连接字符串
String url = "jdbc:mysql://localhost:3306/test";
// 数据库用户名
String username = "root";
// 数据库密码
String password = "root";
// 创建Connection连接
Connection conn = DriverManager.getConnection(url,username,password);
// 添加图书信息的SQL语句
String sql = "insert into tb_book(name,price,bookCount,author) values(?,?,?,?)";
// 获取PreparedStatement
PreparedStatement ps = conn.prepareStatement(sql);
// 对SQL语句中的第1个参数赋值,这里是由于存在一个book的javabean,所以可以这样获得值
ps.setString(1, book.getName());
// 对SQL语句中的第2个参数赋值
ps.setDouble(2, book.getPrice());
// 对SQL语句中的第3个参数赋值
ps.setInt(3,book.getBookCount());
// 对SQL语句中的第4个参数赋值
ps.setString(4, book.getAuthor());
// 执行更新操作,返回所影响的行数
int row = ps.executeUpdate();
// 判断是否更新成功
if(row > 0){
// 更新成输出信息
out.print("成功添加了 " + row + "条数据!");
}
// 关闭PreparedStatement,释放资源
ps.close();
// 关闭Connection,释放资源
conn.close();
} catch (Exception e) {
out.print("图书信息添加失败!");
e.printStackTrace();
}
上面主要是展示一下如何在java代码中执行一条sql语句,实现上执行的方式是有很多种的,这只是一种方法执行一条sql语句的方式,但是这种方式是值得鼓励的,因为这样可以防止sql注入。
另一种主要的方式就是使用批处理方式具体代码如下:
/**
* 获取数据库连接
* @return Connection对象
*/
public Connection getConnection(){
// 数据库连接
Connection conn = null;
try {
// 加载数据库驱动,注册到驱动管理器
Class.forName("com.mysql.jdbc.Driver");
// 数据库连接字符串
String url = "jdbc:mysql://localhost:3306/db_database10";
// 数据库用户名
String username = "root";
// 数据库密码
String password = "111";
// 创建Connection连接
conn = DriverManager.getConnection(url,username,password);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
// 返回数据库连接
return conn;
}
/**
* 批量添加数据
* @return 所影响的行数
*/
public int saveBatch(){
// 行数
int row = 0 ;
// 获取数据库连接
Connection conn = getConnection();
try {
// 插入数据的SQL语句
String sql = "insert into tb_student_batch(id,name,sex,age) values(?,?,?,?)";
// 创建PreparedStatement
PreparedStatement ps = conn.prepareStatement(sql);
// 实例化Random
Random random = new Random();
// 循环添加数据
for (int i = 0; i < 10; i++) {
// 对SQL语句中的第1个参数赋值
ps.setInt(1, i+1);
// 对SQL语句中的第2个参数赋值
ps.setString(2, "学生" + i);
// 对SQL语句中的第3个参数赋值
ps.setBoolean(3, i % 2 == 0 ? true : false);
// 对SQL语句中的第4个参数赋值
ps.setInt(4, random.nextInt(5) + 10);
// 添加批处理命令
ps.addBatch();
}
// 执行批处理操作并返回计数组成的数组
int[] rows = ps.executeBatch();
// 对行数赋值
row = rows.length;
// 关闭PreparedStatement
ps.close();
// 关闭Connection
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
// 返回添加的行数
return row;
}
第二个方法就是利用批处理方式注入了10条代码。注意 ps.executeBatch()的返回值,如果全部命令执行成功,则返回更新计数组成的数组。
由于对JDBC的技术已经非常熟悉了,所以不算再反复说了。
Ajax
根据w3cshool的解释,我们先来看看什么是AJAX:AJAX = 异步 JavaScript 和 XML。AJAX 是一种用于创建快速动态网页的技术。
通过在后台与服务器进行少量数据交换,AJAX可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面。
我们可以通过w3school的例子来理解AJAX,不过里面主要讲解的都是get()和post()方法,书上还讲了load()的使用方法,这三个的使用方法相对都要简单一点。但是这里我想将一个在在线音乐管理系统中实现的例子,它使用的主要是$.ajax()是jquery中最底层的Ajax技术,比起post()方法和get(),其主要提供当请求返回失败的时候,调用页面应该如何处理,具体的代码如下。
<script type="text/javascript">
$(document).ready(function(){
dopage('index_ajax.jsp?page=1');
});
function dopage(ajaxurl){
$('#LoadingStatus').show();
$.ajax({url: ajaxurl,
type: 'GET',
dataType: 'html',
timeout: 30000,
async : false,
error: function(){$('#content').html('<table width="50%" border="0" align="center"> <tr> <td class="center_article" align="center">获取文章失败,请刷新此页面!!!</td></tr></table>');$('#LoadingStatus').hide(500);
},
success: function(html){
$('#LoadingStatus').hide(1000);
$('#content').html(html);
}
});
</script>
主要看到的是一个一段嵌入在index.jsp首页的代码,这段代码是去更新首页的歌曲部分。根据代码,当页面加载完成后开始运行$(document).ready(function(){ });函数(这是属于jquery的知识),那么接着又调用了下面的dopage函数,dopage函数又使用了$.ajax()的动态更新页面的方法。其中
- url: 请求的url
- type: 请求的类型
- dataType: 返回数据的类型
- timeout: 超时的时间
- async : 是否异步,如果是false的话,将会等待服务器返回后代码才继续往下执行
- error: 如果返回的是错误的页面的话,就执行这一段代码
- success: 如果返回的是成功的话,就执行这一段代码
$('#content').html(html);
.html()是一个方法,指按照html的格式解析参数。其中参数的html就是用$.ajax()请求返回的html格式的文件。
我们也可以将代码改成
$('#content').text(html);
结果对比如下:
struts2
想了半天如何讲,其实我的理解也不太深,所以我决定讲一个注册的例子。这只是使用struts2的一种。也就是这个音乐网站注册的流程。首先在首页存在一个这样的超链接:<a href="register.jsp?height=175&width=300&modal=true"class="thickbox" title="我要注册">我要注册</a>
<input type="submit" value="登 陆" />
所以当点击我要注册的时候,自然会跳转到register.jsp?height=175&width=300&modal=true界面,该界面也没有什么特殊的,也就是:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=utf-8">
<META content="MSHTML 6.00.2900.3157" name=GENERATOR>
</HEAD>
<BODY>
<DIV style="TEXT-ALIGN: center">
<form action="register.action" method="post">
<TABLE style="MARGIN: 0px auto" cellSpacing=3 cellPadding=3 border=0>
<TBODY>
<TR>
<TD colspan="2"><div align="center">用户注册</div></TD>
</TR>
<TR>
<TD> </TD>
<TD> </TD>
</TR>
<TR>
<TD><LABEL>用户名:</LABEL> </TD>
<TD><INPUT type="text" name="userName" maxlength="16"/></TD></TR>
<TR>
<TD><LABEL>用户密码:</LABEL> </TD>
<TD><INPUT type="password" name="userPwd" maxlength="16"/></TD>
</TR>
<TR>
<TD><LABEL>确认密码:</LABEL> </TD>
<TD><INPUT type="password" name="confirmPwd" maxlength="16"/></TD></TR>
<TR align=right>
<TD colSpan=2> </TD>
</TR>
<TR align=right>
<TD colSpan=2><div align="center">
<INPUT id=Login type=submit value="注 册">
<INPUT type="reset" οnclick=tb_remove() value="取 消" />
</div></TD></TR></TBODY></TABLE>
</form></DIV></BODY></HTML>
唯一一个值得注意的地方就是,这个表单<form action="register.action" method="post">的action部分,其中register.action就表示的是涉及到了struts2的机制。其中这个register.action的后缀指明了一个可以进行业务处理的地方(有点像servlet),具体处理的方法写在一个类里(这个类继承于ActionSupport),具体是哪个类就需要看其在onlinemusic\srcstruts.xml文件内的注册。如下所示:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.multipart.maxSize" value="10000000" />
<package name="Pluto" extends="struts-default">
<action name="register" class="Pluto.register"></action>
....
</package>
</struts>
可以看到这个类是Pluto.regiter类,其具体代码如下:
package Pluto;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class register extends ActionSupport {
private String userName = null;
private String userPwd = null;
private String confirmPwd = null;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPwd() {
return userPwd;
}
public void setUserPwd(String userPwd) {
this.userPwd = userPwd;
}
public String getConfirmPwd() {
return confirmPwd;
}
public void setConfirmPwd(String confirmPwd) {
this.confirmPwd = confirmPwd;
}
public String execute() throws SQLException, IOException{
ServletActionContext.getResponse().setCharacterEncoding("GB2312");
PrintWriter out = ServletActionContext.getResponse().getWriter();
ServletActionContext.getResponse().setHeader("Pragma", "No-cache");
ServletActionContext.getResponse().setHeader("Cache-Control",
"no-cache");
ServletActionContext.getResponse().setDateHeader("Expires", 0);
if(function.isInvalid(userName) || function.isInvalid(userPwd) || function.isInvalid(confirmPwd)){
out.println(function.PlutoJump("用户名或密码输入错误!", "index.jsp"));
}
if(!userPwd.equals(confirmPwd)){
out.println(function.PlutoJump("两次输入的密码不一致!", "index.jsp"));
}
DBConnection conn = new DBConnection();
ResultSet rs = conn.executeQuery("select * from user where name = '"+userName+"'");
if(rs.next()){
out.println(function.PlutoJump("用户名已存在!", "index.jsp"));
}else{
boolean insert = conn.execute("insert into user(name,pwd) values('"+userName+"','"+function.MD5Encode(userPwd)+"')");
if(insert){
out.println(function.PlutoJump("注册成功,请登陆!", "index.jsp"));
}else{
out.println(function.PlutoJump("注册失败!", "index.jsp"));
}
}
return null;
}
}
最关键的就是提交表单<form action="register.action" method="post">会调用回调函数execute(),这样就可以进行了业务相关的逻辑处理,我们可以看到在execute()函数内,设置了响应头的编码,设置了cache,还进行了逻辑判断,操控了数据库。
由于这个作者没有使用javaBean,所以在这段代码里会有一段三个这register中需要操作的属性值。但是这不妨碍我们理解struts的工作原理,我们可以看到三个属性值userName、userPwd、confirmPwd是和表单里面需要填的内容的name字段是一模一样的,所以能够自动进行参数注入。
<TD><INPUT type="text" name="userName" maxlength="16"/></TD></TR>
<TD><INPUT type="text" name="userPwd" maxlength="16"/></TD></TR>
<TD><INPUT type="password" name="confirmPwd" maxlength="16"/></TD></TR>
更好的办法是使用javaBean,使用javaBean之后只需要,将
public class register extends ActionSupport {
private User user = null;
public User getUser() {
return User;
}
public void setUser(User user) {
this.user = user;
}
....
}
然后在对应的jsp页面里面,如果改为:
<TD><INPUT type="text" name="user.userName" maxlength="16"/></TD></TR>
<TD><INPUT type="text" name="user.userPwd" maxlength="16"/></TD></TR>
<TD><INPUT type="password" name="user.confirmPwd" maxlength="16"/></TD></TR>
就能够进行了自动赋值。
上面这个struts2用的特别简单,说没有使用到struts2里面的很多很多功能。
其他内容
上面讲了挺多的,这里主要总结一下没有讲到的,但是有可能要用到的:EI表示式语言
又是一次在jsp页面内java语言的的封装,比如使用该JSP页面内的session范围内有一个变量username,如果想要输出。使用java代码则:<%
if(session.getAttribute("username"!=null){
out.println(session.getAttribute("username").toString());
}
%>
但是如果使用EI表达式,只需要一句:
${username}
EI表示式语言都是以${开头和}结尾。
这里我产生了一个疑问就是能不能用JSP脚本语言做类似的${username}的事,后来我想了想,上面那一段我以为只是java的代码,其实已经混杂了jsp了,比如使用了session和out两个jsp的内置对象。所以不存只使用jsp的形式。
JSTL
JSTL:JavaServer Pages Standard Tag Library:JSP标准标签库。这个玩意的作用和EI很像,也就是为了能够让在JSP页面内少用java代码,而对Java代码做了一次封装。用了这个东西,就可以取代大部分java代码了。如下所示:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>应用<c:out>标签输出字符串“水平线标记<hr>”</title>
</head>
<body>
escapeXml属性为true时:
<c:out value="水平线标记<hr>" escapeXml="true"></c:out>
<br>
escapeXml属性为false时:
<c:out value="水平线标记<hr>" escapeXml="false"></c:out>
</body>
</html>
其中在上述的代码中就是用了JSTL的标签:<c:out </c:out>来完成输出的功能。
下面有三点需要说明:
第一点,如果不使用JSTL的标签,那么我们只有在JSP中使用java代码(使用到了内置对象out)
<%
out.println("水平线标记")
%>
第二点,使用的这个<c:out </c:out>中的c就是所谓的标签,也就是说利用c这个标签的out的功能,而c这个标签是通过
- <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
第三点是涉及<c:out </c:out>的功能,其中escapeXml是否为true,表示是否将特殊字符转换为可以现在浏览器上直接显示,比如将<转化为<,所以上面一段实例的输出结果应该是:
- <c:out value="水平线标记<hr>" escapeXml="true"></c:out>:原样输出。
- <c:out value="水平线标记<hr>" escapeXml="false"></c:out>:将会输出<hr>在html里面所表示的横线。
更多的JSTL的内容、使用方式、示例可以参考博客: JSTL 核心标签库 使用
在本次实际主要学习的在线音乐管理平台的部分,几乎完全没有使用JSTL标签库和EI的表达式,在jsp页面全部使用了java代码来完成。我在想是不是对java代码比较熟悉的人,直接在jsp页面使用java代码也是可行的。
JSON与XML
其实这两个的作用都是差不多的,首先理解一下,XML,是被设计用来传输和存储数据。该怎么说呢,实际的使用其实是我一年半前学习android的时候把,那个是时候要做一个android平台的音乐播放器,我们就用到了xml来存储歌手的信息。背景是在服务员端存储了一个xml,如下所示:<?xml version="1.0" encoding="UTF-8"?>
<infos>
<info>
<id>0001</id>
<mp3_name>月亮之上.mp3</mp3_name>
<mp3_size>5623</mp3_size>
<lrc_name>月亮之上.lrc</lrc_name>
<lrc.size>192</lrc.size>
</info>
<info>
<id>0002</id>
<mp3_name>老男孩.mp3</mp3_name>
<mp3_size>5092</mp3_size>
<lrc_name>老男孩.lrc</lrc_name>
<lrc.size>166</lrc.size>
</info>
</infos>
应该是tomcat作为服务器,当android的音乐播放器连上这个服务器的时候,那么服务器就返回当前服务器存储的歌曲信息,就返回上面那个xml文件,然后xml文件到了android端之后,android端再一解析,就知道有哪些歌曲了。
上述过程完成了xml文件的存储歌曲信息和传输歌曲信息到android端的过程。我想这个例子是说明了xml文件用于存储和传输方面的功能。
然而仔细回想起来xml文件的作用好像不止于此,
- C:\apache-tomcat-6.0.35\conf\web.xml
对于JSON,先看w3cshool对JSON的解释:
- JSON:JavaScript 对象表示法(JavaScript Object Notation)。
- JSON 是存储和交换文本信息的语法。类似 XML。
- JSON 比 XML 更小、更快,更易解析。
"name":"Bill Gates"
如上所示,其它的无非就是多个键值对一起形成数组之类的,那时用[]表示。下面是一个来自w3cshool的例子,我们可以看到
<html>
<body>
<h2>在 JavaScript 中创建 JSON 对象</h2>
<p>
Name: <span id="jname"></span><br />
Age: <span id="jage"></span><br />
Address: <span id="jstreet"></span><br />
Phone: <span id="jphone"></span><br />
</p>
<script type="text/javascript">
var JSONObject= {
"name":"Bill Gates",
"street":"Fifth Avenue New York 666",
"age":56,
"phone":"555 1234567"};
document.getElementById("jname").innerHTML=JSONObject.name
document.getElementById("jage").innerHTML=JSONObject.age
document.getElementById("jstreet").innerHTML=JSONObject.street
document.getElementById("jphone").innerHTML=JSONObject.phone
</script>
</body>
</html>
结果如下: