day7
一、junit的使用
单元测试
测试对象 是一个类中的方法
单元测试方法时候,方法命名规则public void 方法名(){ }
- 使用注解方式运行测试方法,在方法的上面写
@Test:表示这个方法进行单元测试
public class TestDemo {
@Test//测试方法
public void testAdd1(){
TestJunit test01 = new TestJunit();
test01.testAdd(3, 6);
}
}
@Ignore:表示这个方法不进行单元测试
@Before:表示在每个方法之前运行
@After:表示在每个方法之后运行
断言:Assert.assertEquals("测试期望的值","方法运行的实际的值");
二、泛型的简介
-
在集合上使用泛型
常用集合 list set map
泛型语法:
集合<String> 比如:List<String> - 在list上使用泛型
@Test
public void testList() {
List<String> list = new ArrayList<String>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
for (int i = 0; i < list.size(); i++) {// for循环
String s = list.get(i);
System.out.println(s);
}
System.out.println("=========================");
for (String s1 : list) {// 增强for循环
System.out.println(s1);
}
System.out.println("=========================");
Iterator<String> it = list.iterator();// 使用迭代器遍历
while (it.hasNext()) {
System.out.println(it.next());
}
}
- 在set上使用泛型
@Test
public void testSet(){
Set<String> set = new HashSet<String>();
set.add("aaa");
set.add("www");
set.add("zzz");
for (String s2 : set) {//增强for循环
System.out.println(s2);
}
System.out.println("===================");
Iterator<String> it = set.iterator();//使用迭代器遍历
while(it.hasNext()){
System.out.println(it.next());
}
}
-
在map上使用泛型
map结构:key-value形式
@Test
public void testMap(){
Map<String,String> map = new HashMap<String, String>();
map.put("aaa", "111");
map.put("bbb", "222");
map.put("ccc", "333");
Set<String> sets = map.keySet();//获取所有key
for (String key : sets) {//遍历所有key返回的set
String value = map.get(key);//通过key得到value
System.out.println(key+" : "+value);
}
System.out.println("=======================");
Set<Entry<String,String>> sets1 = map.entrySet();//得到key和value关系
for (Entry<String, String> entry : sets1) {//遍历sets1
//entry是key和value的关系
String keyv = entry.getKey();
String valuev = entry.getValue();
System.out.println(keyv+" : "+valuev);
}
}

三、泛型在方法上使用
- 定义一个数组,实现指定位置上数组元素的交换
方法逻辑相同,只是数据类型不同,这个时候使用泛型方法
使用泛型方法 需要定义一个类型;使用大写字母T表示;这个T表示任意的类型
写在返回值void之前<T>
public static <T> void swap1(T[] arr,int a,int b){
T temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
四、泛型在类上使用
在一个类上定义一个泛型,这个类型可以在类里面直接使用
在类上面定义的泛型,不能再静态方法里面使用
public class TestDemo04<T> {
T aa;
public void test11(T bb){
}
}
五、枚举的简介
枚举:需要在一定的范围内取值,这个值只能是这个范围中的任意一个
使用关键字enum,枚举的构造方法也是私有的
enum Color3{
RED,GREEN,YELLOW;
}
特殊枚举的操作:
1.在枚举类里面有构造方法
构造方法里面有参数,需要在每个实例上面写参数
2.在枚举类里面有抽象方法
在枚举里面写了抽象方法之后,需要在每个实例上面都实现抽象方法
public class TestEnum2 {
}
enum Color11{
RED("red"){
@Override
public void print1() {
System.out.println("red");
}
},GREEN("green"){
@Override
public void print1() {
System.out.println("green");
}
},YELLOW("yellow"){
@Override
public void print1() {
System.out.println("yellow");
}
};
private Color11(String name){}
public abstract void print1();
}
六、枚举的api操作
name():返回枚举的名称
ordinal():枚举的下标,下标从0开始
valueOf(Class<T> enumType,String name):得到枚举的对象
不在api中的方法,编译时生成:
valueOf(String name):转换枚举对象
values():获得所有枚举对象数组
枚举对象,枚举对象下标,枚举对象名称表示之间的转换
- 知道枚举对象,得到枚举名称和下标
@Test
public void test1(){
Color100 c100 = Color100.RED;//得到枚举对象
String name = c100.name();//枚举名称
int idx = c100.ordinal();//枚举下标
System.out.println(name+" "+idx);
}
- 知道枚举的名称,得到枚举的对象和下标
@Test
public void test2(){
String name1 = "GREEN";//得到对象
Color100 c1 = Color100.valueOf(name1);//得到对象
int idx1 = c1.ordinal();//枚举下标
System.out.println(idx1);
}
- 知道枚举下标,得到枚举对象和名称
public void test3(){
int idx2 = 2;
Color100[] cs = Color100.values();//得到枚举对象
Color100 c12 = cs[idx2];//根据下标得到对象
String name = c12.name();//得到枚举名称
System.out.println(name);
}
七、静态导入
可以在代码里面,直接使用静态导入方式,导入静态方法或常量
import static XX.XX.xxx
import static java.lang.System.out;
import static java.util.Arrays.sort;
import java.util.Arrays;
public class TestDemo1 {
public static void main(String[] args) {
out.println("asdas");
int[] arr = {2,5,78,24,8,56};
sort(arr);
System.out.println(Arrays.toString(arr));
}
}
八、自动拆装箱
装箱:把基本数据类型转换成包装类
拆箱:把包装类转换成基本数据类型
Integer i =10;//自动装箱
int m = i;//自动拆箱
九、增强for循环
语法:for(遍历出来的值 :要遍历的集合){ }
使用场景:
1.数组
2.实现Iterable接口的集合
在集合上使用增强for循环遍历
list set 实现了Iterator接口,可以使用增强for循环
map没有实现Iterator接口,不能使用增强for循环
增强for循环出现为了替代迭代器
内容补充
1.泛型擦除:首先泛型只是出现在源代码阶段,编译之后泛型就不存在了
实现一个泛型方法,接受任意类型的数组,颠倒数组中所有元素
public class TestDemo1 {
public static void main(String[] args) {
Integer[] arr1 = {12,423,54,2,6};
System.out.println(Arrays.toString(arr1));
reverses(arr1);
System.out.println(Arrays.toString(arr1));
}
public static <T> void reverses(T[] arr1){
for(int i = 0;i<arr1.length/2;i++){
T temp = arr1[i];
arr1[i] = arr1[arr1.length-i-1];
arr1[arr1.length-i-1] = temp;
}
}
}
十、可变参数
应用场景:如果实现多个方法,这些方法里面逻辑基本相同,唯一不同的是传递参数的个数,可使用可变参数
//2个数相加,3个数相加,4个数相加
public static void main(String[] args) {
add1(10,20);
add1(10,20,30);
add1(10,20,30,40);
}
public static void add1(int...nums){
//nums:理解为一个数组,这个数组存储传递过来的参数
int sum = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
}
System.out.println(sum);
}
注意:
1.可变参数需要写在方法的参数列表中,不能单独定义
2.在方法的参数列表中只能有一个可变参数
3.方法的参数列表中的可变参数必须放在参数最后
十一、反射的原理
应用在一些通用性比较高的代码中
-
首先需要把java文件保存到本地硬盘 .java
-
编译java文件 变成.class文件
-
使用jvm,把class文件通过类加载器加载到内存中
-
class文件在内存中使用class类表示
-
使用反射的时候,首先需要获取到class类,得到这个类之后,就可以得到class文件里面的所有内容,包含 :属性,构造方法,普通方法
构造方法通过一个类 Constructor
普通方法通过一个类 Method
十二、使用反射操作类里面的无参数构造方法
获取Class类三种方式:
Class class1 = Person.class;
Class class2 = new Person().getClass();
Class class3 = Class.forName("cn.itcast.test09.Person");
不使用new,对一个类进行实例化:
@Test
public void test1() throws Exception{
Class c3 = Class.forName("cn.itcast.test09.Person");//得到class
Person p = (Person) c3.newInstance();//得到Person的实例
p.setName("asda");//设置值
System.out.println(p.getName());
}
十三、使用反射操作有参数构造方法
@Test
public void test2() throws Exception{
Class c1 = Class.forName("cn.itcast.test09.Person");//得到class
Constructor cs = c1.getConstructor(String.class,String.class);//传递有参数的构造方法里面的参数类型,类型使用class形式传递
Person p1 = (Person) cs.newInstance("lisi","23");//通过有参数的构造方法创建Person实例
System.out.println(p1.getId()+" "+p1.getName());
}
十四、使用反射操作属性
操作name属性
@Test
public void test3(){
try {
Class c2 = Class.forName("cn.itcast.test09.Person");//得到class类
Person p11 = (Person) c2.newInstance();//得到Person的实例
Field f1 = c2.getDeclaredField("name");//得到name属性
f1.setAccessible(true);//设置可以操作私有属性
f1.set(p11,"wangwu");//相当于p.name = wangwu"";
System.out.println(f1.get(p11));//相当于p.name
} catch (Exception e) {
e.printStackTrace();
}
}
如果操作的是私有属性,需要设置可以操作私有属性的方法setAccessible(true);
十五、使用泛型操作普通方法
使用Method类表示普通方法
@Test
public void test4() throws Exception{
Class c4 = Class.forName("cn.itcast.test09.Person");//得到class类
Person p4 = (Person) c4.newInstance();//得到Psrson实例
Method m1 = c4.getDeclaredMethod("setName", String.class);//得到普通方法
m1.invoke(p4, "niuqi");//让setName方法执行,执行设置值
System.out.println(p4.getName());
}
getDeclaredMethod:第一个参数,方法名称;第二个参数,通过方法设置的值
invoke:第一个参数:person实例;第二个参数: 设置的值
当操作的方法是静态方法时候,因为静态方法调用的是 类名.方法名,所以不需要实例
使用反射操作静态方法时,也不需要实例。
在invoke方法的第一个参数里面写null
m1.invoke(null, "niuqi");
=====================================================================================================================================================================================================================
day8
一、软件系统体系结构
1.常见软件系统体系结构:
(1)C/S:Client/Servlet(客户机/服务器)结构;安全性比较好
(2)B/S:即Browser/Server(浏览器/服务器)结构;安全性较差
2.WEB资源:
html:静态资源 :浏览器可以看懂
JSP/Servlet:动态资源 :需要先转换成html,再给浏览器看
3.Web服务器
Web服务器的作用是接收客户端的请求,给客户端做出响应

二、Tomcat
三、Web应用
创建动态应用:

WEB-INF 目录不能被客户端访问
四、HTTP协议
HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。
https://www.jianshu.com/p/80e25cb1d81a
Referer:可以统计访问量
五、响应协议

响应头:
Last-Modified:html页面最后的修改时间
请求头:
If-Modified-Since:把上次请求的index.html的最后修改时间还给服务器;
状态码:304,比较If-Modified-Since时间与文件真实时间一样时,服务器会响应304,而且不会有响应正文,表示浏览器缓存的就是最新版本!
自动刷新响应头,浏览器会在3秒之后请求http://www.baidu.com
Refresh:3;url=http://www.baidu.com
<meta http-equiv="Refresh" content="5;url=http://www.baidu.com">
六、使用java来画图
public class Demo {
public static void main(String[] args) throws IOException {
BufferedImage bi = new BufferedImage(150,70,BufferedImage.TYPE_INT_RGB);//得到图片缓冲区
Graphics2D g2 = (Graphics2D)bi.getGraphics();//得到他的绘制环境(这张图片的笔)
g2.setColor(Color.white);//设置颜色
g2.fillRect(0,0,150,70);//填充整张图片(背景色)
g2.setColor(Color.red);
g2.drawRect(0,0,150-1,70-1);//设置边框颜色
g2.setFont(new Font("宋体",Font.BOLD,18));//设置字体
g2.setColor(Color.BLACK);//设置颜色
g2.drawString("HelloWorld",3,50);//向图片上写字符串
ImageIO.write(bi, "JPEG",new FileOutputStream("D:/a.jpg"));//保存图片
}
}

=====================================================================================================================================================================================================================
day9
一、Servlet概述
1.Servlet

2.实现Servlet的方式
三种方式:
- 实现javax.servlet.Servlet接口
- 继承javax.servletGenericServlet类
- 继承javax.servlet.http.HTTP.Servlet类
查看Servlet接口中的方法:
生命周期方法:
- void init(ServletConfig servletConfig):在Servlet对象创建之后马上执行,并只执行一次(出生之后)
- void service(ServletRequest request, ServletResponse response):会被调用多次,每次处理请求都是在调用这个方法
- void destroy():在Servlet被销毁之前调用,并且只会被调用一次
特性:
- 单例,一个类只有一个对对象;可能存在多个Servlet类
- 线程不安全的,所有效率最高
Servlet类由我们来写,但对象由服务器来创建,并且由服务器来调用相应的方法
二、ServletConfig介绍
API:
String getServletName():获取的是<servlet-name>中的内容
ServletContext getServletContext():获取Servlet上下文对象
String getInitParameter(String name):通过名称获取指定初始化参数的值
Enumeration getInitParameterNames():获取所有初始化参数的名称
package cn.itcast.web.servlet;
import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class AServlet implements Servlet {
@Override//生命周期方法;在Servlet对象创建之后马上执行,并只执行一次(出生之后)
public void init(ServletConfig config) throws ServletException {
System.out.println("init...");
}
@Override//用来获取Servlet的配置信息
public ServletConfig getServletConfig() {
System.out.println("ServletConfig...");
return null;
}
@Override//生命周期方法,会被调用多次,每次处理请求都是在调用这个方法
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException {
System.out.println("service...");
}
@Override//获取Servlet的信息
public String getServletInfo() {
System.out.println("getServletInfo...");
return null;
}
@Override//生命周期方法,在Servlet被销毁之前调用,并且只会被调用一次
public void destroy() {
System.out.println("destroy...");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>xxx</servlet-name>
<servlet-class>cn.itcast.web.servlet.AServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>xxx</servlet-name>
<url-pattern>/AServlet</url-pattern>
</servlet-mapping>
</web-app>
三、GenericServlet介绍
四、HttpServlet类介绍


五、Servlet细节
1.Servlet与线程安全
不要在Servlet中创建成员,创建局部变量即可
可以创建无状态成员
可以创建有状态成员,但状态必须为只读的
2.让服务器在启动时就创建Servlet
默认情况下,服务器会在某个Servlet第一次收到请求时创建他;也可以在web.xml中对Servlet进行配置,是服务器启动时就创建Servlet
<servlet>
<servlet-name>xxx</servlet-name>
<servlet-class>cn.itcast.web.servlet.FServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>xxx</servlet-name>
<url-pattern>/FServlet</url-pattern>
</servlet-mapping>
3.<url-pattern>
<url-pattern>是<servlet-mapping>的子元素,用来指定Servlet访问路径。必须以" / "开头
可以在<servlet-mapping>中给出多个<url-pattern>
<servlet-mapping>
<servlet-name>xxx</servlet-name>
<url-pattern>/AServlet</url-pattern>
<url-pattern>/BServlet</url-pattern>
</servlet-mapping>
一个Servlet绑定了2个URL,无论访问/AServlet还是/BServlet,访问的都是/AServlet。

六、ServletContext
一个项目只有一个ServletContext对象
我们可以在N多个Servlet中来获取这个唯一对象,使用它可以给多个Servlet传递数据
1.ServletContext概述:
服务器会为每个应用创建一个ServletContext对象
- ServletContext对象的创建是在服务器启动时完成的
- ServletContext对象的销毁时在服务器关闭时完成的
ServletContext对象作用是在整个web应用的动态资源之间共享数据
2.获取ServletContext
ServletConfig有getServletContext();方法
GenericServlet有getServletContext();方法
HttpSession有getServletContext();方法
ServletContextEvent有getServletContext();方法
3.域对象功能(用来在多个Servlet中传递数据)
域对象必须要有存数据功能
域对象必须要有取数据功能
域对象内部有一个Map

向ServletContext获取数据
public class AServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletContext application = this.getServletContext();//获取ServletContext对象
application.setAttribute("name","张三");//调用其setAttribute()方法完成数据保存
}
public class BServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletContext application = this.getServletContext();//获取ServletContext对象
String name = (String) application.getAttribute("name");//调用其getAttribute()方法完成获取数据
System.out.println(name);
}
}
4.获取应用初始化参数
- Servlet也可以获取初始化参数,但它是局部的参数;一个Servlet只能获取自己的初始化参数,不能获取别人的,即初始化参数只为一个Servlet准备
- 可以配置公共的初始化参数,为所有Servlet而用,需要使用ServletContext
public class CServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletContext app = this.getServletContext();//得到ServletContext
String value = app.getInitParameter("context-param");//调用getInitParameter得到初始化参数
System.out.println(value);
}
}
5.获取资源相关方法
- 获取资源路径
@WebServlet(name = "DServlet",urlPatterns = {"/DServlet"})
public class DServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//得到的是有盘符的路径
String path = this.getServletContext().getRealPath("/index.jsp");
System.out.println(path);
}
}
6.获取资源流
@WebServlet(name = "DServlet",urlPatterns = {"/DServlet"})
public class DServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//得到的是有盘符的路径
String path = this.getServletContext().getRealPath("/index.jsp");
System.out.println(path);
//得到资源路径后,在创建出输入流对象
InputStream input = this.getServletContext().getResourceAsStream("/index.jsp");
//获取当前路径下所有资源的路径
Set<String> paths = this.getServletContext().getResourcePaths("/WEB-INF");
System.out.println(paths);
}
}
7.练习:访问量统计
创建一个int类型的变量,用来保存访问量,然后把他保存到ServletContext域中,这样可以保证所有的Servlet都可以访问到
- 当本站第一次被访问时,创建一个变量,设置其值为1,保存到ServletContext中
- 当以后的访问时,就可以从ServletContext中获取这个变量,然后在其基础上加1
- 获取ServletContext对象,查看是否存在名为count的属性,如果存在,说明不是第一次访问,如果不存在,说明是第一次访问
(1)第一次访问:调用ServletContext的setAttribute()传递一个属性,名为count,值为1
(2)第二次访问:调用ServletContext的getAttribute()方法获取原来的访问量,给访问量加1,在调用ServletContext的setAttribute()方法完成设置
@WebServlet(name = "EServlet", urlPatterns = {"/EServlet"})
public class EServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletContext app = this.getServletContext();
Integer count = (Integer) app.getAttribute("count");
if(count==null){
app.setAttribute("count",1);
}
else {
app.setAttribute("count",count+1);
}
//向浏览器输出,需要使用响应对象
PrintWriter pw = response.getWriter();
pw.print("<h1>"+count+"</h1>");//向浏览器输出
}
}
网友评论