一、过滤器高级配置
page指令的错误页面,用的是转发技术
注意:servlet2.5有4个拦截选项,而servlet3.0有5个拦截选项
在web.xml中进行如下配置
<filter>
<filter-name>FilterDemo</filter-name>
<filter-class>com.itheima.filter.FilterDemo</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterDemo</filter-name>
<url-pattern>/*</url-pattern>
<!-- 所有错误都会被过滤 -->
<dispatcher>ERROR</dispatcher>
<!-- 所有转发都会被过滤-->
<dispatcher>FORWARD</dispatcher>
<!-- 所有动态包含都会被过滤 -->
<dispatcher>INCLUDE</dispatcher>
<!-- 所有请求都会被过滤 -->
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<error-page><!-- 配置错误页面 -->
<!-- 需要抓住的异常是什么类型 -->
<exception-type>java.lang.Exception</exception-type>
<!-- 出现错误后,需要转发到哪个页面 -->
<location>/error.jsp</location>
</error-page> |
二、巩固包装设计模式(复习)
建立BufferedReaderDemo
public class BufferedReaderDemo {
public static void main(String[] args) throws IOException {
//记住,不能加/
Reader r = new FileReader("src/com/itheima/filter/FilterDemo.java");
BufferedReader br = new BufferedReader(r);
MyBufferedReader mbr = new MyBufferedReader(br);
String str = null;//记录读到的数据
while((str=mbr.readLine())!=null){
System.out.println(str);
}
mbr.close();
}
} |
建立MyBufferedReader包装类
//包装五步之一,实现被包装相同的接口
public class MyBufferedReader extends BufferedReader {
private int linenum=1;//行号
//包装五步之二,引用被包装的对象
private BufferedReader br;
//包装五步之三,构造函数传入被包装类的对象
public MyBufferedReader(BufferedReader br){
super(br);
this.br=br;
}
//包装五步之四,改写需要修改的方法
//先拿到原有对象的放回值,然后再做判断后进行包装
public String readLine() throws IOException {
String str = br.readLine();
if(str==null)
return null;
if(linenum<10)
return linenum++ +" "+":"+str;
if(linenum>9&&linenum<100)
return linenum++ +" "+":"+str;
return linenum++ +":"+str;
}
//包装五步之五,不需要改写的方法调用原有对象
} |
三、过滤器高级案例:4个(有一个很难)
案例一:全站乱码解决
建立AllCharacterEncodingFilter
//实现解决全站乱码问题的过滤器
public class AllCharacterEncodingFilter implements Filter {
private String encoding = "UTF-8";//设置默认编码
public void init(FilterConfig filterConfig) throws ServletException {
//获取配置文件中的信息,初始化信息encoding的值
String value = filterConfig.getInitParameter("encoding");
if(value!=null){
encoding = value;
}
}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
//必须转成HTTP协议的request类,因为放行后的servlet有可能会使用http协议的方法
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//解决POST请求参数中文编码问题
request.setCharacterEncoding(encoding);
//输出编码及通知客户端编码
response.setCharacterEncoding(encoding);
response.setContentType("text/html;charset="+encoding);
//写一个包装类,对request进行包装,包装类必须把被包装的对象传进来;
MyHttpServletRequest mrequest = new MyHttpServletRequest(request);
chain.doFilter(mrequest, response);
}
public void destroy() {
}
}
class MyHttpServletRequest extends HttpServletRequestWrapper{
private HttpServletRequest request;//引用原有对象
public MyHttpServletRequest(HttpServletRequest request) {
super(request);
this.request=request;
}
//覆盖方法
public String getParameter(String name) {
//获取name的值,后续使用
String value = request.getParameter(name);
if(value==null){
return null;
}
//只解决GET请求参数编码问题 //获取提交方式
String method = request.getMethod();
//因为浏览器提交的方法名大小写不同,所以比较的时候需要忽略大小写
if("get".equalsIgnoreCase(method)){
try {
//Tomcat的默认编码是ISO-8859-1,所以设置编码的时候需要注意
value = new String(value.getBytes("ISO-8859-1"), request.getCharacterEncoding());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return value;
}
} |
设置配置文件
<filter>
<filter-name>AllCharacterEncodingFilter</filter-name>
<filter-class>com.itheima.filter.AllCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>AllCharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> |
案例二:脏话过滤器
DirtyWordsFilter(注意要有解决全站乱码的过滤器)
public class DirtyWordsFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest arg1, ServletResponse arg2,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) arg1;
HttpServletResponse response = (HttpServletResponse) arg2;
//对request进行包装,过滤
DwHttpServletRequest dwrequest = new DwHttpServletRequest(request);
chain.doFilter(dwrequest, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
}
}
class DwHttpServletRequest extends HttpServletRequestWrapper{
private HttpServletRequest request;
public DwHttpServletRequest(HttpServletRequest request){
super(request);
this.request = request;
}
public String getParameter(String name) {
String value = request.getParameter(name);
if(value==null){
return null;
}//定义脏话字典
String[] dws = new String[]{"畜生","禽兽"};
for(String s:dws){
//判断value里面是否包含脏话字典里的词
if(value.contains(s)){
//
value = value.replace(s, "**");
}
}
return value;
}
} |
案例四:全站压缩
注意在进行配置文件设置的时候,只需要设置和文本相关的*.jsp;*.html,*.js;*.css
public class GzipFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest arg1, ServletResponse arg2,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) arg1;
HttpServletResponse response = (HttpServletResponse) arg2;
GzipHttpServletResponse gresponse = new GzipHttpServletResponse(response);
chain.doFilter(request, gresponse);
//获取原始字节,进行压缩
byte[] b = gresponse.getBufferData();
System.out.println("压缩前的大小:"+b.length);//测试用
//建立一个byte[]输出流,关联到Gzip压缩流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//Gzip流需要一个字节输出流来关联,压缩流内的数据
GZIPOutputStream gos = new GZIPOutputStream(baos);
gos.write(b);
gos.close();
b = baos.toByteArray();//取出缓存中被压缩后的数据
System.out.println("压缩有的大小:"+b.length);
//告知浏览器压缩方式,就是设置头
response.setHeader("Content-Encoding", "gzip");
response.getOutputStream().write(b);
}
public void init(FilterConfig filterConfig) throws ServletException {
}
}
class GzipHttpServletResponse extends HttpServletResponseWrapper{
private ByteArrayOutputStream baos = new ByteArrayOutputStream();
private PrintWriter pw;
public GzipHttpServletResponse(HttpServletResponse response) {
super(response);
}
//servlet是使用getOutputStream获取流输出的
//覆盖这个方法,把数据写到一个缓存中,就可以进行获得数据
public ServletOutputStream getOutputStream() throws IOException {
ServletOutputStream sos = super.getOutputStream();
MyServletOutputStream msos = new MyServletOutputStream(sos,baos);
return msos;
}
//1如果是字符流则转成字符流,2把数据弄到baos中去
//查看API文档,PrintWriter的构造函数可以直接调用字符流进行输出
public PrintWriter getWriter() throws IOException {
pw = new PrintWriter(new OutputStreamWriter(baos, super.getCharacterEncoding()));
return pw;
}
public byte[] getBufferData() {
try {
//关闭Printwriter流
if(pw!=null)
pw.close();
baos.flush();
} catch (IOException e) {
e.printStackTrace();
}
return baos.toByteArray();
}
}
class MyServletOutputStream extends ServletOutputStream{
private ServletOutputStream sos;
private ByteArrayOutputStream baos;
public MyServletOutputStream(ServletOutputStream sos,ByteArrayOutputStream baos){
this.sos = sos;
this.baos = baos;
}
public void write(int b) throws IOException {
baos.write(b);
}
} |
案例五,对于常用的动态资源生成的结果进行缓存
web.xml配置 CacheResultFilter
只为category.jsp服务
建立CacheResultFilter 过滤器
建立cache HashMap。
四、文件上传与下载
1.文件上传需要具备的前提:
a,form表单的method必须是post
b,form表单的enctype必须是multipart/form-data(一定要记住头和值)
c,提供。。。。。
2,当表单的enctype=multipart/form-data请求正文的数据如下
建立工程01
建立upload.jsp
建立UploadServlet servlet---不需要记录
通过输入流得到数据
使用Commons-fileupload 组建
还要借助Commons-io
ServletFileupLoad是核心类 需要DiskFilterItemFactory(环境)来创建
tmpdir---java的临时目录
修改upload.jsp
建立Upload2Servlet servlet
拷贝jar包
取得真实的文件路径,非常的重要
修改upload.jsp
建立Upload3Servlet servlet
文件上传,需要考虑的9个问题
1,如何保证服务器的安全
把上传文件的目录设置在WEB-INF,客户端无法访问
2,中文乱码:
普通字段乱码
上传文件名中文乱码
1,文件名重复
3,文件格式限制(比如只允许上传图片)
4,上传文件的大小限制
一个文件的大小限制
总文件的大小限制
6,同一个目录中文件太多
7,多个文件上传,没有选择文件
8,上传进度提示问题
9,