JavaWeb(李兴华著)开发笔记
1.Java语法-基础
环境变量-JAVA_HOME, PATH, ClassPath
变量名 |
作用 |
举例 |
JAVA_HOME |
指向JDK目录 |
C:\Program Files\Java\jdk1.7.0_21 |
PATH |
指向java.exe目录。
|
%JAVA_HOME%\bin; %JAVA_HOME%\jre\bin |
CLASSPATH |
执行.jar文件、zip文件、.class文件所在目录。 (程序要用到哪些.class文件,) |
%JAVA_HOME%\lib\dt.jar; %JAVA_HOME%\lib\tools.jar;
|
控制语句 99 bottles of beer
public class GoJava2 {
/**
* @param args
*/
public static void main(String[] args) {
int beerNum=99;
String word="bottles";
while(beerNum>1){
System.out.println(beerNum+" "+word+" of beer on the wall");
System.out.println(beerNum+" "+word+" of beer");
System.out.println("Take one down");
System.out.println("pass it around");
beerNum--;
}
if(beerNum==1){
System.out.println(beerNum+" bottle of beer on the wall");
System.out.println("Take one down, no more beers");
}
}
}
guessNumber 游戏
public class Player {
int number;
public int Guess(){
this.number=(int)(Math.random()*10);
return this.number;
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Player p1=new Player();
Player p2=new Player();
Player p3=new Player();
boolean continueFlag=true;
int answer=-1;
while(continueFlag){
answer=(int)(Math.random()*10);
int n1=p1.Guess();
int n2=p2.Guess();
int n3=p3.Guess();
System.out.println("answer is:"+answer);
System.out.println("player1 guesses:"+n1);
System.out.println("player2 guesses:"+n2);
System.out.println("player3 guesses:"+n3);
if(n1==answer||n2==answer||n3==answer){
System.out.println("we have a winner among the p1,p2,p3");
continueFlag=false;
}
else{System.out.println("no one guessed the answer,game continue");}
}
System.out.println("p1 guesses:"+(p1.number==answer));
System.out.println("p2 guesses:"+(p2.number==answer));
System.out.println("p2 guesses:"+(p3.number==answer));
}
}
引用变量 遥控 对象
public class Dog {
String name;
public void bark(){
System.out.println(this.name+" is barking");
}
/**
* @param args
*/
public static void main(String[] args) {
Dog[] dogs=new Dog[3];
dogs[2]=new Dog();
dogs[0]=new Dog();
dogs[0].name="Fido";
dogs[2]=dogs[0];
dogs[2].bark();
if(dogs[2].name==dogs[0].name){
System.out.println(true);
}
else{
System.out.println(false);
}
}
}
输出:
Fido is barking
true
super()
final
作用:修饰变量
效果:赋值之后 无法改变。
.java文件中放多个类
规则:
最多只能有一个public Class.
如果存在public Class,那么 .java的文件名必须是public Class的名字
.java-.class-.jar 文件
摘要
类型 |
说明 |
.java |
写代码写在这文件中 |
.jar |
本质:多个.class文件的压缩包。 如何生成:(1)IDE中Export JAR我那件 (2)winzip将class文件压缩成.jar |
.class文件 |
本质:在java虚拟机中运行的二进制文件。 ---- 如何生成: step1:进入到.java文件的目录 f: cd pkgSvt
step2:javac java文件名 效果:相同位置产生.class文件
如何运行.class文件 step1 java –cp f:\pkgSvt ClsStrSB //设置classpath,要用哪些class step2 cd pkgSvt //进入父目录 step3 java ClsStrSB //执行class 中的 main |
Object 为空判断
判断对象为null
If(obj==null){//为空
}
eclipse导出jar, classpath not found
工程文件夹应该会有个大红感叹号。右击工程文件夹,properties 选择java build class,查看各选项卡,有红色错误提醒的remove之即可。
数组- List -ArrayList
数组
摘要:直接声明。
指定长度声明。
不可动态改变长度。
String[] IDNUMs={"US100","US120"};
String[] temp=new String[10];
数组随机 专家术语机.
Index:Math.random, String[] ={},
数组定义:
String[] array1={“”,””,””}
public static void main(String[] args) {
String[] wordListOne = {"24/7","multi-Tier","30,000 foot","B-to-B","win-win","frontend","web-based","pervasive", "smart", "sixsigma","critical-path", "dynamic"};
String[] wordListTow={"process","tipping-point","solution","archetecture","core-competency","strategy","mind-care"};
String[] wordListThree={"toomcat","apache","Linux","nginx"};
String word1=wordListOne[(int)(Math.random()*wordListOne.length)];
String word2=wordListTow[(int)(Math.random()*wordListTow.length)];
String word3=wordListThree[(int)(Math.random()*wordListThree.length)];
for(int i=0;i<=9;i++){
System.out.println(word1+" "+word2+" "+word3);
}
}
输出:
web-based core-competency apache
web-based core-competency apache
web-based core-competency apache
web-based core-competency apache
web-based core-competency apache
web-based core-competency apache
web-based core-competency apache
web-based core-competency apache
web-based core-competency apache
web-based core-competency apache
List
List<E>([]内的内容可省略),与数组类似:
ArrayList<DisPoint> liPts=new ArrayList<DisPoint>();
while(rs.next()){
DisPoint pt=new DisPoint(rs.getInt("ID"),rs.getString("Name"),rs.getDouble("Longitude"),rs.getDouble("Latitude"));
liPts.add(pt);
}
获得集合内元素个数:list.size();
添加元素:
默认添加:list.add(e);
指定下标添加(添加后下标后的元素向后挪一位):list.add(index,e);
删除元素:
返回是否删除:list.remove(e);
直接删除指定下标的元素(只删除找到的第一个相符合的元素):list.remove(index);
替换元素(替换掉指定下标的元素):list.set(index,e);
取出元素:list.get(index);
清空集合:list.clear();
判断集合中是否存在某个元素(存在返回true,不存在返回false):list.contains(e);
对比两个集合中的所有元素:
两个对象一定相等:list.equals(list2);
两个对象不一定相等:list.hashCode() == list2.hashCode();
(两个相等对象的equals方法一定为true, 但两个hashcode相等的对象不一定是相等的对象。)
获得元素下标:
元素存在则返回找到的第一个元素的下标,不存在则返回-1:list.indexOf(e);
元素存在则返回找到的最后一个元素的下标,不存在则返回-1:list.lastIndexOf(e);
判断集合是否为空(空则返回true,非空则返回false):list.isEmpty();
返回Iterator集合对象:list.iterator();
将集合转换为字符串:list.toString();
截取集合(从fromIndex开始在toIndex前结束,[fromIndex,toIndex)):list.subList(fromIndex,toIndex);
将集合转换为数组:
默认类型:list.toArray();
指定类型(objects为指定类型的数组对象,并将转换好的数组赋值给objects数组):list.toArray(objects);
以上为List常用的方法。
ArrayList
int数组
ArrayList<Integer> arID=new ArrayList<Integer>();
ArrayList转Array
public static Integer[] getUtfAr(String usr,int del){
ArrayList<Integer> ar=new ArrayList<Integer>();
for(int i=0;i<=usr.length()-1;i++){
ar.add(usr.codePointAt(i));
}
Integer[] tm=(Integer[])ar.toArray(new Integer[ar.size()]);
return tm;
}
2.SVN操作
目标:集成到eclipse, 源代码管理
1.下载 svn.jar包
2.解压到 得到两个目录:
features,plugins
3.将features,plugins拷贝到ecplise/dropins目录下
4.启动eclipse,创建一个workSpace, 例如fareWeb
5.FileàNewàOtheràsvnà从svn检出项目
6.输入url
https://10.254.53.4:8443/svn/bii2ITA/trunk/src/SourceCode/fareWeb
用户名:gaoxk
密码:gaoxk123
3. 测试-调试
在java classc测试- main函数
public static void main(String[] args) {
Crud crud=new Crud();
Employee emp=new Employee("孔卡",26,"足球运动员");
Employee inserted=crud.insertOne(emp);
crud.printOne(inserted);
inserted.Name="穆里奇";
Employee updated=crud.updateOne(inserted);
crud.printOne(updated);
crud.showAll();
crud.deleteRecs(updated.id);
}
查看方法执行时间
System.out.println("getCond时间:"+((new Date()).getTime()-now.getTime()));
System.out.println 调试
描述:控制台输出
参数:string
举例
System.out.println(“hello world”)
如何查看变量的值
1> 进入Debug View
2> Window àShow View Expressions
3> 在Name中添加变量名/.变量值,Value中查看值
如何查看类型的所有方法/属性 (API Documentation)
1> 鼠标放到类型上,按F2, Open Javadoc in Browser
获取离线JavaSE Documentation
1> 网页版
访问Oracle.com, JavaSE 下载页面,页面靠下的部分有 Java SE Documentation下载,是一个网站(Zip包)
2.>Chm版
在baidu上搜 Java SE API Chm。
使用正则查找/替换
需求:
在 edit.html中 ,draw***();替换成空
譬如:
drawPeoples(); drawGender();
正则表达式
draw[a-zA-Z]+\(\);
Tomcat
目录结构
序号 |
目录名 |
描述 |
1 |
bin |
可运行程序目录。start,shutdown在此目录下。 |
2 |
lib |
放jar包 |
3 |
conf |
放配置文件 |
4 |
logs |
存放日志文件 |
5 |
webapps |
web项目(war包)在此即发布 |
6 |
work |
临时目录,jsp生成 .java文件将在此 |
端口号设置
http端口
conf/server.xml
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
SSL端口
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" />
-->
AJP端口
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
role和用户配置 tomcat-users.xml
用途:管理用户
(设置某个web的jsp权限)
字段:
举例:
打开conf/tomcat-users.xml
添加两个role,两个 user
<role rolename="admin"/>
<role rolename="guest"/>
<user username="admin" password="admin" roles="admin"/>
<user username="guest" password="guest" roles="guest"/>
创建虚拟目录
原则:每一个虚拟目录存放一个Web项目
步骤
序号 |
详细 |
概要 |
1 |
在硬盘上建立目录,并在目录中建立WEB-INF目录 |
创建虚拟目录 |
2 |
将tomcat/webapps/Root/web.xml拷贝到WEB-INF目录下 |
添加配置文件web.xml |
3 |
<Host> ...... <Context path=”/test1” docBase=”E:\test1”></Context> ...... </Host>
|
将虚拟目录关联到conf/server.xml |
4 |
在test1下写 index.jsp:
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> </head> <body> <h1><% out.println("Hello,JSP World");%></h1> </body> </html>
启动tomcat,访问地址 localhost/test1/ |
测试 |
第一个JSP
在已关联的虚拟目录下创建index.jsp,内容如下:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<h1><% out.println("Hello,JSP World");%></h1>
</body>
</html>
效果:
虚拟目录/WEB-INF/web.xml
web.xml中的路径符号
url-pattern |
说明 |
实际地址 |
su |
无法启动 |
|
../su |
不允许../ 服务器无法启动 |
|
/su |
虚拟目录/su |
页面form 的路径
sample1.htm
pattern |
说明 |
实际地址 |
<form action="su" |
与页面同级的su |
|
<form action="../su" |
页面父目录的su |
Web标准目录结构
WEB-INF必须存在
要点:
(1)虚拟目录下必须存在WEB-INF目录。 WEB-INF必须包好web.xml文件。
(2)by default, internet用户无权限访问WEB-INF下的内容。
(3)不想被浏览器直接访问的页面,放在WEB-INF下。增强安全
web.xml jsp映射
摘要:
<servlet>
<servlet-name></servlet-name>
<jsp-file></jsp-file>
</servlet>
<servlet-mapping>
<servlet-name></servlet-name>
<url-pattern></ url-pattern>
</servlet-mapping>
jsp映射
<servlet>
<servlet-name>serA</servlet-name><!--servlet-name only works inside web.xml,to connect JSP-FILE with URL-PATTERN-->
<jsp-file>/test.jsp</jsp-file><!--JSP-FILE-->
</servlet>
<servlet-mapping>
<servlet-name>serA</servlet-name>
<url-pattern>/hello</url-pattern><!--URL-PATTERN-->
</servlet-mapping>
web.xml servlet映射
servlet映射
摘要:
<servlet>
<servlet-name></servlet-name>
<servlet-class></servlet-class>
</servlet>
<servlet-mapping>
<servlet-name></servlet-name>
<url-pattern></ url-pattern>
</servlet-mapping>
摘要:使用通配符 *
<web-app>
<servlet>
<servlet-name>SvtHello</servlet-name>
<servlet-class>pkgResiCrud.SvtHello</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SvtHello</servlet-name>
<url-pattern>/hello/*</url-pattern>
</servlet-mapping>
</web-app>
init-param配置 驱动-dburl-用户名-密码
在web.xml中
注意:
(1)要放在servlet标签下
(2)客户端请求url-pattern时,getInitParameter生效。
客户端直接请求jsp时, getInitParameter取值为null.
<servlet>
<init-param>
<param-name>DbDriver</param-name>
<param-value>oracle.jdbc.driver.OracleDriver</param-value>
</init-param>
<servlet-name>serA</servlet-name>
<jsp-file>/test.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>serA</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
在JSP页面中:
以config.getInitParameter(“”)获取参数值
<error-page> 设置出错处理页面
<error-page>
<error-code>404</error-code>
<location>error.jsp</location>
<error-code>500</error-code>
<location>error.jsp</location>
</error-page>
</web-app>
效果:
index.jsp
<%@ page language="Java" contentType="text/html;charset=GBK"%>
<h2>index.jsp</h2>
<%int result=10/0;%>
服务端跳转:
error.jsp
<%@ page language="Java" contentType="text/html;charset=GBK"%>
<h2>页面发生了错误...</h2>
<a href="index.jsp">点击此处返回主页面</a>
备注:with web.xml,即使没有<%@ page isErrorPage=”true”%>,it still works
security-contraint页面权限
备注:GET和Post Request都要求验证
前件:要在tomcat-users.xml中 添加role,和role类的用户
效果:访问页面需要输入用户名密码
用途:保护管理员页面
密码传输方式:不是明文
配置方式:
<security-constraint><!--page and roles-->
<web-resource-collection><!--pages are protected-->
<url-pattern>/check.jsp</url-pattern>
</web-resource-collection>
<auth-constraint><!--allowed roles-->
<role-name>admin</role-name><!--must-->
</auth-constraint>
</security-constraint>
<login-config><!--Login form for validation-->
<auth-method>BASIC</auth-method>
</login-config>
<security-role><!--withoud this,warning appears when start-->
<role-name>admin</role-name>
</security-role>
</web-app>
JSP
第一个JSP
<%@ page language=”Java” contentType=”text/html;charset=utf-8”%>
<h1><%out.println("hello world");%></h1>
访问:
http://localhost:8080/UI05/html/first.jsp
效果:
...
结论:
(1)jsp文件,可以不写<!DOCTYPE><head><body>
JSP本质是 java类
JSP文件最终都是以.java文件在服务端执行
后果:
(1)第一次访问.jsp比第二次之后慢
(2)访问后在硬盘上生成.java文件
第一个交互表单
在虚拟目录下创建 index.jsp和index.html
index.html:
<!DOCTYPE HTML>
<html>
<head></head>
<body>
<form action='index.jsp'>
<input type="text" name="info" value=""/><input type="submit" value="提交"/>
</form>
</body>
</html>
index.jsp:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<h1><% out.println(request.getParameter("info"));%></h1>
</body>
</html>
访问:index.html
点击提交:
基础语法
注释符号
序号 |
举例 |
1 |
<%-- out.println(“hello world”);--%> |
2 |
<% //out.println(“hello world”);%> |
3 |
<% /*out.println(“hello world”);*/ %> |
java语句标签
作用:java语句要写在 java语句标签内。
备注:不要将指令写在语句标签内
序号 |
举例 |
说明 |
1 |
<%!public String HelloWorld(){ return “hello world”; }%> |
作用: 定义 类,方法,全局变量。 (备注: 不要在JSP中定义方法,类。 在JavaClass中定义。) |
2 |
<% String one=”hello world”; out.println(one); %> |
执行语句。 |
3 |
<%=one%> |
获取变量。 (备注: 不要在<%=%>中添加注释) |
4 |
<jsp:scriptlet></jsp:scriptlet> |
|
举例:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<%!public String helloWorld(){
return "hello world";
};//定义方法%>
<%String one="one";//定义变量%>
<h1><%=helloWorld()%></h1>
<h2><%=one%><%//取变量%></h2>
</body>
</html>
out.print vs <%=%>
<%=%> 称作 表达式输出。
结论:
使用<%=%> 取代<%out.println()%>
好处(1)效率高
(2)html代码和 java代码分离
if else写法
正确:
<%if(info.equals("true")){%>
<jsp:forward page="success.jsp">
<jsp:param name="info" value="<%=paraU%>"></jsp:param>
</jsp:forward>
<%}else{%>
错误:
<%if(info.equals("true")){%>
<jsp:forward page="success.jsp">
<jsp:param name="info" value="<%=paraU%>"></jsp:param>
</jsp:forward>
<%}%>
<%else{%>
Page指令索引
常用的4种:
contentType , pageEncoding, errorPage ,import,
Page import指令
导入Jar包
备注:1个page指令 只能由1个import,1个import只能导1个jar
<%@ page contentType="text/html;" pageEncoding="GBK" import="java.util.*"%>
<%@ page import="java.io.*"%> <%// one page Dir can only import one jar%>
<%@ page import="java.math.*"%>
Page pageEncoding=”GBK” 显示中文
<%@ page language="Java" contentType="text/html;" pageEncoding="GBK"%><%//jsp要显示中文%>
<table border=1>
<tr><td>序号</td><td>名称</td><td>描述</td></tr>
</table>
Page指令contentType 显示html
contentType=”mimeType;”
举例 |
Mime类型 |
contentType=”text/html;” |
text/html |
<%@ Page language="Java" contentType="text/html; "%>
Page contentType vs response.setHeader控制编码
Page设置 Content-Type 正常
<%@ page language="Java" contentType="text/html;" pageEncoding=”GBK”%>
<table border="1" cellpadding=0 cellspacing=0>
<tr><td>序号</td><td>名称</td><td>描述</td><tr>
</table>
setHeader-ContentType乱码
<%@ page language="Java"%>
<%response.setHeader("Content-Type","text/html;charset=GBK");%>
<table border="1" cellpadding=0 cellspacing=0>
<tr><td>序号</td><td>名称</td><td>描述</td><tr>
</table>
结论:
JSP页面编码,使用Page指令,不用response.setHeader
Page指令 设置出错页
show.jsp:
<%@ page language="Java" contentType="text/html;charset=GBK"%>
<%@ page language="Java" errorPage="error.jsp"%>
<h2>index.jsp</h2>
<%int result=10/0;%>
error.jsp
<%@ page language="Java" contentType="text/html;charset=GBK"%>
<%@ page isErrorPage="true"%><%//此页可处理错误%>
<h2>页面发生了错误...</h2>
<a href="index.jsp">点击此处返回主页面</a>
效果:
特点:
服务端跳转(客户端只发送了一次请求。服务端执行了另一个页面的代码)
Include指令 包含jsp,htm文件
原理:所有file被included into index.jsp,再编译
应用:
index.jsp:
<%@ page language="Java" contentType="text/html;charset=GBK"%>
<%@include file="left.htm"%>
<%@include file="middle.htm"%>
<%@include file="right.htm"%>
left.htm
<div style="display:inline-block; width:300px;">
<h1>We<h1>
</div>
middle.htm
<div style="display:inline-block; width:300px;">
<h1> are cellestial<h1>
</div>
right.htm
<div style="display:inline-block; width:300px;">
<h1> man<h1>
</div>
效果:
jsp:include指令 动态包含
区别:各部分被分别编译,然后包含
jsp:forward指令 跳转
jsp实现登录功能
login.htm
<!DOCTYPE HTML>
<html>
<head></head>
<body>
<center>
<form action="login_check.jsp">
<table cellspacing=0 cellpadding=0 style="border-collapse:collapse;border:1px solid rgb(0,0,0);">
<tr><td colspan=2>登录系统</td><td></td></tr>
<tr><td>用户名:</td><td><input type="text" name="usr" /></td></tr>
<tr><td>密码:</td><td><input type="text" name="psw" /></td></tr>
<tr><td colspan=2><input type="submit" value="登录" /><input type="reset" value="重置"></td><td></td></tr>
</table>
</form>
</center>
</body>
</html>
login_check.jsp
<%@ page language="Java" contentType="text/html;charset=GBK"%>
<%@ page import="java.sql.*"%>
<%
final String DbDriver="oracle.jdbc.driver.OracleDriver";
final String DbUrl="jdbc:oracle:thin:@localhost:1521:orcl";
final String Usr="test";
final String Psw="test";
String paraU=request.getParameter("usr");
String paraP=request.getParameter("psw");
Class.forName(DbDriver);
Connection conn=DriverManager.getConnection(DbUrl,Usr,Psw);
Statement stmt=conn.createStatement();
String sqlStr="select usr, psw from account";
String info="false";
ResultSet rs=stmt.executeQuery(sqlStr);
while (rs.next()){
if(rs.getString("usr").equals(paraU)){
if(rs.getString("psw").equals(paraP)){
info="true";
}
else{
info="invalid password";
}
}
else{
continue;
}
}
info=info.equals("false")?"user does not exist":info;
rs.close();
stmt.close();
conn.close();
%>
<%if(info.equals("true")){%>
<jsp:forward page="success.jsp">
<jsp:param name="info" value="<%=paraU%>"></jsp:param>
</jsp:forward>
<%}else{%>
<jsp:forward page="fail.jsp">
<jsp:param name="info" value="<%=info%>"></jsp:param>
</jsp:forward>
<%}%>
success.jsp
<%@ page contentType="text/html;charset=GBK"%>
<h1>You're Welcome,<%=request.getParameter("info")%></h1>
fail.jsp
<%@ page language="Java" contentType="text/html;charset=GBK"%>
<h1>登录失败...<%=request.getParameter("info")%></h1>
<a href="login.htm">返回登录页</a>
效果
服务端跳转 和 客户端跳转
|
代码 |
浏览器效果 |
服务端跳转 |
<jsp:forward page=”other.jsp”></> |
地址栏未改变 |
客户端跳转 |
<a href=<%=loc2%> /> |
地址栏变化 |
效率:服务端跳转高
JSP 内置对象索引
常用5个:request, response, pageContext, session, application
作用范围 request , session, application
page 范围
用途:
jsp页面内存取变量
范围:
在当前jsp页面中有效
失效情况(any)
<jsp: forward=”page2.jsp”></jsp:forward>
request 范围
特点:
比page略长,服务器端跳转后 依然有效;
客户端跳转后,无效
举例-服务端跳转,有效
request_01.jsp
request_02.jsp
request-客户端跳转
requst_01.jsp
session 范围
特点:session.setAttribute(“info”,”Juptor Mind”)执行
如果不关闭浏览器,则Webapp下其它页面都可取
无法取得:
浏览器关闭后
举例:
session_01.jsp
session_02.jsp
application 范围
特点:存在服务器上。所有session都可存取
中止:服务器重启
举例:
application_1.jsp
application_2.jsp
request 范围实验(DIY)
req1.jsp
<%@ page language="java" contentType="text/html;charset=GBK"%>
<title>Req1.jsp</title>
<%request.setAttribute("info","Jupitor mind");%>
<span>request.getAttribute("info")=<%=request.getAttribute("info")%></span>
<a href="req2.jsp">anchor to req2.jsp</a></br><%//prove 客户端跳转%>
<jsp:forward page="req2.jsp"></jsp:forward> <%//prove 服务端跳转.进行 服务端跳转,请去除此语句%>
req2.jsp
<%@ page language="Java" contentType="text/html;charset=GBK"%>
<title>req2.jsp</title>
<span>request.getAttribute("info") is:<b><%=request.getAttribute("info")%></b></span>
session范围实验(DIY)
req1.jsp
<%@ page language="java" contentType="text/html;charset=GBK"%>
<title>Req1.jsp</title>
<%session.setAttribute("info","Jupitor mind");%>
<span>session.getAttribute("info") is:<b><%=session.getAttribute("info")%></b></span></br>
<a href="req2.jsp">click to req2.jsp</a>
req2.jsp
<%@ page language="Java" contentType="text/html;charset=GBK"%>
<title>req2.jsp</title>
<span>session.getAttribute("info") is:<b><%=session.getAttribute("info")%></b></span>
HttpServletRequest对象
备注:
JSP页面和Servlet中的request都是HttpServletRequest类型。
setCharacterEncoding 解析中文
应用:客户端发送未编码的中字,先使用此方法,否则乱码
实验
check.jsp
<%@ page language="Java" contentType="text/html;" pageEncoding="GBK"%><%//jsp要显示中文%>
<%
request.setCharacterEncoding("GBK"); //解析中文字符串
String usr=request.getParameter("usr");
%>
usr:<%=usr%>
login.htm
<!DOCTYPE HTML>
<html>
<head><meta content-type="text/html;charset=utf-8"></head>
<body>
<form action="check.jsp" method="post">
<table><tr><td>用户名:</td><td><input type="text" name="usr" value="his name is 木星意志"/></td></tr>
<tr><td colspan=2><input type="submit" value="提交"></td><td></td></tr>
</table>
</form>
</body>
</html>
getParameter(name) 取一个value
getParameterValues(name) 获取同name标签values
背景:任何两个html标签允许同名。
login.htm
<!DOCTYPE HTML>
<html>
<head><meta content-type="text/html;charset=utf-8"></head>
<body>
<form action="check.jsp" method="post">
<table>
<tr><td>姓名</td><td>
<input type="text" name="name" value="木星"/>
<input type="text" name="name" value=""/>
</td></tr>
<tr><td>爱好</td>
<td>
游泳<input type="checkbox" name="inter" value="游泳"/>
篮球<input type="checkbox" name="inter" value="篮球"/>
神风<input type="checkbox" name="inter" value="神风"/>
</td>
</tr>
<tr><td colspan=2><input type="submit" value="提交"/></td><td></td></tr>
</table>
</form>
</body>
</html>
check.jsp
<%@ page language="Java" contentType="text/html;" pageEncoding="GBK"%><%//jsp要显示中文%>
<%
request.setCharacterEncoding("GBK"); //解析中文字符串
String[] names=request.getParameterValues("name");
String[] inters=request.getParameterValues("inter");
%>
<%
if(names!=null){
for(int i=0;i<=names.length-1;i++){%>
name[<%=i%>]:<%=names[i]%></br>
<%}}%>
<%if(inters!=null){
for(int i=0;i<=inters.length-1;i++){
%>
interest[<%=i%>]:<%=inters[i]%>
<%}}%>
getParameterNames取所有name
用途:获取所有传入参数
举例:获取复选框项
适用于:存在复选框时
拓展:查询条件组合,购物车
login.html
<!DOCTYPE HTML>
<html>
<head><meta content-type="text/html;charset=utf-8"></head>
<body>
<form action="check.jsp" method="post">
<table>
<tr><td>姓名</td><td>
<input type="text" name="name" value="木星"/>
</td></tr>
<tr><td>邮箱</td><td>
<input type="text" name="mail" value="1695539064@qq.com"/>
</td></tr>
<tr><td>爱好</td>
<td>
游泳<input type="checkbox" name="inter" value="游泳"/>
篮球<input type="checkbox" name="inter" value="篮球"/>
神风<input type="checkbox" name="inter" value="神风"/>
</td>
</tr>
<tr><td colspan=2><input type="submit" value="提交"/></td><td></td></tr>
</table>
</form>
</body>
</html>
check.jsp
<%@ page language="Java" contentType="text/html;" pageEncoding="GBK"%><%//jsp要显示中文%>
<%@ page import="java.util.*"%>
<%
request.setCharacterEncoding("GBK"); //解析中文字符串
Enumeration pNames=request.getParameterNames(); //取所有names
while(pNames.hasMoreElements()){//遍历names
String pName=(String)pNames.nextElement();
%>
参数名:<%=pName%>,参数值:<%String[] values=request.getParameterValues(pName);//retrive values of one Name
for(int i=0;i<=values.length-1;i++){%>
<%=values[i]%><span> </span>
<%}
%></br>
<%}%>
效果:
Header Cookie, agent, IP , referer,method
举例:遍历request头信息
<%@ page language="Java" contentType="text/html" pageEncoding="GBK" import="java.util.*"%>
<%
Enumeration items=request.getHeaderNames();
%>
method:<%=request.getMethod()%></br>
clientIP:<%=request.getRemoteAddr()%></br>
<%while(items.hasMoreElements()){
String hName=(String)items.nextElement();
String value=(String) request.getHeader(hName);
%>
<%=hName%>:<%=value%></br>
<%}%>
clientIP:127.0.0.1
host:localhost
connection:keep-alive
content-length:80
cache-control:max-age=0
accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
origin:http://localhost
user-agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like
Gecko) Chrome/28.0.1500.72 Safari/537.36
content-type:application/x-www-form-urlencoded
referer:http://localhost/test1/login.htm
accept-encoding:gzip,deflate,sdch
accept-language:zh-CN,zh;q=0.8
cookie:JSESSIONID=816945B50F0C1130B0E00C99B90F731C
判断role类型
前提:
(1)在tomcat-users.xml中添加了role和user
(2)在虚拟目录-web.xml中配置security-constraint,login-config,security-role
效果:
login验证通过后,retrive用户role.(不是username)
<%@ page language="Java" contentType="text/html" pageEncoding="GBK"%>
<%if(request.isUserInRole("admin")){%>
Welcome,<b>Role admin</b>
<%}%>
getContextPath() 获取应用名
<%@ page language="Java" contentType="text/html;" pageEncoding="GBK"%>
host:<b><%=request.getHeader("host")%></b></br>
ContextPath:<b><%=request.getContextPath()%></b></br>
ServletPath:<b><%=request.getServletPath()%></b>
getServletPath() 取应用名之后部分
getCoockies() Cookies[]
HttpServletReponse对象
备注:JSP页面和Servlet中的request都是HttpServletRequest类型。
setHeader(“refresh”) 定时跳转
摘要:setHeader(“refresh”,”3;url=login.htm”)
备注:客户端跳转
<%@ page language="Java" contentType="text/html;" pageEncoding="GBK"%>
<%response.setHeader("refresh","3;url=login.htm");%><%//setHeader("refresh","2;url="),客户端跳转%>
3秒钟后将跳转到login.htm...
sendRedirect 客户端跳转
备注:客户端跳转
<%@ page language="Java" contentType="text/html;" pageEncoding="GBK"%>
<%response.sendRedirect("login.htm");%>
response.setHeader 保存word
页面:
<%@ page language="Java" pageEncoding="GBK"%>
<%response.setHeader("Content-Disposition","attachment;filename=test.doc");%>
<table border="1">
<tr><td>序号</td><td>名称</td><td>描述</td><tr>
</table>
Mime设置:
打开conf/web.xml,
确认一下mime-mapping存在
<mime-mapping>
<extension>dot</extension>
<mime-type>application/msword</mime-type>
</mime-mapping>
效果:页面不打开,直接下载
byte[]返回文件 (下载)
InputStream inStream=null;
//全部
try {
inStream=ResiCrud.createExcel(filePath);
} catch (ClassNotFoundException | WriteException
| SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
response.reset();
response.setHeader("Content-Disposition", "attachment;filename=" +response.encodeURL(fileUrl));
response.setContentType("application/octet-stream");
byte[] fileBytes=new byte[1024];
int length=0;
while((length=inStream.read(fileBytes))>0){
response.getOutputStream().write(fileBytes,0,length);
}
response.flushBuffer();
response.getOutputStream().close();
inStream.close();
return;
response返回文本数据
(1) response.getOutputStream.write二进制流
//设置 数据编码
response.setHeader("Content-type", "text/plain;charset=utf-8");
String result="hello World";
//传送 二进制数组,将字符串以 utf-8变成 二进制数组
response.getOutputStream().write(result.getBytes("utf-8"));
(2)response.getWriter.write() 字符串
response.setHeader("Content-type","text/html;charset=UTF-8");
PrintWriter writer = response.getWriter();
writer.write("中国");
Cookie对象
意义:Cookie生存在客户端上。常用于存放用户名密码等信息。
在周期满后,会被清除。浏览器执行清空Cookie操作后,也被清除。
个数限制:最多300个
Cookie 索引
命名空间:javax.Servlet.http.Cookie
response.addCookie 添加Cookie
模拟登录,Cookie遍历,添加,
摘要:
取所有Cookies |
Cookie[] cos=request.getCookies(); |
遍历Cookies |
for(int i=0;i<=cos.length-1;i++){ String coName=cos[i].getName(); String coVal=cos[i].getValue(); } |
设置Cookies时长 |
coName.setMaxAge(600);//十分钟 |
客户端 延时跳转 |
response.setHeader(“refresh”,”3;url=login.jsp”) |
客户端 立即跳转 |
reponse.sendRedirect(“login.jsp”) |
login.jsp
<%@ page language="Java" pageEncoding="GBK" contentType="text/html"%>
<%
Cookie[] cos=request.getCookies();
String usr=null;
String psw=null;
%>
<%if(cos!=null){
for(int i=0;i<=cos.length-1;i++){
if(cos[i].getName().equals("usr")){
usr=cos[i].getValue();
}
if(cos[i].getName().equals("psw")){
psw=cos[i].getValue();
}
}
if(usr!=null&&psw!=null){%>
<jsp:forward page="index.jsp"></jsp:forward><%--服务端跳转--%>
<%}%>
<%}%>
<!DOCTYPE HTML>
<html>
<head><meta content-type="text/html;charset=utf-8"></head>
<body>
<form action="check.jsp" method="post">
<table>
<tr><td colspan=2>登录系统</td><td></td></tr>
<tr><td>用户名</td><td><input type="text" name="usr"/></td></tr>
<tr><td>密码</td><td><input type="text" name="psw"/></td></tr>
<tr><td colspan=2><input type="submit" value="登录"></td><td></td></tr>
</table>
</form>
</body>
</html>
check.jsp
<%@ page language="Java" contentType="text/html;" pageEncoding="GBK"%>
<%
String usr=request.getParameter("usr");
String psw=request.getParameter("psw");
String info="用户名不存在";
if(usr.equals("test")){
if(psw.equals("test")){
info="true";
}
else{info="密码无效";}
}
%>
<%
if(info=="true"){
Cookie cName=new Cookie("usr",usr);
Cookie cPsw=new Cookie("psw",psw);
response.addCookie(cName);
response.addCookie(cPsw);
response.sendRedirect("index.jsp");
}
else{%>
<%=info%>,<a href="login.htm">请重新登录</a>
<%}%>
index.jsp
<%@ page language="Java" contentType="text/html;" pageEncoding="GBK"%>
<%
Cookie[] cos=request.getCookies();//取所有Cookie
String usr=null;
String psw=null;
for(int i=0;i<=cos.length-1;i++){
if(cos[i].getName().equals("usr")){//取用户名Cookie
usr=cos[i].getValue();
}
%>
CookieName:<%=cos[i].getName()%>,Value:<%=cos[i].getValue()%></br>
<%}%>
<%if(usr!=null){%>
欢迎你,<b><%=usr%></b>
<%}else{%>
请先登录,<a href="login.htm">点此前往登录页</a>
<%}%>
Cookie.setMaxAge 存在时间
背景:
不设置Cookie时间,则浏览器关闭后,Cookie被清空。
co.setMaxAge(600) ,Cookie存在10分钟
check.jsp
<%@ page language="Java" contentType="text/html;" pageEncoding="GBK"%>
<%
String usr=request.getParameter("usr");
String psw=request.getParameter("psw");
String info="用户名不存在";
if(usr.equals("test")){
if(psw.equals("test")){
info="true";
}
else{info="密码无效";}
}
%>
<%
if(info=="true"){
Cookie cName=new Cookie("usr",usr);
cName.setMaxAge(600);
Cookie cPsw=new Cookie("psw",psw);
cPsw.setMaxAge(600);
response.addCookie(cName);
response.addCookie(cPsw);
response.sendRedirect("index.jsp");
}
else{%>
<%=info%>,<a href="login.htm">请重新登录</a>
<%}%>
Session对象
应用:用户登录-注销
生存周期:浏览器关闭。
为啥发明session:
客户端访问服务器,服务器产生唯一的SessionID,用于 标记一次访问。
专门用于身份验证。
命名空间:javax.servlet.http.HttpSession
sessionID产生和 获取
产生:服务端收到request之后,即产生session
获取:session.getId();
或者request.getCookies[“JSESSIONID”]
在客户端,sessionID被存储在Cookie中
session登录和注销
评定:
类别 |
思路 |
比较 |
Cookies进行登录校验 |
(1)login.jsp中,遍历Cookies,判断usr是否存在。 不存在,进行登录àreponse.AddCookie(“usrid”,usr) à跳转到index.jsp,index.jsp中取Cookie(“usrid”),存在,则允许访问;不存在,则跳转到登录页
不存在à登录 |
可设置时间长度。 |
Session进行登录校验 |
(1)login.jsp中, session.getAttribute(“usrid”)存在 则跳转到index.jsp页; 不存在,则进行验证。验证完成 session.setAttribute(“usrid”)。跳转到页面index.jsp
|
比Cookie少一次遍历。
|
摘要:
设置session |
session.setAttribute(“uid”,usrName) |
获取session |
session.getAttribute(“uid”) |
清空session(注销) |
session.invalidate() |
客户端 延时跳转 |
response.setHeader(“refresh”,”3;url=login.jsp”) |
客户端 立即跳转 |
reponse.sendRedirect(“login.jsp”) |
代码:
login.jsp
<%@ page language="Java" contentType="text/html;" pageEncoding="GBK"%>
<form action="login.jsp" method="post">
<table>
<tr><td colspan=2>登录系统</td><td></td></tr>
<tr><td>用户名</td><td><input type="text" name="usr"></td></tr>
<tr><td>密码</td><td><input type="password" name="psw"/></td></tr>
<tr><td colspan=2><input type="submit" value="登录"></td><td></td></tr>
</table>
</form>
<% if(session.getAttribute("uid")!=null){
response.addHeader("refresh","index.jsp;");
}
String usr=request.getParameter("usr");
String psw=request.getParameter("psw");
String info="";
if(usr!=null){
if(usr.equals("test")){
if(psw.equals("test")){
info="true";
}
else{
info="密码无效";
}
}
else{info="用户名不存在"; }
if(info.equals("true")){
session.setAttribute("uid",usr);
response.sendRedirect("index.jsp");
}
else{%>
<b><%=info%></b>
<%}
}%>
index.jsp
<%@ page language="Java" contentType="text/html;" pageEncoding="GBK"%>
<%//注销分支
String t=request.getParameter("t");
if(t!=null&&t.equals("0")){
session.invalidate();
response.sendRedirect("login.jsp");
return;
}
%>
<% //校验分支
String uid=(String)session.getAttribute("uid");
if(uid==null){
response.setHeader("refresh","3;url=login.jsp");%>
<b>尚未登录系统..
<span id="spT">3</span>
<script type="text/javascript">
var count=2;
setInterval(function(){
document.getElementById("spT").innerHTML=count;
count--;
},1000);
</script>s后跳转到登录页</b></br><a href="login.jsp">点击登录系统</a>
<%}else{%>
<b>欢迎,<%=uid%></b></br>
<a href="index.jsp?t=0">点击此处注销</a>
<%}
%>
4种会话跟踪
表单隐藏 和 地址重写 不安全。
结论:使用session 活着Cookie进行 会话跟踪。
session记录 用户的登录 注销时间
摘要:
session建立的时间 |
session.getCreationTime() |
session结束的时间 |
session.getLastAccessedTime() |
<%@ page contentType="text/html;" pageEncoding="GBK"%>
<%
long start=session.getCreationTime();
long end=session.getLastAccessedTime();
long time=(end-start)/1000;
response.setHeader("refresh","1;url=test.jsp");
%>
您已经在页面上提留了<%=time%>秒
isNew()判断新session
application对象(this.getServerletContext)
所属类:javax.servlet.ServletContext
备注:this.getServletContext() 等价于application
代表:整个虚拟目录 (test1)
取虚拟目录绝对路径
摘要:
this.getServletContext().getRealPath("/") |
<%@ page contentType="text/html;" pageEncoding="GBK"%>
虚拟目录绝对路径:<%=this.getServletContext().getRealPath("/")%></br>
写文件内容
摘要:
引用的jar |
import=”java.io.*” |
初始化File对象 |
File file=new File(path) |
判断目录存在 |
file.getParentFile().exists() |
创建目录 |
file.getParentFile().mkdir() |
写入内容 |
PrintStream ps=new PrintStream(new FileOutputStream(file)); ps.println(fC); ps.close(); fos.close(); |
代码:
test.jsp
<%@ page contentType="text/html;" pageEncoding="GBK"%>
<form action="file.jsp" method="post">
<table>
<tr><td>输入文件名</td><td><input type="text" name="fNa" value="file.txt"></td></tr>
<tr><td>文件内容</td><td><textarea name="fCo" style="height:200px"></textarea></td></tr>
<tr><td colspan=2><input type="submit" value="保存"><input type="reset" value="清空"></td><td></td></tr>
</table>
</form>
<%%>
file.jsp
<%@ page contentType="text/html;" pageEncoding="GBK" import="java.io.*"%>
<%
request.setCharacterEncoding("GBK");
String fN=request.getParameter("fNa");
String fC=request.getParameter("fCo");
String fPath=this.getServletContext().getRealPath("/")+"\\files\\"+fN;
File file=new File(fPath);
if(!file.getParentFile().exists()){
file.getParentFile().mkdir();
}
FileOutputStream fos=new FileOutputStream(file);
PrintStream ps=new PrintStream(fos);
ps.println(fC);
ps.close();
fos.close();
%>
fN:<%=fN%></br>
fC:<%=fC%></br>
fPath:<%=fPath%></br>
读文件
摘要:
FileInputStream存文件内容 |
FieInputStream fiStr= new FileInputStream(this.getServletContext().getRealPath("/")+"\\files\\file.txt") |
Scanner逐行取FileInputStream |
Scanner scan=new Scanner(fiStr) |
遍历Scan,内容存到String中 |
String co=""; while(scan.hasNext()){//逐行读取 co+=scan.next(); } scan.close(); fis.close(); |
备注:
文件内容过长时,使用
StringBuffer buf=new StringBuffer();
buf.append(scan.next());
test.jsp
<%@ page contentType="text/html;" pageEncoding="GBK" import="java.util.*" import="java.io.*"%>
<%
FileInputStream fis=new FileInputStream(this.getServletContext().getRealPath("/")+"\\files\\file.txt")
Scanner scan=new Scanner(fis);
scan.useDelimiter("\n");//使用换行符
StringBuffer buf=new StringBuffer();
while(scan.hasNext()){//逐行读取
buf.append(scan.next());
}
scan.close();
fis.close();
%>
<form action="file.jsp" method="post">
<table>
<tr><td>文件内容</td><td><textarea name="fCo" style="height:200px"><%=buf%></textarea></td></tr>
<tr><td colspan=2><input type="submit" value="保存"><input type="reset" value="清空"></td><td></td></tr>
</table>
</form>
<%%>
效果:
访量计数器
思路:
访客总数写到count.txt中
每当session.isNew()时,打开count.txt,取数并加1,保存,返回新数。
摘要:
调试方法,在eclipse的console下进行。比用哪日志快2h
读文件和写文件
BigInteger 来记录数值
test.jsp
<%@ page contentType="text/html;" pageEncoding="GBK" import="java.util.*"%>
<%@ include file="fOper.jsp"%>
<%
String path=this.getServletContext().getRealPath("/")+"\\files\\count.txt";
BigInteger newNum;
if(session.isNew()){
synchronized(this){//同步操作,原因不详
newNum=load(path);
newNum=newNum.add(new BigInteger("1"));
save(path,newNum);
}
}
else{
newNum=load(path);
}
%>
您是第<b><%=newNum%></b>个访;
fOper.jsp
<%@ page pageEncoding="GBK" import="java.io.*"%>
<%@ page import="java.util.*"%>
<%@ page import="java.math.BigInteger"%>
<%!
public static void save(String path,BigInteger count){
try{
FileOutputStream fos=new FileOutputStream(path);
PrintStream ps=new PrintStream(fos);
ps.println(count);
ps.close();
fos.close();
}
catch(Exception e){
e.printStackTrace();
return;
}
}
//测试,在eclipse下进行.
public static BigInteger load(String path){
try{
FileInputStream fis=new FileInputStream(path);
Scanner scan=new Scanner(fis);
scan.useDelimiter("\n");//使用换行符
BigInteger count=new BigInteger("0"); //can't use 0 for para
while(scan.hasNext()){//逐行读取
count=new BigInteger(scan.nextLine().trim());
}
scan.close();
fis.close();
return count;
}
catch(Exception e){
e.printStackTrace();
return new BigInteger("0");
}
}
%>
getAttributeNames 遍历属性
摘要:
获取AttrNames |
this.getServletContext().getAttributeNames() Enumeration |
获取某个attr的值 |
this.getServletContext().getAttribute(name) |
<%@ page contentType="text/html;" pageEncoding="GBK"%>
<%@ page import="java.util.*"%>
<%
Enumeration es=this.getServletContext().getAttributeNames();
while(es.hasMoreElements()){
String na=(String)es.nextElement();
%>
Name:<%=na%>,Value:<%=this.getServletContext().getAttribute(na)%></br>
<%}%>
config对象
命名空间:javax.servlet.ServletConfig
代表:web.xml对象的init-param
取DbDriver, DbUrl, usr, psw. 参见 web.xml配置
PageContext对象
pageContext的等价操作
page.Context |
相同 |
pageContext.forward("login.jsp");
|
<jsp:forward page="login.jsp"></jsp:forward> |
pageContext.include("login.jsp"); |
<jsp:include page="login.jsp"></jsp:include> |
pageContext.getServletConfig() |
config |
|
|
不等价
pageContext.getServletRequest()取的对象是HttpServletRequest,不是request。
pageContext.getServletResponse()取的对象是HttpServletResponse,不是response.
备注:
pageContext在 jsp标签开发中 常见。很少直接使用。
JavaBean 规范 C7
为啥有JavaBean规范?
将Class写成 JavaBean组件,提高开发效率。
JavaBean被谁用?
Servlet和JSP.
JavaBean 规范的内容(对class)
1. Class必须放在某个Package中
2. Class必须用public声明
3.Class必须包含无参数构造函数
4. 属性必须用private声明
5. 要被外界操作的属性,则必须声明setter和Getter
6 属性必须用小写字母开头(很重要!,否则jsp:setProperty 无法自动赋值属性)
上述5条都满足的class, 即符合JavaBean 的Class.
JavaBean的类别
1 |
简单JavaBean |
只包含 属性,setter,getter |
2 |
POJO |
|
3 |
VO |
|
4 |
TO |
属性,setter,getter, Serializable接口 |
简单javaBean
备注: Java默认生成不带参数的构造函数
class Person{
private String name;
private int age;
public Person(){};
public void setName(String name){
this.name=name;
}
public String getName(){
return this.name;
}
public void setAge(int age){
this.age=age;
}
public int getAge(){
return this.age;
}
}
打包 和 调用两种方式
摘要
打包 |
方法1:export jar包 方法2:javac –d 目录 最后,扔到classes目录下 |
调用 |
方法1:在jsp页面中 import=”pkg.*” 方法2: <jsp:useBean class="pkgTest.Person" id="p1" scope="page"></jsp:useBean> scope的取值:page, request, session, application
|
import Jar调用JavaBean
<%@ page language="Java" pageEncoding="GBK" import="pkgTest.*"%>
<%
Person p1=new Person();
p1.setName("高承荀");
p1.setAge(26);
%>
姓名:<%=p1.getName()%><br></br>
年龄:<%=p1.getAge() %>
jsp:useBean class=”” scope=”page” id=”objName”
<%@ page language="Java" pageEncoding="GBK""%>
<jsp:useBean class="pkgTest.Person" id="p1" scope="page"></jsp:useBean>
姓名:<%=p1.getName()%><br></br>
年龄:<%=p1.getAge() %>
jsp useBean-Property 简化表单映射
摘要:
原始 |
jsp loop{ //n次 obj.setPropertiy(request.getParameter) } |
jsp:setProperty name=javaBeanId property=”*” |
两句将表单中所有 name值映射到 obj对应property上 |
备注:Model必须符合JavaBean规范6条。否则赋值为null
login.htm
<!DOCTYPE HTML>
<html>
<head></head>
<body>
<form action="test.jsp" method="post">
<div>姓名:<input type="text" name="name" value="高承荀"></div>
<div>年龄:<input type="text" name="age" value="26"></div>
<div>邮箱:<input type="text" name="email" value="1695539064@qq.com"></div>
<div><input type="submit" value="提交"></div>
</form>
</body>
</html>
test.jsp
<%@ page language="Java" pageEncoding="GBK"%>
<% request.setCharacterEncoding("GBK");%>
<jsp:useBean class="pkgTest.Person" id="p1" scope="page"></jsp:useBean>
<jsp:setProperty name="p1" property="*"/>
姓名:<%=p1.getName()%></br>
年龄:<%=p1.getAge()%></br>
邮箱:<%=p1.getEmail()%>
jsp:setPropery 4种设置方式
1 |
property=”*” |
自动 name-property映射 |
2 |
property=”属性名” |
只为某property赋值 |
3 |
property=”属性名” param=”参数名” |
property 获得指定 name值 |
4 |
property=”属性名” value=”内容” |
perperty获得value值 |
只为某property赋值
<%@ page language="Java" pageEncoding="GBK"%>
<% request.setCharacterEncoding("GBK");%>
<jsp:useBean class="pkgTest.Person" id="p1" scope="page"></jsp:useBean>
<jsp:setProperty name="p1" property="name"/>
姓名:<%=p1.getName()%></br>
年龄:<%=p1.getAge()%></br>
邮箱:<%=p1.getEmail()%>
效果
property 获得指定 name值
<jsp:useBean class="pkgTest.Person" id="p1" scope="page"></jsp:useBean>
<jsp:setProperty name="p1" property="name" param="age"/>
<jsp:setProperty name="p1" property="email" param="name"/>
姓名:<%=p1.getName()%></br>
年龄:<%=p1.getAge()%></br>
邮箱:<%=p1.getEmail()%>
姓名:26
年龄:0
邮箱:高承荀
property获得指定value值
<jsp:useBean class="pkgTest.Person" id="p1" scope="page"></jsp:useBean>
<jsp:setProperty name="p1" property="name" value="姓名"/>
<jsp:setProperty name="p1" property="age" value="123"/>
<jsp:setProperty name="p1" property="email" value="jjkjkkj"/>
姓名:<%=p1.getName()%></br>
年龄:<%=p1.getAge()%></br>
邮箱:<%=p1.getEmail()%>
姓名:姓名
年龄:123
邮箱:jjkjkkj
jsp:getPropery 获取属性
摘要
取obj某个property |
<jsp:getProperty name=”objID” property=”属性名”/> |
效果等价于<%=obj.getProperty()%>
<jsp:setProperty name="p1" property="name" value="姓名"/>
姓名:<jsp:getProperty name="p1" property="name"/>
姓名:姓名
JavaBean scope 属性
描述:obj的生存周期
1 |
page |
页面内有效,跳转后失效。 |
2 |
request |
请求内有效。(如果服务器端跳转到b.jsp,则b.jsp中有效)。 回应完请求则失效。 |
3 |
session |
一次会话内有效。 浏览器关闭失效。 |
4 |
application |
保存在服务器上。 服务器重启/关闭 失效。 |
删除JavaBean
摘要
序号 |
scope |
删除语句 |
1 |
page |
pageContext.removeAttribute(id); |
2 |
request |
request.removeAttribute(id); |
3 |
session |
session.removeAttribute(id); |
4 |
application |
application.removeAttribute(id); |
应用- 注册功能
索引:Page 200
蓝图
详情:jspCode\register
摘要:
1 |
index.jsp 同时具备显示空白和提示功能 |
<%@ page language="Java" pageEncoding="GBK"%> <jsp:useBean id="person" scope="request" class="pkgTest.Person"></jsp:useBean> <form action="check.jsp" method="post"> <div>姓名:<input type="text" name="name" value="<%=person.getName()%>"/><%=person.getError("nameEr")%></div> <div>年龄:<input type="text" name="age" value="<%=person.getAge()%>"/><%=person.getError("ageEr")%></div> <div>邮箱:<input type="text" name="email" value="<%=person.getEmail()%>"/><%=person.getError("emailEr")%></div> <div><input type="submit" value="提交"></div> </form>
//构造函数中,默认设置Name,Age,Email为空; JavaBean的无参数构造函数~ //getError中默认如果取到的是null,则返回”” |
2 |
check.jsp 引用index.jsp中的javaBean对象 |
<jsp:useBean class="pkgTest.Person" id="person" scope="request"></jsp:useBean> <jsp:setProperty name="person" property="*"></jsp:setProperty>
|
3 |
person.java中将age设置成String
|
private String name; private String age; private String email; private Map<String,String> errors=null;
//好处:所有项都能用Regex校验 //JavaBean的set,get不会出现type不匹配 |
4 |
无参数构造函数 |
public Person(){ this.name=""; this.age=""; this.email=""; this.errors=new HashMap<String,String>(); }; |
5 |
Map和HashMash 表示 [{key,value}] |
//添加 errors.put("emailEr", "邮箱格式不正确"); //获取 this.errors.get(key) //Map是一个 [{key,value}] //这样初始化this.errors=new HashMap<String,String>(); |
6 |
正则验证 |
姓名:if(!this.name.matches("\\w{6,15}")){ 年龄:if(!this.age.matches("\\d+")){ 邮箱:if(!this.email.matches("\\w+@\\w+\\.\\w+\\.?\\w*")){
|
7 |
两种实现思路 |
第1: index.htm+Servlet 第2: index.jsp+check.jsp
index.jsp 和check.jsp 间使用服务端跳转 到出错页 check.jsp和index.jsp间使用服务端跳转
|
Web开发模式
JSP-JavaBean-数据库 模式
摘要:
JSP单职责模式
层 |
职责 |
缺点 |
JSP |
显示,流程控制 |
流程控制和前端在一起。 维护困难。 |
JavaBean |
数据库操作 |
|
数据库 |
|
|
MVC模式
Model-View-Controller
Model层 |
JavaBean类。 |
View层 |
JSP页。 接收Servlet内容,生成和显示数据。 |
Controller层 |
处理所有http请求。 解析参数,进行流程控制。 |
关键:
Servlet中requestDistpatcher(“test.jsp”).forward(request,response)
Servlet到jsp使用request记录属性
MVC模式下,JSP的4规范
目的:确保jsp简洁,
1. 接收属性
2. 判断属性存在,流程控制
3. 使用迭代或者Model进行输出
4. 只许import “java.util.*”包
应用 MVC模式 的登录功能
//不足:(1)界面不美观(2)未加密post (比ajaxHtm+Servlet+JavaBean的MVC)
//作战目的: 熟悉 JSP+Servelet+JavaBean的MVC
记住 JSP页面的4个规范
数据库准备
使用Account数据库
代码清单
ClsDbConfig |
数据库配置(driver,url,usr,psw) 取得Connection 关闭Connection |
成员: private,... private Connection conn
方法: public Connection getConnection |
ClsDbOper |
|
方法: public static boolean checkAccount |
Account |
JavaBean |
成员: ID,usrName,password Map<String,String>
方法: public boolean isValidate() public String getError(String key)
|
svt
|
接收requestParameter 调用isValidate -- case 校验不通过, req.setAttribute(“info”,info); request.getRequestDispatcher(“test.jsp”) .forward(req,res);
case 校验通过,isValidate未通过 req.setAttribute(“info”,info) req.getRequestDispatcher(“url”) .forward(req,res)
case 校验通过,isValidate通过 session.setAttribute(“uid”,uid) response.sendRedirect(url); -- |
|
login.jsp
|
登录界面 错误提示 输入校验 |
|
index.jsp |
校验session(“uid”) case通过:欢迎 case未通过: response.sendRedirect(“login.jsp”)
|
|
作战开始:14:23
完成时间:16:18
2h
设计模式
数据访问- DAO模式
DAO: Data Access Object
功能:实现CRUD功能
各层的功能
类别 |
功能 |
编码规则 |
客户层 |
浏览器(B/S架构) |
|
显示层 |
JSP/Servlet页面效果显示。 |
|
业务层 |
从客户的角度,就是一个功能。 从代码的角度,就是调用一组数据层函数。 |
|
数据层 |
CRUD操作。 直接操作数据库 |
DAO类军规: 1.DAO类名与表名相同 2.DAO类添加,更改,删除 以 do开头。 举例: Emp doCreat(Emp) Emp doUpdate(Emp) boolean doDelete(int ID)
3.DAO类查询 以find, get开头 List<Emp> doFind(String key) Emp doGet(int ID)
Model类军规: Model类JavaBean规范
|
应用 DAO-雇员管理系统
战斗序列:
数据库设计
(1)字段-类型-约束
(2)创建表-添加数据
Model类设计
(1)类名同表名
(2)JavaBean规范开发Model类
DataConnection类设计
(1)定义Driver,DbUrl,usr,psw
(2)实现getConnection()和close方法
DAO类设计
数据库设计
名 |
类型 |
约束 |
ID |
Number |
主键,自增 |
Name |
varchar(10) |
非空 |
Job |
varchar(9) |
非空 |
EmpDate |
varchar(10) |
雇佣日期 |
sal |
number |
薪水 |
min 10
Model类设计
package pkgEmp;
import java.util.HashMap;
import java.util.Map;
public class Emp{
private int id;
private String name;
private String job;
private String empDate;
private String salary;
private Map<String,String> errors=null;
public Emp(){
this.id=-1;
this.name="";
this.job="";
this.empDate="";
this.salary="";
this.errors=new HashMap<String,String>();
}
public boolean isValidate(){
boolean flag=true;
if(!this.name.matches("\\w{2,10}")){
flag=false;
this.errors.put("erN","姓名长度必须是2~10");
System.out.println("Name:"+this.name+". erN,姓名长度必须是2~10");
return flag;
}
if(this.job!=null&&this.job.length()==0){
flag=false;
this.errors.put("erJ","工作不能为空");
System.out.println("erJ工作不能为空");
return flag;
}
if(!this.salary.matches("\\d+")){
flag=false;
this.errors.put("erS","薪水必须是数值");
System.out.println("erS薪水必须是数值");
return flag;
}
System.out.println(flag);
return flag;
}
public String getError(String key){
if(this.errors.get(key)==null){return "";}
return this.errors.get(key);
}
public int getID(){
return this.id;
}
public void setID(int id){
this.id=id;
}
public String getName(){
return this.name;
}
public void setName(String str){
this.name=str;
}
public String getJob(){
return this.job;
}
public void setJob(String str){
this.job=str;
}
public String getEmpDate(){
return this.empDate;
}
public void setEmpDate(String str){
this.empDate=str;
}
public String getSalary(){
return this.salary;
}
public void setSalary(String str){
this.salary=str;
}
}min5
DbConnection类
private DbDriver |
|
private DbUrl |
|
private Usr |
|
private Psw |
|
public static getCoonection |
return this.conn |
public class DbConnection {
public static final String DbDriver="oracle.jdbc.driver.OracleDriver";
public static final String DbUrl="jdbc:oracle:thin:@localhost:1521:orcl";
public static final String Usr="test";
public static final String Psw="test";
public static Connection getConnection() throws ClassNotFoundException, SQLException{
Connection con=null;
Class.forName(DbDriver);
con=DriverManager.getConnection(DbUrl, Usr, Psw);
return con;
}
}
min 10
DAO类设计
public Emp doCreate(Emp emp) |
public List<Emp> find(String key) |
public Emp getById(int ID) |
public static Emp doCreate(Emp emp) throws ClassNotFoundException, SQLException{
Connection con=DbConnection.getConnection();
String sqlStr="insert into emp(Name,Job,EmpDate,Salary) values('"+emp.getName()+"','"+emp.getJob()+"','"+emp.getEmpDate()+"',"+emp.getSalary()+") returning ID into :1";
OraclePreparedStatement pstmt =(OraclePreparedStatement)con.prepareStatement(sqlStr);
pstmt.registerReturnParameter(1, Types.NUMERIC);
pstmt.executeUpdate();
ResultSet rs=pstmt.getReturnResultSet();
rs.next();
emp.setID(rs.getInt(1));
rs.close();
pstmt.close();
con.close();
return emp;
}
public static List<Emp> find(String key) throws ClassNotFoundException, SQLException{
List<Emp> li=new ArrayList<Emp>();
Connection con=DbConnection.getConnection();
String sqlStr="select ID,Name,Job,EmpDate,Salary from emp";
if(!key.equals("")){sqlStr+=" where Name like '%"+key+"%'";}
Statement stmt=con.createStatement();
ResultSet rs=stmt.executeQuery(sqlStr);
while(rs.next()){
Emp emp=new Emp();
emp.setID(rs.getInt("ID"));
emp.setName(rs.getString("Name"));
emp.setJob(rs.getString("Job"));
emp.setEmpDate(rs.getString("EmpDate"));
emp.setSalary(rs.getString("Salary"));
li.add(emp);
}
return li;
}
public static Emp getById(int ID) throws SQLException, ClassNotFoundException{
Connection con=DbConnection.getConnection();
String sqlStr="select ID,Name,Job,EmpDate,Salary from emp where ID="+ID;
Statement stmt=con.createStatement();
ResultSet rs=stmt.executeQuery(sqlStr);
Emp emp=new Emp();
while(rs.next()){
emp.setID(rs.getInt("ID"));
emp.setName(rs.getString("Name"));
emp.setJob(rs.getString("Job"));
emp.setEmpDate(rs.getString("EmpDate"));
emp.setSalary(rs.getString("Salary"));
}
return emp;
}
min20
测试DAO
/*
for(int i=0;i<=4;i++){
Emp emp=new Emp();
emp.setName("李兴华"+i);
emp.setJob("程序员"+i);
emp.setEmpDate("2012-01-0"+i);
emp.setSalary(String.valueOf(1000*(i+2)));
doCreate(emp);
}*/
/*
List<Emp> emps=find("李");
for(int i=0;i<=emps.size()-1;i++){
System.out.println(emps.get(i).getName());
}
*/
/*
Emp emp=getById(2);
System.out.println(emp.getName());
*/
min10
Jsp 添加
insert.jsp |
字段信息输入,提示信息错误 |
doCreate.jsp |
校验信息,执行添加。 添加成功则显示。 添加失败则跳转到insert.jsp并提示错误。 |
insert.jsp
<%@ page language="Java" pageEncoding="GBK"%>
<%request.setCharacterEncoding("GBK");%>
<jsp:useBean id="emp" class="pkgEmp.Emp" scope="request"/>
<form action="doCreate.jsp" method="post">
<table>
<tr><td>姓 名</td><td><input type="text" name="name" value="<%=emp.getName()%>"/></td><td><%=emp.getError("erN")%></td></tr>
<tr><td>职 位</td><td><input type="text" name="job" value="<%=emp.getJob()%>"/></td><td><%=emp.getError("erJ")%></td></tr>
<tr><td>受聘日期</td><td><input type="text" name="empDate" value="<%=emp.getEmpDate()%>"/></td><td><%=emp.getError("erE")%></td></tr>
<tr><td>薪 资</td><td><input type="text" name="salary" value="<%=emp.getSalary()%>"/></td><td><%=emp.getError("erS")%></td></tr>
<tr><td colspan=3><input type="submit" value="提交"/></td></tr>
</table>
</form>
doCreate.jsp
<%@ page language="Java" pageEncoding="GBK" import="pkgEmp.*"%>
<%request.setCharacterEncoding("GBK");%>
<jsp:useBean class="pkgEmp.Emp" id="emp" scope="request"/>
<jsp:setProperty name="emp" property="*"/>
<%if(emp.isValidate()){
Emp emp2=DbOper.doCreate(emp);
if(emp2.getID()!=-1){%>
<h1>添加成功</h1>
姓名:<%=emp2.getName()%><br/>
工作:<%=emp2.getJob()%><br/>
受聘日期:<%=emp2.getEmpDate()%><br/>
薪水:<%=emp2.getSalary()%>
<%}else{%>
<jsp:forward page="insert.jsp"/>
<%}%>
<%}else{%>
<jsp:forward page="insert.jsp"/>
<%}%>
Jsp显示
list.jsp |
查询关键字输入框 -- table显示信息 |
list.jsp
<%@ page language="Java" pageEncoding="GBK" import="pkgEmp.*"%>
<%@ page import="java.util.*" %>
<%
request.setCharacterEncoding("GBK");
String key="";
key=request.getParameter("key")==null?"":request.getParameter("key");
List<Emp> emps=DbOper.find(key);
String dataStr="";
%>
<form action="emp_list.jsp" method="post">
<div>请输入查询关键字:<input type="text" value="" name="key"/><input type="submit" value="查询"></div>
<table border=1><tr><td>姓名</td><td>工作</td><td>入职日期</td><td>薪资</td></tr>
<%for(int i=0;i<=emps.size()-1;i++){ %>
<tr><td><%=emps.get(i).getName()%></td><td><%=emps.get(i).getJob()%></td><td><%=emps.get(i).getEmpDate()%></td><td><%=emps.get(i).getSalary()%></td></tr>
<%}%>
</table>
</form>
文件上传
smartUpload手册
参考jspsmartupload.zip
图片上传
jar包:jspSmartUpload.jar
特点:(1)可限制类型
(2)获取文件名、类型、尺寸
额外依赖:
jsp-api.jar (tomcat自带)
servlet-api.jar (tomcat自带)
备注:放在lib目录下
摘要:
(1)表单中使用 <input type=”file” name=””/>上传
项 |
任务 |
upload.htm |
(1) <input type=”file” name=””/> input标签 上传 (2) form action=”su” 指向svt |
pkgUpload.ClsUpload |
(1)取文件-检查合法性-保存-页面跳转
|
依赖项 |
(1)jsp-api.jar (2)servlet-api.jar (3)jspSmartUpload.jar
|
upload.htm
<HTML>
<BODY BGCOLOR="white">
<H1>jspSmartUpload : Sample 1</H1>
<HR>
<FORM METHOD="POST" ACTION="su" ENCTYPE="multipart/form-data">
<INPUT TYPE="FILE" NAME="FILE1" SIZE="50"><BR>
<INPUT TYPE="SUBMIT" VALUE="Upload">
<input type="text" name="info" value="test photp"/>
</FORM>
</BODY>
</HTML>
ClsUpload.java
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//存储路径
String filePath = "F:\\Workspaces\\UI05\\UI05\\WebContent\\upload\\";
String messages="";
String forward="";
SmartUpload su = new SmartUpload();
long maxsize = 2 * 1024 * 1024;// 设置大小,为2MB
String allowedFilesList = "jpg,gif,bmp,png";//允许文件
//拒绝文件
String denidFilesList = "exe,bat,jsp,htm,html,,";
try {
su.initialize(this.getServletConfig(), request, response); //初始化
su.setMaxFileSize(maxsize); // 限制上传文件的大小
su.setAllowedFilesList(allowedFilesList); // 设置允许上传的文件类型
su.setDeniedFilesList(denidFilesList);
su.upload(); // 上传文件
// 获取上传的文件,因为只上传了一个文件,所以可直接获取
File file = su.getFiles().getFile(0);
// 如果选择了文件
if (!file.isMissing()) {
//获取当前时间并格式化为字符串
String now = new Date().getTime() + "";
//filePath值
String photoAddr=filePath + now + "."+file.getFileExt();
System.out.println(photoAddr);
file.saveAs(photoAddr,File.SAVEAS_PHYSICAL);
}else{
System.out.println("file is Missing()");
messages="请选择要上传的文件!";
forward="/admin/error.jsp";
}
}catch (java.lang.SecurityException e){
System.out.println("上传失败82");
messages="<li>上传文件失败!上传的文件类型只允许为:jpg,gif,bmp</li>";
forward="/admin/error.jsp";
}catch (SmartUploadException e) {
System.out.println("上传失败86");
messages="上传文件失败!";
forward="/admin/error.jsp";
e.printStackTrace();
} catch (SQLException e) {
System.out.println("92");
e.printStackTrace();
}
request.setAttribute("messages",messages);
request.getRequestDispatcher(forward).forward(request, response);
}
}
混合表单处理
背景:客户端form中包含照片 和 备注信息
摘要:
SmartUpload su = new SmartUpload();
su.initialize(this.getServletConfig(),request, response);
su.setAllowedFilesList("jpg,gif,bmp,png");//允许文件
su.setMaxFileSize(2 * 1024 * 1024);// 设置大小,为2MB
su.getRequest.getParameter(“info”) |
取备注信息 |
su.getFiles().getFile(0) |
取文件 |
htm
<!Doctype HTML>
<html><head><meta charset="GBK"/></head>
<body>
<form action="sa" method="post" enctype="multipart/form-data">
<table><tr><td>姓名</td><td><input type="text" name="name"/></td></tr>
<tr><td>照片</td><td><input type="file" name="photo"/></td></tr>
<tr><td colspan=2><input type="submit" value="提交"/><input type="reset" value="重置"/></td></tr>
</table>
</form>
</body>
</html>
svt:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("GBK");
SmartUpload su = new SmartUpload();
su.initialize(this.getServletConfig(),request, response);
su.setAllowedFilesList("jpg,gif,bmp,png");//允许文件
su.setMaxFileSize(2 * 1024 * 1024);// 设置大小,为2MB
Map<String,String> info=new HashMap<String,String>();
try {
su.upload();
} catch (SmartUploadException e1) {
e1.printStackTrace();
info.put("false", "上传发生错误");
}
String name=su.getRequest().getParameter("name");
File fi=su.getFiles().getFile(0);
if(!info.isEmpty()){
request.setAttribute("failReason",info.get("false"));
request.getRequestDispatcher("/re.jsp").forward(request,response);
return;
}
String fiName=new Date().getTime()+"."+fi.getFileExt();
System.out.println(fiName);
try {
fi.saveAs(this.getInitParameter("dirPic")+"\\"+fiName,File.SAVEAS_PHYSICAL);
} catch (SmartUploadException e) {
e.printStackTrace();
request.setAttribute("failReason","保存发生错误");
request.getRequestDispatcher("/re.jsp").forward(request,response);
return;
}
request.removeAttribute("failReason");
System.out.println(name);
request.setAttribute("name",name);
//request.setAttribute("url","/pics/"+fiName);//host/pics/
request.setAttribute("url","pics/"+fiName);//host/vir/pics
request.getRequestDispatcher("/re.jsp").forward(request,response);
return;
}
re.jsp
<%@ page language="Java" contentType="text/html" pageEncoding="GBK"%>
<% if(request.getAttribute("failReason")!=null){%>
<b>保存失败,原因:</b><h3><%=request.getAttribute("failReson")%></h3>
<%}else{%>
<b>保存成功</b>
<div>姓名:<%=request.getAttribute("name")%></div>
<div><img alt="照片" src="<%=request.getAttribute("url")%>"/></div>
<% }%>
Servlet
背景知识
Servlet本质 |
继承了HttpRequest的 java类。 它是一个.java文件 |
依赖项 |
将tomcat/lib/servlet-api.jar拷贝到Web-inf/lib目录下 |
结构 |
pkgSvt ClsSvt |
引用 |
Export jar到: WebContent/WEB-INF/classes |
web.xml映射 |
<web-app> <servlet> <servlet-name>sA</servlet-name> <servlet-class>pkgSvt.ClsSvt</servlet-class> </servlet> <servlet-mapping> <servlet-name>sA</servlet-name> <url-pattern>pkgSvt.ClsSvt</url-pattern> <servlet-mapping> </web-app> |
|
|
svt比CGI的优势
svt多线程, 项目比CGI高。
第一个Servlet
创建Servlet
1.创建servlet, 输入package Name(对应nameSpace和className(servletName)
package servletPack;
public class ReqHandler extends HttpServlet {//继承HttpServlet
备注:servletPack.ReqHandler 之后将写入 servlet-class
2.把这个java的doGet写上代码。
// TODO Auto-generated method stub
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
PrintWriter print=response.getWriter();
String result="<html><head></head><body><h1>Hello World</h1></body></html>";
print.print(result);
}
将servletPackage导出成jar,并拷贝到WebContent/Web-inf/classes目录下
web-inf\web.xml 配置信息
在Web-Inf的Web.xml中添加请求映射
<?xml version="1.0" encoding="utf-8"?>
<web-app>
<servlet>
<servlet-name>SvtHello</servlet-name>
<servlet-class>pkgResiCrud.SvtHello</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SvtHello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
备注:
1. <servlet>标签下的<servlet-name>与<servlet-mapping>下的<servlet-name>相同
2.s<servlet-class>写packageName.servletName
3.servlet-name不要和url-pattern完全相同,否则tomcat无法启动,譬如
<servlet-mapping>
<servlet-name>SvtHello</servlet-name>
<url-pattern>/SvtHello</url-pattern>
</servlet-mapping>
即可
访问url:
http://ip/webAppName/hello
访问url,测试
获取Ajax的postData
结论:request.getInputStream
//数据流
ServletInputStream inpStream=request.getInputStream();
//数据流总长
int dataLength=request.getContentLength();
//已读长度
int readLength=0;
//本次读取长度
int curLength=0;
//存放数据流的 byte数组
byte[] byteArr=new byte[dataLength];
while(readLength<dataLength){
curLength=inpStream.read(byteArr);
readLength+=curLength;
}
String dataString=new String(byteArr,"utf-8");
System.out.println("dataGet:"+dataString);
获取form.submit的data
结论:request.getParameter(name)
test.html:
<script>
function bindEvents(){
$("#btnTest1").on("click",function(){
$("#frmDownload")[0].action="../resiCrud";
var postData={cmd:5,data:null};
$("#inpPostData").val(JSON.stringify(postData));
$("#frmDownload")[0].submit();
});
}
</script>
<body>
<input type="button" id="btnTest1" value="getXls"/>
<form id="frmDownload" method="post" style="display:none">
<input type="text" name="postData" id="inpPostData"/>
</form>
</body>
servlet:
String postData=request.getParameter("postData");
System.out.println(postData);
获取url中的参数
结论:request.getQueryString()
test.html:
function bindEvents(){
$("#btnTest1").on("click",function(){
$("#frmDownload")[0].action="../resiCrud?para1=1¶2=2";
var postData={cmd:5,data:null};
$("#inpPostData").val(JSON.stringify(postData));
$("#frmDownload")[0].submit();
});
}
</script>
</head>
<body>
<input type="button" id="btnTest1" value="getXls"/>
<form id="frmDownload" method="post" style="display:none">
<input type="text" name="postData" id="inpPostData"/>
</form>
</body>
servlet:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
String postData=request.getParameter("postData");
System.out.println("postData:"+postData);
String queryStr=request.getQueryString();
System.out.println("queryString:"+queryStr);
....
输出结果:
postData:{"cmd":5,"data":null}
queryString:para1=1¶2=2
冲突 getParameter和getInputStream()
结论:
对象HttpServletRequest, getParameter()执行之后,会让getInputStream()的值发生改变。反之亦然。
because POST data can be read only once
解决方法:
在url中添加queryString。暗示使用getParameter还是getInputStream来获取request参数
//从form来
String queryStr=request.getQueryString();
System.out.println("queryString:"+queryStr);
//从getInputStream中取参数
if(queryStr==null){
}
//从getParameter中取参数
else if(queryStr.equals("para")){
}
取config,session, application对象
config |
this.getServletConfig() |
session |
request.getSession() |
application |
this.getServletContext() |
svt中取servlet initParam
摘要:
init-param 存在于 servlet标签下。不能直接放在web-app目录下。
一个servlet标签下可以存放多个init-param
web.xml配置 |
在对应servlet标签下 添加 <init-param> |
svt中获取 |
使用this.getServletContext.getInitParameter(“name”) |
<servlet>
<servlet-name>sA</servlet-name>
<servlet-class>pkgSu.ClsSu</servlet-class>
<init-param>
<param-name>dirPic</param-name> <param-value>F:\\Workspaces\\UI05\\UI05\\WebContent\\pics</param-value>
</init-param>
</servlet>
this.getServletContext().getInitParameter(“dirPic”)
svt 客户端跳转
response.sendRedirect("http://www.baidu.com");
svt服务端跳转
摘要:等价于 <jsp:forward page=”” />
request.getRequestDispatcher(url).forward(request, response);
参数:url-要跳转的路径。 request-传递参数,response-传递参数
Svt返回页面
摘要:
设置页面字符串 |
StringBuffer.append(“<html>...</html>”); |
response 页面字符串 |
PrinterWriter pw=reponse.getWrite(); pw.write(buf.toString()); pw.close() |
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
this.doPost(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
StringBuffer buf=new StringBuffer();
response.setCharacterEncoding("utf-8");
buf.append("<!Doctype html><html><head><meta charset='utf-8'></head><body>");
buf.append("<h1>Page write by PrinterWriter</h1><h2>测试Svt输出页</h2></body><html>");
PrintWriter pw=response.getWriter();
pw.write(buf.toString());
pw.close();//关闭响应
}
ajax,jsp,svt制作页面比较
结论:使用ajax制作页面,使用svt处理请求
方便程度排序:
Ajax>jsp>svt
代码分离程度:
Ajax>jsp>svt
思路 |
工具 |
ajax |
html,css,jq,js |
jsp |
<%%> html |
svt |
StringBuffer PriterWriter |
Servlet生命周期
阶段 |
前件 |
时间 |
初始化 int() |
(1)jar在class目录下 (2)web.xml 中servletMapping |
web容器启动时 (tomcat\bin\startup) |
服务 doGet(),doPost() |
初始化完成 |
接到http请求 |
中止,释放 destroy() |
|
以下任意: (1)web容器关闭 (2)接到卸载svt指令 |
过滤Servlet
摘要:
作用 |
限制客户对WebContent中资源的访问 |
本质 |
实现了 servlet.Filter的 java Class |
主要方法:
init() |
web容器启动时,调用FilterConfig取得配置参数 |
doFilter() |
完成过滤操作 |
destroy() |
结束过滤器,释放资源 |
ResultSet
获取记录条数
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn=DriverManager.getConnection("");
Statement std=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
String sqlStr="select * from Resident";
ResultSet rs=std.executeQuery(sqlStr);
//获取记录条数.
int rowCount=0;
rs.last();
rowCount=rs.getRow();
System.out.println("rowCount:"+rowCount);
//将cursor移到第一条
rs.first();
String result="[";
while(rs.next()){
//Todo.....
}
遍历所有字段
停用:
rs.getString(0) 值会变化,停用
使用:
rs.getString(“Name”);
正则-String
Java 正则
分组
String Str="{District:4,hyID:6,IsActivated:2}";
//(?<dVal>\\d),将\\d存储到group,dVal中
Pattern pat = Pattern.compile("District:(?<dVal>\\d),");
Matcher m = pat.matcher(Str);
while(m.find()) {
System.out.println(m.group("dVal"));//group(para),para即分组号
}
//(\\d),()将被分组,从1开始编号.读取 用m.group(1). 备注:group(0)对应整个匹配项
Pattern pat2 = Pattern.compile("District:(\\d),");
m=pat2.matcher(Str);
while(m.find()) {
System.out.println(m.group(1));//group(para),para即分组号
}
输出:
4
4
姓名-年龄-邮箱
姓名:if(!this.name.matches("\\w{6,15}")){
年龄:if(!this.age.matches("\\d+")){
邮箱:if(!this.email.matches("\\w+@\\w+\\.\\w+\\.?\\w*")){
String
replaceAll替换字符串中的所有 \”null\”
背景:rs.getString(“Address”)会将null值表示成 \”null\”.
返回给前端的JSON串要写成Address:””
String oStr="\"null\" is null";
String dStr=oStr.replaceAll("\"null\"","\"\"");
System.out.println("dString is:"+dStr);
字符串相等
在编程中,通常比较两个字符串是否相同的表达式是“==”,但在Java中不能这么写。在Java中,如果要比较a字符串是否等于b字符串,需要这么写:
if(a.equals(b)){
}
原因:
由于字符串是对象类型,而使用equals()方法比较两个对象的内容
字符串非空
if(queryStr!=null&&queryStr.length()>0){
}
字符串为空
queryStr==null|| queryStr.length()==0
String byte[]互相 转换
String str="你";
byte[] b=str.getBytes("UTF-8");
for(int i=0;i<=b.length-1;i++){
System.out.println(b[i]);
}
String back=new String(b);
System.out.println(back);
String+ 和 StringBuffer.append比较
摘要:
String +被转换成 StringBuffer执行 append操作。
编码中使用StringBuffer效率高。
public static String strPlus(String a,String b){
/* StringBuffer sA=new StringBuffer(a);
* sA.append(b);
* return sA.toString();
* */
return a+b;
}
public static String strAppend(String a,String b){
StringBuffer sb=new StringBuffer(a);
sb.append(b);
return sb.toString();
}
JSON处理
客户端JSON处理
解析responseString
即使是一个JSON对象,不用数组传回去。eval提示字符串错误。
未知原因。
建议用[]包裹字符串
将requestData 转成JSONString
var reqData={cmd:0,data:null};
JSON.stringify(reqData)
服务端JSON处理
JSON字符串和JSON对象的差异(重要)
JSON字符串,要求属性名加双引号。如果属性值是对象,对象花括号不要引号
举例:
{"Done":true,"Info":{"ID":15090,"Longitude":116.32502,"Latitude":40.00006}}
JSON对象, 属性名不要双引号
JSONView的检验能通过,但JSON.parse出错,一定是因为,有属性名没有加引号
将ResultSet写成JSON字符串
result+="{\"ID\":"+rs.getString("ID")+",\"Name\":\""+rs.getString("Name")+"\",\"Age\":"+rs.getString("Age")+",\"Job\":\""+rs.getString("Job")+"\"},";
属性名也要加引号。否则前端无法用JSON.parse转
字符串值需要加引号。
Gson 的toJSON和fromJSON
Gson由google开发
Gson gson = new Gson(); // Or use new GsonBuilder().create();
MyType target = new MyType();
//Class转Json字符串
String json = gson.toJson(target); // serializes target to Json
//Json字符串转Class
MyType target2 = gson.fromJson(json, MyType.class); // deserializes json into target2
jdbc
ojdbc位置:
Oracle安装目录
app\product\11.2.0\dbhome_1\jdbc\lib\ojdbc6.jar
放在javaProject的 src目录下。
插入 (返回最新记录)
http://blog.csdn.net/yzsind/article/details/6918506
//添加商户, 返回最新添加
public static String InsertShop(Shop shop) throws ClassNotFoundException, SQLException{
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "gxk", "gxk");
String vsql = "insert into shopmbase(ID,Num,InnerNum,Name,InstallDate,Address,Active,IsActivated) values(shm_sequence.nextval,'"+shop.Num+"','"+shop.InnerNum+"','"+shop.Name+"','"+shop.InstallDate+"','"+shop.Address+"','"+shop.Active+"','"+shop.IsActivated+"') returning ID into :1";
OraclePreparedStatement pstmt =(OraclePreparedStatement)conn.prepareStatement(vsql);
pstmt.registerReturnParameter(1, Types.NUMERIC);
pstmt.executeUpdate();
ResultSet rs=pstmt.getReturnResultSet();
rs.next();
int ID=rs.getInt(1);
rs.close();
pstmt.close();
shop.ID=ID;
return new Gson().toJson(shop);
}
更新
//更新商户
public static String UpdateShop(Shop[] shops) throws ClassNotFoundException, SQLException{
Report result=new Report();
result.Done=false;
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "gxk", "gxk");
Statement stmt=conn.createStatement();
int updated=0;
for(int i=0;i<=shops.length-1;i++){
String sqlStr="update shopmbase set Num='"+shops[i].Num+"',InnerNum='"+shops[i].InnerNum+"',Name='"+shops[i].Name+"',InstallDate='"+shops[i].InstallDate+"',CZDate='"+shops[i].CZDate+"',CLDate='"+shops[i].CLDate+"',Address='"+shops[i].Address+"',IsActivated='"+shops[i].IsActivated+"',Active='"+shops[i].Active+"',Longitude="+shops[i].Longitude+",Latitude="+shops[i].Latitude+" where ID="+shops[i].ID;
int val=stmt.executeUpdate(sqlStr);
if(val!=0){
updated++;
}
}
result.Done=true;
result.Info=updated+" of "+shops.length+" are updated";
stmt.close();
conn.close();
String report=new Gson().toJson(result);
report="["+report+"]";
System.out.println(report);
return report;
}
删除
delete from where
查询
select from where
rs.close 将触发stmt.close
说明:
rs1=stmt.executeQuery(sql1);
rs2=stmt.executeQuery(sql2);
rs2.close();//stmt也将被close()
System.out.println(rs.next()) //false; stmt.close之后,rs1.close()
Connection conn = DriverManager.getConnection(ClsDbConfig.dbUrl,ClsDbConfig.userName, ClsDbConfig.password);
Statement stmt = conn.createStatement();
String sqlStr="select distinct type from shopothattr";
/*结果
* [{attrName:"设备状态",values:[{text:'未激活',value:1}]},{attrName:"商户类型"}..]
* */
String result="[";
ResultSet rs=stmt.executeQuery(sqlStr);
while(rs.next()){
result+="{\"attrName\":\""+rs.getString("type")+"\",\"values\":[";
String sqlStr2="select id,type,value from shopothattr where type='"+rs.getString("type")+"'";
Statement stmt2 = conn.createStatement();
ResultSet rs2=stmt2.executeQuery(sqlStr2);
while(rs2.next()){
result+="{\"text\":\""+rs2.getString("value")+"\",\"value\":"+rs2.getInt("id")+"},";
}
result=result.substring(0,result.length()-1);
result+="]},";
rs2.close();
stmt2.close();
}
result=result.substring(0,result.length()-1);
result+="]";
rs.close();
stmt.close();
conn.close();
数制-编码-加密
编码-数制
byte[] 和String 互相转换
摘要:
字符串转byte[] |
byte[] b= str.getBytes(“UTF-8”) |
byte[]转字符串 |
String str=new String(b); |
String str="你好世界1234qwER~!@#$%^&*()_+";
byte[] b=str.getBytes("UTF-8");
String back=new String(b);
System.out.println(back);
char和int的转换
结论:Unicode中共65535个字符。
使用0-65535这些数字,即可表示全球所有字符。
//ASCII 字符和int互相转换
for(int i=0;i<=127;i++){ System.out.print(i+":"+(char)(i)+","+(int)((char)(i))+" ");
}
所有Unicode字符
System.out.print("\n");
for(int i=0;i<=65535;i++){
System.out.print(i+":"+(char)(i)+" ");
}
char和Unicode互相转换
本质:char和int的互相转换
Unicode:万国码
\uDFEF
\u 4个16进制位。
总共有65535种取值。
映射了全球所有字符。
备注:Java中int范围是 -21.47亿-21.47亿。
codePointAt(s) 的范围完全涵盖unicode所有值
摘要:
char转unicode,\\u+Integer.toHexString(char);
unicode转char,(char)Integer.parseInt(uni.subString(2),16);
/*unicode转字符
*/
public static char unicodeToChar(String uni){
if(!uni.subSequence(0,2).equals("\\u")){
return ' ';
}
return (char)Integer.parseInt(uni.substring(2),16);
}
/*字符转Unicode
*/
public static String charToUnicode(char c){
String result="\\u";
result+=Integer.toHexString(c);
return result;
}
String和int[]转换
应用:用户名加密发送
String usr="1234qwER你好世界";
//字符串转 int[]数组
int[] intAr=new int[usr.length()];
StringBuffer sb1=new StringBuffer();
for(int i=0;i<=usr.length()-1;i++){
intAr[i]=usr.codePointAt(i);
sb1.append(intAr[i]).append(",");
}
System.out.println(sb1.substring(0, sb1.length()-1));
//int数组转字符串
StringBuffer sb=new StringBuffer();
for(int i=0;i<=intAr.length-1;i++){
sb.append((char)intAr[i]);
}
System.out.println(sb.toString());
输出:
49,50,51,52,113,119,69,82,20320,22909,19990,30028
1234qwER你好世界
十进制-十六进制
Integer.toHexString(120);
Integer.parseInt(“8C”,16);
加密
备注:加密的基础是 编码转换
sha256加密
//hash是单向的...无解密方式
//破解方式只有一个, 尝试字符串,获得相同的hash序列,则表明明文
//结果:sha256的结果是64位字符串
public static String ShaEncrypt(String mes){
String result="";
MessageDigest digest;
try {
digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(mes.getBytes("UTF-8"));
result = Hex.encodeHexString(hash);
return result;
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
对称,unicode-偏移
摘要:
编码:将String 转成int[]数组,每个元素+10000
还原:将每个元素-10000,然后变成char
public static void main(String[] args) throws UnsupportedEncodingException{
String usr="1234qwER你好世界";
System.out.println(encodeUsr(usr,10000));
System.out.println(getUsr(encodeUsr(usr,10000),10000));
}
//从数组获取字符串
public static String getUsr(int[] arInt,int delta){
StringBuffer sb=new StringBuffer();
for(int i=0;i<=arInt.length-1;i++){
sb.append((char)(arInt[i]-delta));
}
return sb.toString();
}
//将字符串编码成数组
public static int[] encodeUsr(String str,int delta){
int[] res=new int[str.length()];
for(int i=0;i<=str.length()-1;i++){
res[i]=str.codePointAt(i)+delta;
}
return res;
}
Excel操作 (jxl)
写Excel
import java.io.File;
import jxl.*;
import jxl.write.*;
import jxl.write.biff.RowsExceededException;
public static void main(String[] args) throws IOException, RowsExceededException, WriteException {
WritableWorkbook book=Workbook.createWorkbook(new File("WebContent/test.xls"));
WritableSheet sheet=book.createSheet("fistPage", 0);
//在col0,row0添加 内容为test的cell
Label lable=new Label(0,0,"test");
sheet.addCell(lable);
//在col1,row0添加数值789.123
jxl.write.Number number=new jxl.write.Number(1,0,789.123);
sheet.addCell(number);
//保存book
book.write();
book.close();
System.out.println("Mission Done");
}
备注:文件 默认输出路径是 Workspace目录
读取Excel
public static String getShopsFromXls(String path) throws IOException, BiffException{
String result="[";
Workbook book=Workbook.getWorkbook(new File(path));
Sheet sheet=book.getSheet(0);
//遍历所有行
for(int i=1;i<=sheet.getRows()-1;i++){
result+="{No:"+i+",Num:'"+sheet.getCell(0,i).getContents()+"',InnerNum:'"+sheet.getCell(1,i).getContents()+"',Name:'"+sheet.getCell(2,i).getContents()+"',SDDate:'"+sheet.getCell(3,i).getContents()+"',CLDate:'"+sheet.getCell(4,i).getContents()+"',CZDate:'"+sheet.getCell(5,i).getContents()+"',Activated:'"+sheet.getCell(6,i).getContents()+"',Address:'"+sheet.getCell(7,i).getContents()+"',HYSH:'"+sheet.getCell(8,i).getContents()+"'},";
}
result=result.substring(0,result.length()-1);
result+="]";
return result;
}
导出InputStream
public static InputStream createExcel(String filePath) throws ClassNotFoundException, SQLException, IOException, WriteException{
String[] arrCols={"身份证","姓名","教育程度","血型","工作单位","性别","曾用名","出生日期","身高(cm)","电话","地址","民族","婚姻状况"};
String[] arrFields={"IDNUM","NAME","EDUCATION","BLOODTYPE","WORKUNIT","GENDER","OLDNAME","to_char(Birthdate,'yyyy-mm-dd') as BIRTHDATE","TALL","PHONE","ADDRESS","PEOPLE","MARRIAGE"};
String[] arrFields2={"IDNUM","NAME","EDUCATION","BLOODTYPE","WORKUNIT","GENDER","OLDNAME","BIRTHDATE","TALL","PHONE","ADDRESS","PEOPLE","MARRIAGE"};
String sqlStr="select ";
for(int i=0;i<=arrFields.length-1;i++){
sqlStr+=arrFields[i]+",";
}
sqlStr=sqlStr.substring(0, sqlStr.length()-1);
sqlStr+=" from Resident";
System.out.println(sqlStr);
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "gxk", "gxk");
Statement std=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
ResultSet rs=std.executeQuery(sqlStr);
WritableWorkbook book=Workbook.createWorkbook(new File(filePath));
WritableSheet sheet=book.createSheet("fistPage", 0);
//设置列宽 此单位非像素,比值是1:7
int[] arrWidths={23,10,10,10,32,10,10,12,11,10,10,10,10};
for(int i=0;i<=arrWidths.length-1;i++){
sheet.setColumnView(i, arrWidths[i]);
}
//表头 (colNum,rowNum)
WritableFont fontBold = new WritableFont(WritableFont.TIMES,12,WritableFont.BOLD);
WritableCellFormat headFormat=new WritableCellFormat(fontBold);
headFormat.setAlignment(jxl.format.Alignment.CENTRE);
for(int i=0;i<=arrCols.length-1;i++){
Label cell=new Label(i,0,arrCols[i],headFormat);
sheet.addCell(cell);
}
//表体
WritableFont fontNormal = new WritableFont(WritableFont.TIMES,12);
WritableCellFormat bodyFormat=new WritableCellFormat(fontNormal);
bodyFormat.setAlignment(jxl.format.Alignment.CENTRE);
int j=1;
while(rs.next()){
for(int i=0;i<=arrFields2.length-1;i++){
//System.out.println(arrFields2[i]+":"+rs.getString(arrFields2[i]));
//Label cell=new Label(i,j,rs.getString(i)); rs.getString(序号) 值会变化,停用
Label cell=new Label(i,j,rs.getString(arrFields2[i]),bodyFormat);
sheet.addCell(cell);
}
j++;
}
//保存book
book.write();
book.close();
InputStream inStream=new FileInputStream(filePath);
return inStream;
}
创建sheet
//获取4个区域的商户
public static InputStream GetRegionShops(double lon,double lat,String filePath) throws ClassNotFoundException, SQLException, IOException, RowsExceededException, WriteException{
WritableWorkbook book=Workbook.createWorkbook(new File(filePath));
String[] sheetNames={"西北区","东北区","西南区","东南区"};
//第i页
for(int i=0;i<=sheetNames.length-1;i++){
WritableSheet sheet= book.createSheet(sheetNames[i],i);
}
book.write(); //book.write如写在循环里面,只创建1sheet
book.close();
System.out.println("Excel输出完成");
InputStream inStream=new FileInputStream(filePath);
return inStream;
}
获取sheet
book.getSheet(i)
字体
//字体
WritableFont wf=new WritableFont(WritableFont.TIMES,10,WritableFont.BOLD);
WritableCellFormat cf=new WritableCellFormat(wf);
new Label(0,0,"商户内部编",cf)
设置列宽
WritableSheet.setColumnView(int i,int width);
居中
WritableFont wf=new WritableFont(WritableFont.TIMES,10,WritableFont.BOLD);
WritableCellFormat cf=new WritableCellFormat(wf);
cf.setAlignment(Alignment.CENTRE);