web(24)web注解开发&使用web3.0完成文件上传功能

web(24)_web注解开发&使用web3.0完成文件上传功能

一、注解
【注解的概述】
1.注解(annotation)与注释的区别
>注释是给开发人员看的,说明某个代码的功能
>注解是给虚拟机看的,让虚拟机看到程序中的注解,代表程序的一些特殊的功能.
比如,@override代表重写,虚拟机看到@override就会检测该方法是否与
父类的方法名,返回值类型,参数一样。一样就是子类的重写。

【JDK提供的注解】

1.@override:

重写:给一个方法添加@override以后,虚拟机就会检查该方法的方法名,返回值,参数
是否与父类的方法一样,不一样就会报错。添加override能防止写错。
1.6及其以后的版本,注解可以用在类的继承和类的接口实现上面。
》ps:重载是函数名字一样。参数或返回值类型不一样
2.@SuppressWarnings("unused") 压制警告(小黄色感叹号)
比如 int i;没有初始化会显示黄色的感叹号,项目依旧能运行。加上@SuppressWarnings("unused")
在方法上,可以消除黄色感叹号
双引号""中有很多值。记住一个"all":@SuppressWarnings("all")就可以消除所有的感叹号
3.@DEprecated:描述方法过时
比如,date.toLocaleString():是个过时的方法
可以自己写一个方法,加上@DEprecated 表示这个方法过时
4.自定义注解:
1)格式:@interface 注解名称
比如 @interface Anono1{}
然后再其他方法中就可以写@Anono1,虽然没有意义
2)自定义注解的属性:注意是用()
{int a();String s()}
只有基本数据类型,class,String,enumeration..才允许定义在注解中
3)使用:@myAnono1(a=1,s="abc") 给注解的属性赋值.不然会报错
给属性赋初始值:
{int a() default 2;
 boolean b() defalut false;
 }
4)自定义属性为class类型的对象
{Class c()}
使用:@Anono(c=User.class)
5)只有一个属性时,并且当注解中的属性名为"value"时,在引用时可以省略名字
比如:@Anno2("abc");
@interface Anno2
{String value();}
6)引用注解的多个属性要用","逗号隔开
了解注解是为了在web3.0中支持用注解代替xml配置。另外在以后的三大框架中也支持注解开发。

二、案例1:模仿Junit自定义测试注解@Test
核心分析【注解的寿命】
1.自定义的存在阶段:
在java中,一个类有三个阶段:
源码阶段:A.java
class阶段:A.java经过编译后变成A.class
运行阶段:JVM通过ClassLoader类加载器执行程序
2.默认情况下,自定义的注解存在于源码阶段,在生成Class和运行阶段就不存在了。
这时候,要想延长自定义注解的寿命,要使用元注解Retention(元注解:用于修饰其他的注解)
@Retention(value=RetentionPolicy.RUNTIME)
设置成运行阶段.
RetentionPolicy:是一个枚举类型->枚举:有限个数据


代码1:【案例1:模仿Junit自定义测试注解@Test

AnnotationDemo3.java:

public class AnnotationDemo3 {
	
	@MyTest
	public void demo1() throws Exception {
		System.out.println("demo1运行了...");
	}
	
	@MyTest
	public void demo2() throws Exception {
		System.out.println("demo2运行了...");
	}
	
	public void demo3() throws Exception {
		System.out.println("demo3运行了...");
	}
}

MyTest.java

/*
 * 自定义注解MyTest,模仿Junit的@Test运行测试类
 *使用@Retention注解将注解的寿命设置延长至运行阶段
 */
@Retention(value=RetentionPolicy.RUNTIME)
public @interface MyTest {

}

CoreRunner.java

/* 
 * 核心运行类:
 * 通过反射获得测试类的Class
 * 遍历每个方法,查看每个方法上面是否有MyTest注解
 * 有@MyTest注解,就执行这个方法
 * 
 * 规定:测试的方法必须时public类型
 */
public class CoreRunner {

	public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
		Class clazz = AnnotationDemo3.class;
		Method[] methods = clazz.getMethods();
		for(Method method:methods)
		{
			
			//核心方法:判断这个方法是否含有注解@myTest
			/*
			 * 注意默认情况下注解设置自定义注解的寿命
			 * isAnnotationPresent(MyTest.class)
			 * 表示是否存在某个指定的注解
			 * 
			 */
			boolean b = method.isAnnotationPresent(MyTest.class);
			if(b)
			{
				method.invoke(clazz.newInstance(),null);
			}
		}
	}
}



三、案例2:WEB3.0文件上传功能
1.【文件上传概述】
》文件上传:QQ头像,简历上传,文件发送等多方面使用到。在网站维护中,上传商品的图片到服务器中。
>在技术方面,文件上传指的是将本地的文件变成流写到服务器上。
>文件上传技术:
 *利用servlet 3.0:比servlet2.5多的功能:注解开发,文件上传,异步请求(用的不多)
 *JSPSmartUpload: 嵌入到JSP中,用的不多。
 *FileUpload:来自Apache的文件上传组件
 *Struts框架:已经封装好了文件上传功能。底层是FileUpload;
>文件上传的要素:
 *表单提交的方式必须是POST
      理由是POST上传方式没有数据的大小限制
 *表单中需要有文件上传的表单元素:这个表单中必须有name属性和值:<input type="file" name="upload">
 *表单的enctype属性的值必须是multipart/form-data

2.【Servlet3.0注解开发】
Servlet3.0提供了三个新的特性:
1)*注解开发:
(1)Servlet注解配置:
[1]Servlet配置:
在2.5中,要在web.xml中写一堆才能访问到Servlet.
在3.0中,在类上面添加一个注解:@webServlet就可以访问了
a.@WebServlet(urlPatterns="/ServletDemo1")
b.@WebServlet("/ServletDemo1")
[2]属性配置:
a.启动时就会创建Servlet属性:
@WebServlet(urlPatterns="/ServletDemo1",loadOnStartup=2)
2表示数值越大优先级别越高
启动服务器直接创建好Servlet,可以在init()方法中打印看到
b.配置初始化参数:
@WebServlet(initParams={@WebInitParams(name="username",value="root")});
配置多个初始化参数的话,逗号隔开多个@WebInitParams数组注解
[3]监听器配置:
@WebListener使用这个注解就好
记住,监听器有三类:例如创建MyServletContextListener,要实现接口 ServletContextListener
[4]过滤器配置:
@WebFilter(urlPatterns="/*")
记得在doFilter()方法中执行过滤器链放行方法
chain.doFilter(req,res);不然访问不到的。
2)*文件开发
3)*异步请求
 
3.【文件上传的抓包分析】
1.新建一个文件上传upload.jsp:
表单要满足三个条件:
1)表单上传方式必须是post方法
2)表单元素必须要有name和值
3)表单的属性enctype="multipart/form-data"
2.抓包分析:没有设置enctype的时候,会是怎么样的?
火狐或者谷歌访问页面,按F12 点击上传
没有设置enctype头:抓到的包显示的是一堆请求头,在请求体上只有文件名称,而没有文件内容
设置enctype属性:获得到文件名,文件内容。有了文件内容,我们可以直接写一个流


4.【文件上传原理分析】
1)在抓包分析中,如果有设置enctype="multipart/form-data",我们可以得到一个请求头:
multipart/form-data; boundary=---------------------------61421105010721
用request.getHeader("Content-Type");
截取boundary得到分割线:---------------------------61421105010721
2).由于上面使用了enctype属性,所以只能用request.getInputStream()得到这个请求体的内容的流形式
将流转换成String形式,得到整个请求体的内容。然后我们可以领用分割线来切割字符串。
3)当然,在web3.0中 。上述的工作都已经完成了。不用我们去做


5.【文件上传的代码实现】
【步骤一:】设置一个文件上传页面
【步骤二:】点击提交按钮,提交到Servlet中
【步骤三:】在Servlet中接收参数
【步骤四:】获得服务器文件上传的路径
【步骤五:】通过流写到该路径下就OK了
1)首先在UploadServlet中加一个注解:

@MultipartConfig才可以使用方法

【案例2:WEB3.0文件上传功能】代码

upload.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>文件上传页面</title>
</head>
<body>
<!-- 
 *表单提交的方式必须是POST
 *表单中需要有文件上传的表单元素:这个表单中必须有name属性和值:<input type="file" name="upload">
 *表单的enctype属性的值必须是multipart/form-data
 -->
	<h1>文件上传页面</h1>
	<form method="post" action="${pageContext.request.contextPath}/UploadServlet" enctype="multipart/form-data">
		<table border="1" width=600px>
			<tr>
				<td>文件描述:</td>
				<td><input type="text" name="filedesc" /></td>
			</tr>
			<tr>
				<td>文件上传:</td>
				<td><input type="file" name="upload" /></td>
			</tr>
			<td colspan=2><input type="submit" value="上传" /></td>
			</tr>
		</table>
	</form>
</body>
</html>

UploadServlet.java

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;

/**
 * 
 */
@WebServlet("/UploadServlet")
@MultipartConfig
public class UploadServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//接收普通数据:
		request.setCharacterEncoding("UTF-8");
		String filedesc = request.getParameter("filedesc");
		//接收文件
		//得到name=upload的那块请求体内容
		//也就是包含文件名和文件内容的那块分割线
		Part part = request.getPart("upload");
		long size = part.getSize();
		//提供API不全,没法获得文件名。自己截取
		String header=part.getHeader("content-Disposition");
		//在头字符串中找到filename
		int idx = header.lastIndexOf("filename=\"");
		//filename="aaa.txt"
		//idx+10:filname 8; =" 2;8+2=10 
		String filename=header.substring(idx+10, header.length()-1);
		//获得文件内容:
		InputStream is = part.getInputStream();
		
		//开始获得文件的服务器路径:
		String path = this.getServletContext().getRealPath("/upload");
		OutputStream os = new FileOutputStream(path+"/"+filename);
		
		//有输入流和输出流,两个流对接就好了
		byte[] bytes = new byte[1024];
		int len = 0;
		while((len = is.read(bytes))!=-1)
		{
			os.write(bytes, 0, len);
		}
		is.close();
		os.close();
	}
	

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值