Table of Contents
3.1.1:用于上传文件的Form表单,需要设置enctype属性。
1:什么是mvc
- MVC是一个框架型设计模式
- 本身没有实际的代码(功能)
- 它只是说明页面、数据处理如何摆放。
1.1:Model---逻辑处理
- 封装应用状态(封装应用数据)
- 响应状态查询(对数据进行增删改查)
- 暴露应用的功能(暴露接口<public>)
1.2:Controller---控制页面跳转
- 验证HTTP请求的数据(收集组织数据)
- 将用户数据与模型的更新相映射(调用逻辑层)
- 选择用于响应的视图(选择下一个界面)
1.3:View ---演示数据
- 产生HTML响应(展示数据),如jsp,html等
- 请求模型的更新(人机交互)
- 提供HTML form用于用户请求(收集参数,调用逻辑层api)

1.4:MVC的优缺点
1.4.1:MVC的优点:
低耦合性:视图层和业务层分离
高重用性和可适用性
可维护性
有利于软件工程化管理
提高软件的健壮性
1.4.2: MVC的缺点:
工作量大,增加工作的复杂性,MVC不适合小型甚至中等规模的应用程序
将状态查询封装在Model中,使Model过于臃肿。
2:定制错误页面
声明方式:
使用部署描述符为特定情况(HTTP错误或Java异常)声明错误页面,并由Web容器将处理转发到这些页面
编程方式:
直接在servlet代码中处理Java异常,并将HTTP请求转发到所选定的错误页面
2.1:声明错误页面
使用error-page元素声明一个给定HTTP状态码的处理器:
<error-page>
<error-code>404</error-code>
<location>/error/404.html</location>
</error-page>
可以声明任意数量的错误页面,但一个给定的状态码只能对应一个页面。
- 使用exception-type元素声明给定Java异常的处理器
<error-page>
<exception-type>
java.lang.ArithmeticException
</exception-type>
<location>/error/ExceptionPage</location>
</error-page>
可以声明任意数量的错误页面,但一个给定的异常类型只对应一个页面。
不能使用父类捕获多种异常。
2.2:容器处理异常:
一个servlet可抛出ServletException指明有异常产生
所有检查到的异常必须被捕获,并封装在ServletException中
编写错误处理Servlet
- 应同时覆盖doGet和doPost方法
两个预定义的请求属性:
- javax.servlet.error.exception :包含原始(被包装)的异常
- javax.servlet.error.request_uri:包含原始客户请求的URI
可编写自己的servlet代码捕获所有异常并自己处理,而不是让容器处理
使用此技术只可以处理Java异常,而非HTTP异常
步骤:
- 对可能产生异常的所有代码使用一个 try-catch块
- 在catch块中使用RequestDispatcher将异常转发到一个servlet异常处理器
- (可选)可以设置特定的请求属性
声明servlet异常处理器,但不提供URL映射
<servlet>
<servlet-name>ExceptionHandler</servlet-name>
<servlet-class>sl314.web.ExceptionDisplay</servlet-class>
</servlet>
使用servlet名获得RequestDispatcher
ServletContext context = getServletContext();
RequestDispatcher errorPage= context.getNamedDispatcher("ExceptionHandler");
request.setAttribute("javax.servlet.error.exception", e);
request.setAttribute("javax.servlet.error.request_uri",
request.getRequestURI());
errorPage.forward(request, response);
3:文件上传下载
3.1:文件上传
在Servlet2.5中,我们要实现文件上传功能时,一般都需要借助第三方开源组件,例如Apache的commons-fileupload组件,在Servlet3.0中提供了对文件上传的原生支持,我们不需要借助任何第三方上传组件,直接使用Servlet3.0提供的API就能够实现文件上传功能了。
3.1.1:用于上传文件的Form表单,需要设置enctype属性。
<form action="UploadServlet.do" method="post" enctype= "multipart/form-data">
</form>
3.1.2:开发支持文件上传的Servlet
在Servlet类的声明上,使用注解@MultipartConfig可以设置Servlet支持文件上传。
@MultipartConfig
public class UploadServlet extends HttpServlet {
}
3.1.3:part类
Part是Java EE6.0新增的接口,Servlet3.0将multipart/form-data的部分POST请求封装成Part,通过Part对上传的文件进行操作。
//通过name获得上传文件对象Part
Part part=request.getPart("file");
//获取上传的文件集合
Collection<Part> parts = request.getParts();
3.2:单文件上传
3.2.1:html页面
上传单个文件
<form action="UploadServlet.do" method="post" enctype="multipart/form-data">
上传文件:
<input type="file" name="file">
<br>
<input type="submit" value="上传">
</form>

3.2.2:Servlet
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
// 存储路径
String savePath = request.getServletContext().getRealPath("/uploadFile");
// 通过name获得上传文件对象Part
Part part = request.getPart("file");
// Servlet3没有提供直接获取文件名的方法,需要从请求头中解析出来
// 获取请求头,请求头的格式:form-data; name="file"; filename="snmp4j--api.zip"
String header = part.getHeader("content-disposition");
// 获取文件名
String fileName = getFileName(header);
// 把文件写到指定路径
part.write(savePath + File.separator + fileName);
PrintWriter out = response.getWriter();
out.println("上传成功");
out.flush();
out.close();
}
获取文件名的方法:
/**
* 根据请求头解析出文件名 请求头的格式:
* 火狐和google浏览器下:form-data;name="file";filename="AmazeUI-2.7.2.zip"
* IE浏览器下:form-data; name="file";filename="E:\AmazeUI-2.7.2.zip"
* @param header 请求头
* @return 文件名
*/
public String getFileName(String header) {
String[] tempArr1 = header.split(";");
/**
* 火狐或者google浏览器下:tempArr2={filename,"AmazeUI-2.7.2.zip"}
* IE浏览器下:tempArr2={filename,"E:\AmazeUI-2.7.2.zip"}
*/
String[] tempArr2 = tempArr1[2].split("=");
// 获取文件名,兼容各种浏览器的写法
String fileName = tempArr2[1].substring(tempArr2[1].lastIndexOf("\\") + 1).replaceAll("\"", "");
return fileName;
}
3.3:文件下载
在Servlet中实现文件的下载,第一需要通过HttpServletResponse的setContentType方法设置ContentType头信息的值,这样设置之后浏览器才会以下载的方式来响应。第二需要使用IO流来读取文件内容,将字节输出在响应流中。
3.3.1:Servlet
@WebServlet("/downloadServlet.do")
public class DownloadServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 处理请求
// 根据根路径得到绝对路径
String path = this.getServletContext().getRealPath("/uploadFile/AmazeUI-2.7.2.zip");
// 读取要下载的文件
File f = new File(path);
if (f.exists()) {
//需要注意:源文件的名称是《AmazeUI-2.7.2.zip》,下载后的文件名称是《妹子UI.zip》
// 解决中文文件名下载后乱码的问题,将gbk编码转换成ISO8859_1编码
String filename = new String("妹子UI.zip".getBytes("GBK"),"ISO8859-1");
response.setHeader("Content-Disposition", "attachment;filename=" + filename + "");
// 获取要下载的文件输入流
FileInputStream fis = new FileInputStream(f);
int len = 0;
// 创建数据缓冲区
byte[] buffer = new byte[1024*16];
// 通过response对象获取OutputStream流
OutputStream out = response.getOutputStream();
// 将FileInputStream流写入到buffer缓冲区
while ((len = fis.read(buffer)) > 0) {
//使用OutputStream将缓冲区的数据输出到客户端浏览器
out.write(buffer, 0, len);
out.flush();
}
out.close();
}
}
}
public Response downUpload(String id) {
InputStream in = null;
ByteArrayOutputStream bos = null;
try {
String fileName = "";
in = UploadIn.downloadFile(id);
bos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while((len = in.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
return Response.ok(bos.toByteArray())
.header("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"))
.header("Cache-Control", "no-cache").build();
}catch (Exception e){
System.out.println(""+e);
}finally {
try {
if(in != null)
in.close();
if(bos != null)
bos.close();
}catch (IOException e){
System.out.println(""+e);
}
}
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
3.3.2:Html页面
<a href="downloadServlet.do">下载</a>

3.3.3:设置contentType
调用HttpServletResponse接口的setContentType方法,可以设置响应内容的类型,也叫MIME类型。它的作用是使客户端浏览器可以区分不同类型的数据,并根据不同的MIME类型调用浏览器内不同的程序嵌入模块来处理相应的数据。
例如web浏览器就是通过MIME类型来判断文件是word。
// 根据根路径得到绝对路径
String path = this.getServletContext()
.getRealPath("/uploadFile/[汇才同飞教育]预科班教程_V1.6.docx");
// 读取要下载的文件
File f = new File(path);
String filename =
new String(f.getName().getBytes("GBK"),"ISO8859-1");
response.setHeader("Content-Disposition",
"attachment;filename=" + filename + "");
//设置响应类型是word
response.setContentType("application/x-msdownload");
3.3.4:常用ContentType
| 文件扩展名 | Content-Type(Mime-Type) |
| .*(二进制流,不知道文件类型) | application/octet-stream |
| .tif | image/tiff |
| .awf | application/vnd.adobe.workflow |
| .avi | video/avi |
| .bmp | application/x-bmp |
| .doc | application/msword |
| .class | java/* |
| .css | text/css |
| .exe | application/x-msdownload |
| .excel | application/vnd.ms-excel |
| .gif | image/gif |
| .htm | text/html |
| .html | text/html |
| .ico | image/x-icon |
| .img | application/x-img |
| .java | java/* |
| .jpe | image/jpeg |
| .jpeg | image/jpeg |
| .jpg | image/jpeg |
| .jsp | text/html |
| .mp3 | audio/mp3 |
| .mp4 | video/mpeg4 |
| .mpeg | video/mpg |
| .odc | text/x-ms-odc |
| | application/pdf |
| .png | image/png |
| .ppt | application/vnd.ms-powerpoint |
| rar | application/octet-stream |
| .rmvb | application/vnd.rn-realmedia-vbr |
| .swf | application/x-shockwave-flash |
| .torrent | application/x-bittorrent |
| .txt | text/plain |
| .xml | text/xml |
| .zip | application/x-zip-compressed |

797

被折叠的 条评论
为什么被折叠?



