??xml version="1.0" encoding="utf-8" standalone="yes"?>
Junit是由 Erich Gamma ?span lang="EN-US"> Kent Beck ~写的一个回归测试框Ӟregression testing frameworkQ?span lang="EN-US">Junit是一套框Ӟl承TestCasec,可以用Junitq行自动试了?/p>
1 junitҎ?span lang="EN-US">
junit
Junit是一个开放源代码?span lang="EN-US">Java试框架Q用于编写和q行可重复的试。他是用于单元测试框架体p?span lang="EN-US">xUnit的一个实例(用于java语言Q。它包括以下Ҏ:
?用于试期望l果的断aQ?span lang="EN-US">AssertionQ?span lang="EN-US">
?用于׃n共同试数据的测试工?span lang="EN-US">
?用于方便的组l和q行试的测试套?span lang="EN-US">
?囑Ş和文本的试q行?span lang="EN-US">
叛_要用的junit的项目,点击properties—java bulid path-librariesQ点?span lang="EN-US">Add External JARs,加上JUNIT包?span lang="EN-US">
3 用法
- 创徏Q从junit.framework.TestCaseznuit test需要的test case.
- 书写试Ҏ
- ~译 书写?span lang="EN-US">test case后,~译所写的test casec?span lang="EN-US">
- q行Q启?span lang="EN-US">junit test runnner 来运行这?span lang="EN-US">test case?span lang="EN-US">
实例代码Q?span lang="EN-US">
package com.dr.test;
import java.util.List;
import junit.framework.TestCase;
import com.dr.dao.StudentDao;
import com.dr.dao.impl.StudentDaoImpl;
import com.dr.vo.Student;
public class StudentDaoImplTest extends TestCase{
StudentDao dao;
protected void setUp() throws Exception{
dao=new StudentDaoImpl();
}
protected void tearDown() throws Exception{
}
public void testAdd(){
Student stu=new Student();
stu.setName("ling");
stu.setAge(1);
stu.setEmail("ling@126.com");
dao.addStudent(stu);
}
public void testListStudent(){
List<Student> list=dao.getStudentList();
System.out.println(list.size());
}
}
Junit中的两个函数Q?span lang="EN-US">setUp?span lang="EN-US">tearDown,?span lang="EN-US">junit framework中提供初始化金额反初始化每个试Ҏ的?span lang="EN-US">setUp在每个测试方法调用前被调用,负责初始化测试方法所需要的试环境Q?span lang="EN-US">teardown在每个测试方法被调用之后被调用,负责撤销试环境?span lang="EN-US">
试l果Q?br />
?/span>JUnit的窗口中昄了一个绿条,l条证明试成功?/span>
ServletContextListener监听ServletContext。当创徏ServletContextӞȀ?/span> contextInitialized(ServletContextEvent sce)ҎQ当销?/span>ServletContextӞȀ?/span>contextDestroyed(ServletContextEvent sce)Ҏ?/span>
ServletContextAttributeListener监听?/span>ServletContext属性的操作Q比如增加、删除、修改属性?/span>
HttpSessionListener监听HttpSession的操作。当创徏一?/span>SessionӞȀ?/span>session Created(HttpSessionEvent se)ҎQ当销毁一?/span>SessionӞȀ?/span>sessionDestroyed (HttpSessionEvent se)Ҏ?/span>
HttpSessionAttributeListener监听HttpSession中的属性的操作。当?/span>Session增加一个属性时Q激?/span> attributeAdded(HttpSessionBindingEvent se) ҎQ当?/span>Session删除一个属性时Q激?/span>attributeRemoved(HttpSessionBindingEvent se)ҎQ当?/span>Session属性被重新讄ӞȀ?/span>attributeReplaced(HttpSessionBindingEvent se) Ҏ?/span>
下面我们开发一个具体的例子Q这个监听器能够l计在线的h数?br />
E序源代码:
package com.dr.web.listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
publicclass UserCountListener implements ServletContextListener,
HttpSessionListener {
//每个web应用都有且仅有一?/span>ServletContext对象Q这个对象在所有的Servlet都可以用?/span>
/**
* 因ؓ一?/span>web应用׃?/span>ServletContext 对象Q因此可以?/span>ServletContext 来做一些全局性的属性设|等?/span>
* 比如|站讉K计数器等{?/span>
*
*
* ServletContext 是一个应用程序与Web容器(tomcat之类)交互的接?/span>,同时它也是管理应用程序资源的对象Q?/span>
通过它可以读?/span>web.xml中一些配|,?/span><context-param>中的信息Q读取应用中的资源等?/span>
Session 是一个会话对象,也就是说当客L讉K服务器页面时Q它才生,
原理是服务器Ҏ个客L产生一?/span>sessionid?/span>,q把它也保存在客LQ?/span>
每次h旉证这?/span>sessionid是否是创Zsessionid的客LQ在服务器端对应q个sessionid会创Z个缓存区Q?/span>
存储一些相关信?/span>,E序员可以操作,如被用于购物车,存储用户信息{,q个区域只有对特定用h讉K权限Q对其他客户是拒l访问的Q这是一个会话?/span>
Request 是一个请求对象,也就是说它的生命很短暂,只在一个请求中存在Q如一个页面到另一个页面,
一个页面到servlet?/span>action,一?/span>servlet?/span>action?/span>jsp面{?/span>,你可以用它的setAttributeҎ传递需要的信息(对象),验证h方的信息,获得h方发q来的文件内容等?/span>
*/
private ServletContext sc;
publicvoid contextDestroyed(ServletContextEvent arg0) {
}
publicvoid contextInitialized(ServletContextEvent event) {
ServletContext sc = event.getServletContext();
sc.setAttribute("Users", new Integer(0));
this.sc = sc;
}
publicvoid sessionCreated(HttpSessionEvent event) {//在线
System.out.println("new user login our web site");
Integer users = (Integer)sc.getAttribute("Users");
sc.setAttribute("Users", ++users);
}
publicvoid sessionDestroyed(HttpSessionEvent event) {
Integer users = (Integer)sc.getAttribute("Users");
sc.setAttribute("Users", --users);
}
}
Web.xml中配|如下:
<listener>
<listener-class>com.dr.web.listener.UserCountListener</listener-class>
</listener>
?/span>UserCountListener里,?/span>users代表当前在线的h敎ͼUserCountListener在Web服务器启动时自动执行。当UserCountListener构造好后,?/span>users讄?/span> 0。每增加一?/span>SessionQ?/span>UserCountListener会自动调?/span>sessionCreated(HttpSessionEvent event)ҎQ每销毁一?/span>SessionQ?/span>UserCountListener会自动调?/span> sessionDestroyed(HttpSessionEvent se)Ҏ。当调用sessionCreated(HttpSessionEvent event)ҎӞ说明又有一个客户在hQ此时在线的h敎ͼusersQ加1Qƈ且把user写到ServletContext中?/span> ServletContext的信息是所有客L׃n的,q样Q每个客L都可以读取到当前在线的h数?/span>
q行l果Q?br />
qo器代码:
package com.dr.course;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import com.dr.common.Global;
import com.dr.vo.User;
public class IsLoginFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
System.out.println("every request pass here");
HttpServletRequest hrequest=(HttpServletRequest)request;
HttpSession session=hrequest.getSession();
User user = (User)session.getAttribute(Global.USER);
if(user == null){
//跌{到登陆页?/span>
hrequest.getRequestDispatcher("/index.jsp").forward(request,response);
}
filterChain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
}
}
LoginServletc,q行d之后的处理:
package com.dr.course;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.dr.common.Global;
import com.dr.vo.User;
public class LoginServlet extends HttpServlet{
public void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
String userName=request.getParameter("username");
String passWord=request.getParameter("password");
System.out.println("userName | " + userName);
System.out.println("passWord | " + passWord);
User user = new User();
user.setUserName(userName);
user.setPassWord(passWord);
HttpSession session = request.getSession();
//d成功Q把User攑ֈsessionQ然后在拦截器中判断
//key--value
session.setAttribute(Global.USER, user);
request.getRequestDispatcher("/admin/main.jsp").forward(request, response);
}
}
web.xml中配|如下:
- <filter>
<filter-name>isLogin</filter-name>
<filter-class>com.dr.course.IsLoginFilter</filter-class>
</filter>
- <filter-mapping>
<filter-name>isLogin</filter-name>
<url-pattern>/admin/*</url-pattern>
</filter-mapping>
- <servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.dr.course.LoginServlet</servlet-class>
</servlet>
- <servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
未登录界面:
成功d的界面:
我们在登?/span>126邮箱Ӟ如果N上两周内自动登录,两周内不用输入用户名和密码邮׃自动dQ这是因为第一ơ登录时服务器将用户名和密码写入cookie中,q返回给客户端?/span>
下次d?/span>Http协议会带着用户?/span>cookieL务器验证Q因为服务器已经存储用户的信息,所以会自动d?/span>
d代码Q?/span>
package com.dr.course;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username=request.getParameter("username");
String password=request.getParameter("password");
String savetime=request.getParameter("saveTime");
if(CheckLogin.login(username, password)){
if(null!=savetime){
int saveTime=Integer.parseInt(savetime);//q里接受的表单gؓ天来计算?/span>
int seconds=saveTime*24*60*60;
Cookie cookie = new Cookie("user", username+"=="+password);
cookie.setMaxAge(seconds);
response.addCookie(cookie);
}
request.setAttribute("username",username);
request.getRequestDispatcher("/main126.jsp").forward(request,response);
}else{
request.getRequestDispatcher("/failure.jsp").forward(request,response);
}
}
}
验证代码Q?/span>
package com.dr.course;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class IndexFilter implements Filter {
public void destroy() {
// TODO Auto-generated method stub
}
public void doFilter(ServletRequest arg0, ServletResponse arg1,
FilterChain arg2) throws IOException, ServletException {
System.out.println("every request pass here haha");
HttpServletRequest request = (HttpServletRequest) arg0;
HttpServletResponse response = (HttpServletResponse) arg1;
Cookie[] cookies = request.getCookies();
String[] cooks = null;
String username = null;
String password = null;
if (cookies != null) {
for (Cookie coo : cookies) {
String aa = coo.getValue();
cooks = aa.split("==");
if (cooks.length == 2) {
username = cooks[0];
password = cooks[1];
}
}
}
System.out.println("cookie username | " + username);
System.out.println("cookie password | " + password);
if (CheckLogin.login(username, password)) {
System.err.println("check successfully cookie data ");
request.getSession().setAttribute("username",username);
request.getRequestDispatcher("/main126.jsp").forward(request, response);
}else{
arg2.doFilter(request,response );
}
}
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
}
package com.dr.course;
public class CheckLogin {
public static boolean login(String username, String password) {
if ("admin".equals(username) && "123456".equals(password)) {
return true;
} else {
return false;
}
}
}
web.xml中配|如下:
- <filter>
<filter-name>loginFilter</filter-name>
<filter-class>com.dr.course.IndexFilter</filter-class>
</filter>
- <filter-mapping>
<filter-name>loginFilter</filter-name>
<url-pattern>/main126.jsp</url-pattern>
</filter-mapping>
- <servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.dr.course.LoginServlet</servlet-class>
</servlet>
- <servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login.do</url-pattern>
</servlet-mapping>
目录加入到Tomcat中,开?/span>TomcatQ打开览器输入网址:http://127.0.0.1:8080/AutoLogin/login.doq行试?/span>
为防止中文ؕ码出玎ͼ首先我们要把目中每个网늚~码形式Ҏ中文的,HTML|页中的charsetҎUTF-8Q?/span>JSP|页中的pageEncodingҎUTF-8?/span>
然后我们做一个过滤器Q每ơ对|页的请求都会进入到qo器,q且?/span>request?/span>response都改?/span>UTF-8~码形式Q这样防止了中文q的出现?/span>
源代码如下:
package com.dr.servletform;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.jsp.jstl.core.Config;
public class MyFilter implements Filter{
String encoding="";
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("pass here-------");
request.setCharacterEncoding(encoding);
response.setCharacterEncoding(encoding);
chain.doFilter(request, response);
}
public void init(FilterConfig config) throws ServletException {
String encoding=config.getInitParameter("encoding");
this.encoding=encoding;
System.out.println(encoding);
}
}
web.xml中配|如下:
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>com.dr.servletform.MyFilter</filter-class>
- <init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
- <filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
JDBC~程步骤Q?/span>
加蝲数据库驱动(jar 文gQ?/span>
获得数据库连?/span>
创徏语句 (SQL)
执行查询
遍历l果?/span>
关闭数据库连?/span>
CZ程序:
package com.dr.jdbc;
/**
* DriverManager 驱动E序理?/span> 在数据库和相应驱动程序之间徏立连?/span>
* Connection 对象代表与数据库的连接,也就是在已经加蝲?/span>Driver和数据库之间建立q接
* Statement 提供在基层连接上q行SQL语句Qƈ且访问结?/span>
* ResultSet ?/span>Statement执行SQL语句Ӟ有时会返?/span>ResultSetl果集,包含的是查询的结果集
*/
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Test {
public static void main(String[] args) {
query();
}
public static void query(){
Connection conn = null;
try {
//1.加蝲数据库驱?/span>
Class.forName("com.mysql.jdbc.Driver");
//2.获得数据库连?/span>
//DriverManager 驱动E序理?/span> 在数据库和相应驱动程序之间徏立连
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/jdbc_db", "root", "1234");
//3.创徏语句
String sql = "select * from UserTbl";
//q回一个执?/span>SQL的句?/span>
Statement stmt = conn.createStatement();
//q回查询?/span>
//4.执行语句
ResultSet rs = stmt.executeQuery(sql);
//5.遍历l果?/span>
while(rs.next()){
int id = rs.getInt(1);
String username = rs.getString(2);
String password = rs.getString(3);
int age = rs.getInt(4);
System.out.println(id+":"+username+":"+password+":"+age);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
if(conn!=null){
try { //关闭数据库连?/span>
conn.close();
} catch (SQLException e) {
conn = null;
e.printStackTrace();
}
}
}
}
}
package com.dr.Demo01;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerSocket01 {
public static void main(String[] args) {
ServerSocket server=null;
try{
//服务器在9999端口开辟了服务
server=new ServerSocket(9999);
}catch(Exception e){}
//对于服务器而言Q所有用Lh都是通过SeverSocket实现
Socket client=null;
try{
//服务器在此等待用L链接
System.out.println("{待客户端链接、、?);
client=server.accept();//服务端接收到一个client
}catch(Exception e){}
//要向客户端打C?br />
PrintStream out=null;
//得到向客L输出信息的能?br />
try{
out=new PrintStream(client.getOutputStream());
}catch(Exception e){}
out.println("Hi,how do you do?");
try{
client.close();
server.close();
}catch(Exception e){}
System.out.println("客户端回应完毕、、?);
}
}
package com.dr.Demo01;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.Socket;
public class ClientSocket01 {
public static void main(String[] args) {
Socket client=null;
try{
//实际上表C链接到服务器上去?br />
client=new Socket("192.168.1.23",9999);
}catch(Exception e){}
//{待服务器端的回?br />
String str=null;
//如果直接使用InputStream接受会比较麻?br />
//最好的Ҏ是可以把内容攑օ发哦~冲之中进行读?br />
BufferedReader buf=null;
try{
buf=new BufferedReader(new InputStreamReader(client.getInputStream()));
str=buf.readLine();
}catch(Exception e){}
System.out.println(str);
}
}
E序有两U以外需要考虑Q?/span>
1?span style="font: 7pt 'Times New Roman'">
假设BenzU程刚向数据存储I间d了一辆R的名字。还没有加入q辆车的颜色Q?/span>CPU切换到?/span>BMWU程Q?/span>BenzU程把q辆车的名字和上辆R的颜色联pd了一赗?/span>2?span style="font: 7pt 'Times New Roman'">
Benz放了若干ơ的数据?/span>BMW才开始取数据Q或者是Q?/span>BMW取完了一个数据后Q还没等?/span>Benz攑օ新的数据Q又重复取出已取q的数据?/span>可能出现的问题:
1?span style="font: 7pt 'Times New Roman'">
Benz?/span>BMW快时Q?/span>BMW会漏掉一些数据没有取到?/span>2?span style="font: 7pt 'Times New Roman'">
BMW?/span>Benz快时Q?/span>BMW取相同的数据?/span>多个U程׃n同一资源的时候,必须q行同步Q采用同步方法,解决W一个问题?/span>
U程的等待和唤醒机制Q?/span>
wait()Q告诉当前线E放弃监视器q进入睡眠状态,直到其他U程q入同一监视器ƈ调用notify为止?/span>
notify()Q唤醒同一对象监视器中调用wait的第一个线E?/span>
E序中采用线E的{待和唤醒机Ӟ当发?/span>BMW没有取走内容ӞBenz应该{待Q当BMW把内容取C后,Benz才可以放。这栯决了W二个问题?/span>
代码如下Q?/span>
package com.dr.test;
class Car{
private String name="奔驰";
private String color="银色";
private boolean flag=false;
public synchronized void set(String name,String color){
//如果flag的g?/span>true则要{待
if(!flag){
//{待
try{
wait();
}catch(Exception e){}
}
//如果向下l箋执行了,则表C可以设|,flag=true
this.name=name;
this.color=color;
flag=false;
notify();
}
public synchronized void get(){
//如果flag的gؓtrue的时候,表示要等?/span>
if(flag){
try{
wait();
}catch(Exception e){}
}
//如果向下执行了,则表C允许取?/span>
System.out.println(this.name+"-->"+this.color);
//改变标志Q表C可以生产了
flag=true;
notify();
}
}
class Benz implements Runnable{
Car car=null;
public Benz(Car c){
this.car=c;
}
public void run(){
int i=0;
while(true){
if(i==0){
car.set("宝马", "U色");
i=1;
}
else{
car.set("奔驰", "银色");
i=0;
}
}
}
}
class BMW implements Runnable{
Car car=null;
public BMW(Car c){
this.car=c;
}
public void run(){
while(true){
car.get();
}
}
}
public class Demo01 {
public static void main(String[] args) {
Car c=new Car();
Benz benz=new Benz(c);
BMW bmw=new BMW(c);
new Thread(benz).start();
new Thread(bmw).start();
}
}
q行l果Q?br />
1 通过l承ThreadcL实现?/span>
每个U程都是通过某个特定Thread对象所对应的方?/span>run()l来完成其操作的,Ҏrun()成ؓU程体?/span>
如果惌启动多线E,则肯定调?/span>start()ҎQ?/span>startҎ可以调用被子c覆写过?/span>runҎ
不过q种q种实现方式会受到单l承的局?/span>
CZ代码Q?/span>
package com.dr.demo01;
//一个类只要l承?/span>Threadc,则此cd是多U程c?/span>
class MyThread extends Thread{
private String name;
public MyThread(String name){
this.name=name;
}
//如果要用多U程Q则必须有一个方法的M
public void run(){
//打印输出
for(int i=0;i<15;i++){
System.out.println(this.name+"--->在运行、、?/span>");
}
}
}
public class ThreadDemo01{
public static void main(String args[]){
MyThread mt1=new MyThread("U程A");
MyThread mt2=new MyThread("U程B");
MyThread mt3=new MyThread("U程C");
mt1.run();
mt2.run();
mt3.run();
}
}
2 通过实现Runnable接口来实现?/span>
该实现方式有以下好处Q?/span>
?span style="font: 7pt 'Times New Roman'">
适合多个相干同程序代码的U程d理同一资源的情c?/span>?span style="font: 7pt 'Times New Roman'">
可以避免׃Java单承特性带来的局限?/span>?span style="font: 7pt 'Times New Roman'">
有利于程序的健壮性,代码能够被多个线E共享?/span>CZ代码Q?/span>
package com.dr.Demo05;
class MyThread implements Runnable{
public void run(){
for(int i=0;i<100;i++){
try{
Thread.sleep(1000);
}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"--q行?/span>--");
}
}
}
public class Demo05 {
public static void main(String[] args) {
MyThread mt=new MyThread();
Thread t1=new Thread(mt,"U程A");
Thread t2=new Thread(mt,"U程B");
Thread t3=new Thread(mt,"U程C");
t1.start();
t2.start();
t3.start();
}
}