一个专注于技术的IT男
JavaEE
久疏战阵
八 13th
语言这玩意是熟能生巧的,久疏战阵必然导致一些遗忘,虽说我常写些小玩意玩玩,但也扛不住关于java语言细节的拷问,感觉中国人面试就喜欢的问这样的问题,抗议
昨天被问到的问题是这样的,父类A有一个方法申明抛出异常ExceptionA,继承自A的子类B能不能覆盖这个方法,且声明抛出ExceptionA和ExceptionB?
回答这个问题的时候我不是非常确定,认为可以,因为印象中看到过类似的代码。
面试官却说这个是不可以的,相信他这么说的原因肯定是因为众多java编程书里面都有这么一点,方法覆盖的时候,子类方法不能抛出比父类方法更多的异常
然而这句话对么?结束之后,抱着怀疑的态度,我就在eclipse试了一下,其实这句话不完全对。
第一种情况:子类抛出的是父类声明异常的子类,这句话不适用
class A
{
public void method() throws Exception{}
}
class B extends A
{
public void method() throws ClassNotFoundException, IOException{}
}
class C extends A
{
public void method() throws Exception, IOException{}
}
第二种情况:子类声明多出来的异常是unchecked Exception,这句话不适用
class A2Exception extends RuntimeException
{
}
class B2Exception extends RuntimeException
{
}
class A2
{
void method1() throws A2Exception{}
}
class B2 extends A2
{
@Override
void method1() throws A2Exception,B2Exception{}
}
第三种情况:唯有这种情况下,编译不能通过,这句话能够适用
class AException extends Exception
{
}
class BException extends Exception
{
}
class A1
{
void method1() throws AException{}
}
class B1 extends A1
{
@Override
void method1() throws AException,BException{}
}
GoogleAppEngine中如何使用EL表达式?
四 28th
GoogleAppEngine中如何使用EL表达式?
方法是必须在页面里强制指定:
<%@ page language=”java” contentType=”text/html; charset=UTF-8″ pageEncoding=”UTF-8″ isELIgnored=”false”%>
我也尝试在web.xml中配置了el-ignore:false,但是这样做不行。
This doesn't work for GAE <jsp-config> <jsp-property-group> <url-pattern>/*</url-pattern> <el-ignored>false</el-ignored> </jsp-property-group> </jsp-config>
除此之外,还要在WEB-INF/lib中加入JSTL,EL的jar文件。
update:自己加入JSTL和EL的jar文件可能会导致这个问题 java.lang.AbstractMethodError: javax.servlet.jsp.PageContext.getELContext()Ljavax/el/ELContext;
但是如果不加入,使用eclipse编辑jsp的时候不能对JSTL进行代码辅助提示,权衡一下把jar加入classpath后运行app时还需要去掉,否则会有兼容性问题。
有用的参考资料:JavaEE的相关技术在Google App Engine中的兼容情况。
使用JNDI查找JBOSS内配置好的数据源遇到的问题
二 4th
这应该是很多J2EE新手都会碰到的问题,我在做一个J2SE中调用EntityManager学习JPA的小例子,遇到了不少异常信息
其中一个问题就是,运行Main程序时拿不到MySqlDS的配置,
google的一堆文章之后,在这篇帖子中找到的想要的答案 http://www.theserverside.com/discussions/thread.tss?thread_id=29813
总结一下就是JBoss默认将数据源绑定在本地JNDI命名空间下,所以不能从JBoss运行的JVM之外查找到改数据源,要解决这个问题就是配置JBoss将数据源绑定在全局命名空间下。
这个在dataSource的配置文件中指定,以MySql为例,就是在修改${JBOSS_HOME}/server/default/deploy/mysql-ds.xml
在<jndi-name>MySqlDS</jndi-name>下面一行添加 <use-java-context>false</use-java-context>
下面截取了JBoss此时打印出的一段日志,可以明显看到我们要的结果生效了
*** CONTEXTS IN ERROR: Name -> Error
persistence.unit:unitName=#HelloTitan -> javax.naming.NameNotFoundException: MySqlDS not bound
14:29:24,589 INFO [Http11Protocol] Starting Coyote HTTP/1.1 on http-127.0.0.1-8080
14:29:24,693 INFO [AjpProtocol] Starting Coyote AJP/1.3 on ajp-127.0.0.1-8009
14:29:24,709 INFO [ServerImpl] JBoss (Microcontainer) [5.0.0.GA (build: SVNTag=JBoss_5_0_0_GA date=200812042120)] Started in 1m:768ms
14:35:10,011 INFO [ConnectionFactoryBindingService] Unbound ConnectionManager ‘jboss.jca:service=DataSourceBinding,name=MySqlDS’ from JNDI name ‘java:MySqlDS’
14:35:10,222 INFO [WrapperDataSourceService] Bound ConnectionManager ‘jboss.jca:service=DataSourceBinding,name=MySqlDS’ to JNDI name ‘MySqlDS’
再次小结ServletRequest.getParameter乱码问题
十一 25th
情况之一:没有编码URL
HTML 页面
var url = “./SuggestServlet?tagName=”+document.getElementById(‘tagName’).value;
做一个AJAX请求到SuggestServlet,参数是中文字符串,(传递到容器,由容器决定采用何种编码解析)
到Servlet之后取这个参数 String myparam = request.getParameter(“tagName”);
得到的是一个乱码字符串,request.getCharacterEncoding() 得到的是一个null值,这时候tomcat默认的是ISO-8859-1编码解析,这就是我们得到乱码的原因了。
解决办法:
myparam = new String(myparam.getBytes(“ISO-8859-1″),”UTF-8″); 这样就能得到中文了
情况之二:使用javascript的encodeURI编码中文参数
HTML页面
var url = “./SuggestServlet?tagName=”+encodeURI(document.getElementById(‘tagName’).value);
同样是做一个AJAX请求到SuggestServlet,这时候参数被编码过了
到Servlet之后取这个参数 String myparam = request.getParameter(“tagName”);
得到的是UTF-8编码之后的字符串,其实不是乱码。
要获得中文字符,我们还需要再转换一次编码String decodingParam = URLDecoder.decode(myparam, “UTF-8″);
———————————————————————————————————————
补充:做URL请求之前,应该使用JavaScript encodeURL(url)
———————————————————————————————————————
EL如何取得数组长度?EL取不了要靠JSTL
十 22nd
方法一: 使用JSTL functions
<%@taglib uri=”http://java.sun.com/jsp/jstl/functions” prefix=”fn”%>
Eg:You have ${fn:length(shoppingCart.products)} in your shopping cart.
注意:这个标记和core不一样,它不能这样用 <fn:length(${commentsList}) />,这样会报类似于这样的一个异常:
org.apache.jasper.JasperException: /myshowpost.jsp(17,27) No tag “length(${commentsList})” defined in tag library imported with prefix “fn”
方法二: 使用<c:foreach status.count属性
<%@taglib uri=”http://java.sun.com/jsp/jstl/core” prefix=”c”%>
用c:forEach 中vaStatus的属性可以获得迭代的自身状态,如:
<c:forEach var=”" items=”" varStatus=”status”>
<c:out value=”${status.index}”/> 此次迭代的索引
<c:out value=”${status.count}”/> 已经迭代的数量
<c:out value=”${status.first}”/> 是否是第一个迭代对象
<c:out value=”${status.last}”/> 是否是最后一个迭代对象
</c:forEach>
Servlet+JSP分页的一个例子
十 15th
想在网上找个这样的例子,奈何这个世界太浮夸,干实事的不多,搞转帖的垃圾网站一大堆,有的还转的七零八落,有的例子下载还要登录,着实郁闷了一把
最后还是决定自己写吧,本例子提供eclipse工程压缩包下载,直接导入就能用了,本着踏实的态度干这件事,希望能给新手帮助。
本例着重介绍如何表现层分页的小技巧,DAO只是一个Demo,数据库查询的分页技巧不在本文讨论范围之内。
先看看最终效果的一个截图:
单从表现层来说分页不是一个复杂的工作,稍微理一下思路,处于不同competence level的同学应该都能自己搞出来。
以上面的文章列表分页为例,我觉得分页有两点重要的,
一是:分页我们必须首先自己搞清楚,文章总数、每页显示文章数(页大小)、页数
二是:如何做好页脚的分页导航条
实际应用中,文章总数这个值我们从数据库可以得到;每页显示的文章数即分页的页大小可以自己定义;页数我们可以通过下面的个表达式简单得出。
假设:
int pageSize = 10; //分页大小
int totalPosts = PagingDAO.entryList.size(); //总文章数
int totalPages = totalPosts/pageSize + ((totalPosts%pageSize)>0?1:0); //计算得出的总页数
每页的文章怎么取出来?
知道分页的大小之后,我们生成了页好的选取下拉框,每次选择第几页的时候,都会向Servlet传递当前选择页号的参数,这样Servlet调用后面的 DAO相应的方法,取得文章列表信息,再回传到JSP以供显示。
看看我们用作显示的index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
page Size : ${pageSize}
<br />
Total Posts: ${totalPosts}
<br />
Total Pages: ${totalPages}
<br />
Current Page: ${pageNumber}
<hr />
<table>
<thead>
<tr align="center">
<td width="10%">Article ID</td>
<td width="70%">Article Title</td>
<td colspan="3">Actions</td>
</tr>
</thead>
<tbody>
<c:forEach items="${entryList}" var="entry">
<tr align="center">
<td>${entry.entryID}</td>
<td>${entry.title}</td>
<td><a href="viewEntry?entryID=${entry.entryID}">View</a></td>
<td><a href="editEntry?entryID=${entry.entryID}">Edit</a></td>
<td><a href="deleteEntry?entryID=${entry.entryID}">Delete</a></td>
</tr>
</c:forEach>
</tbody>
<tfoot>
<tr align="center">
<td colspan="5">
<jsp:include page="paging_footer.jsp"></jsp:include>
</td>
</tr>
</tfoot>
</table>
<hr/>
这些流程清晰之后,我们就可以实现分页导航条了,也就是上面的paging_footer.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<script type="text/javascript">
function gotoSelectedPage()
{
var x = document.getElementById("navigatorForm");
//alert("Original action: " + x.action)
x.submit();
}
</script>
<form action="Posts" method="get" id="navigatorForm">
<a href="Posts?pageNumber=1">首页</a>
<c:if test="${pageNumber>1}">
<a href="Posts?pageNumber=${pageNumber-1}">上一页</a>
</c:if>
跳转到第 <select name="pageNumber" onchange="gotoSelectedPage();">
<c:forEach begin="1" end="${totalPages}" step="1" var="pageIndex">
<c:choose>
<c:when test="${pageIndex eq pageNumber}">
<option value="${pageIndex}" selected="selected">${pageIndex}</option>
</c:when>
<c:otherwise>
<option value="${pageIndex}">${pageIndex}</option>
</c:otherwise>
</c:choose>
</c:forEach>
</select>页
<c:if test="${pageNumber<totalPages}">
<a href="Posts?pageNumber=${pageNumber+1}">下一页</a>
</c:if>
<a href="Posts?pageNumber=${totalPages}">末页</a>
</form>
Posts是我们的Servlet,负责取得相关参数,和DAO打交道,取得一些文章的数据,然后传递到JSP,我们来看一下这个Servlet 的 doGet 方法。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String pageNumberStr = request.getParameter("pageNumber");
int pageNumber = 1;
if(pageNumberStr!=null && !pageNumberStr.isEmpty())
{
pageNumber = Integer.parseInt(pageNumberStr);
}
int pageSize = 10; //分页大小
int totalPosts = PagingDAO.entryList.size(); //总文章数
int totalPages = totalPosts/pageSize + ((totalPosts%pageSize)>0?1:0); //计算得出的总页数
request.setAttribute("pageSize", pageSize);
request.setAttribute("totalPosts", totalPosts);
request.setAttribute("pageNumber", pageNumber);
request.setAttribute("totalPages", totalPages);
List<Entry> entryList = PagingDAO.getEntryList(pageNumber, pageSize);
System.out.println("entryList:"+ entryList.size());
request.setAttribute("entryList", entryList);
request.getRequestDispatcher("index.jsp").forward(request, response);
}
分页其实还是很简单的事情,为了方便新手上路,这里提供一下这个eclipse的工程压缩包,直接导入就能用了。
(注意:对于eclipse JEE版本,工程导入后,请自行拷贝jstl.jar 和 standard.jar到WEB-INF/lib目录,如果没有配置Server的话,down个tomcat在eclipse里配置一下,不然怎么 run?这个基础的应该都会吧)
下载地址: Paging.zip
