JavaWeb -- Servlet Filter 过滤器
来源:互联网 发布:钉钉打卡软件 编辑:程序博客网 时间:2024/04/30 15:02
1. Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截,如下所示:
Filter开发分为二个步骤:
•编写java类实现Filter接口,并实现其doFilter方法。
•在 web.xml文件中使用<filter>和<filter-mapping>元素对编写的filter类进行注册,并设置它所能拦截的资源。(动手实验)
Filter链
•在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链。
•web服务器根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter,当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。
Filter的生命周期
init(FilterConfig filterConfig)throws ServletException:
•和我们编写的Servlet程序一样,Filter的创建和销毁由WEB服务器负责。web应用程序启动时,web服务器将创建Filter的实例对象,并调用其init方法,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作(注:filter对象只会创建一次,init方法也只会执行一次。示例 )
•开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。(filterConfig对象见下页PPT)
destroy():
在Web容器卸载Filter对象之前被调用。该方法在Filter的生命周期中仅执行一次。在这个方法中,可以释放过滤器使用的资源。
FilterConfig接口
用户在配置filter时,可以使用<init-param>为filter配置一些初始化参数,当web容器实例化Filter对象,调用其init方法时,会把封装了filter初始化参数的filterConfig对象传递进来。因此开发人员在编写filter时,通过filterConfig对象的方法,就可获得:
•String getFilterName():得到filter的名称。
•String getInitParameter(String name):返回在部署描述中指定名称的初始化参数的值。如果不存在返回null.
•Enumeration getInitParameterNames():返回过滤器的所有初始化参数的名字的枚举集合。
•public ServletContext getServletContext():返回Servlet上下文对象的引用。
Filter的部署
<filter-name>用于为过滤器指定一个名字,该元素的内容不能为空。
<filter-class>元素用于指定过滤器的完整的限定类名。
<init-param>元素用于为过滤器指定初始化参数,它的子元素<param-name>指定参数的名字,<param-value>指定参数的值。在过滤器中,可以使用FilterConfig接口对象来访问初始化参数。
<filter-mapping>元素用于设置一个Filter所负责拦截的资源。一个Filter拦截的资源可通过两种方式来指定:Servlet名称和资源访问的请求路径
•<filter-name>子元素用于设置filter的注册名称。该值必须是在<filter>元素中声明过的过滤器的名字
•<url-pattern>设置filter所拦截的请求路径(过滤器关联的URL样式)
•<servlet-name>指定过滤器所拦截的Servlet名称。
•<dispatcher>指定过滤器所拦截的资源被Servlet容器调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认REQUEST。用户可以设置多个<dispatcher>子元素用来指定Filter对资源的多种调用方式进行拦截。
<dispatcher> 子元素可以设置的值及其意义:
•REQUEST:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。
•INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。
•FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。
•ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。
<filter> <filter-name>testFitler</filter-name> <filter-class>org.test.TestFiter</filter-class> <init-param> <param-name>word_file</param-name> <param-value>/WEB-INF/word.txt</param-value> </init-param></filter>
<filter-mapping> <filter-name>testFilter</filter-name> <url-pattern>/test.jsp</url-pattern></filter-mapping>
<filter-mapping> <filter-name>testFilter</filter-name> <url-pattern>/index.jsp</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher></filter-mapping>
2. 实例
Filter常见应用(1) -- 全站乱码过滤
统一全站字符编码的过滤器
•通过配置参数encoding指明使用何种字符编码,以处理Html Form请求参数的中文问题
过滤器代码:
public class EncodingFilter implements Filter {private FilterConfig filterConfig;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {this.filterConfig = filterConfig;}@Overridepublic void doFilter(ServletRequest req, ServletResponse res,FilterChain chain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) req;HttpServletResponse response = (HttpServletResponse) res;String charset = this.filterConfig.getInitParameter("charset");request.setCharacterEncoding(charset);response.setCharacterEncoding(charset);response.setContentType("text/html;charset="+ charset);MyCharacterEncodingRequest myrequest = new MyCharacterEncodingRequest(request);chain.doFilter(myrequest, response);}@Overridepublic void destroy() {}}/* * 装饰者模式1.实现与被增强对象相同的接口 2、定义一个变量记住被增强对象3、定义一个构造器,接收被增强对象4、覆盖需要增强的方法5、对于不想增强的方法,直接调用被增强对象(目标对象)的方法 */class MyCharacterEncodingRequest extends HttpServletRequestWrapper{private HttpServletRequest request = null;public MyCharacterEncodingRequest(HttpServletRequest request) {super(request);this.request = request;}@Overridepublic String getParameter(String name) {try{String value = this.request.getParameter(name);if(value==null)return null;if(request.getMethod().equalsIgnoreCase("post"))return value;value = new String( value.getBytes("ISO8859-1"), this.request.getCharacterEncoding());return value;}catch(Exception e){throw new RuntimeException(e);}}
web.xml 配置
<filter> <filter-name>EncodingFilter</filter-name> <filter-class>com.kevin.web.EncodingFilter</filter-class> <init-param> <param-name>charset</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>EncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
测试servlet
public class servlet1 extends HttpServlet {private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public servlet1() { super(); // TODO Auto-generated constructor stub }/** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.getWriter().write("servlet1中国"); String param1 = request.getParameter("param1"); String param2 = request.getParameter("param2"); System.out.println("Param1: " + param1); System.out.println("Param2: " + param2);}/** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}}
测试jsp
<%@ page language="java" import="java.util.*" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!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><!-- get方式 测试参数乱码问题 --><c:url value="/servlet1" scope="page" var="encodingTest"><c:param name="param1" value="中国param1"></c:param></c:url><a href="${encodingTest}">encodingTest get方式测试</a><!-- post方式 测试参数乱码问题 --><form action="${pageContext.request.contextPath}/servlet1" method="post">输入<input type="text" name="param2">提交<input type="submit" value="提交"></form></body></html>
Filter常见应用(2) -- 不缓存
禁止浏览器缓存所有动态页面的过滤器:
•有 3个HTTP响应头字段都可以禁止浏览器缓存当前页面,它们在Servlet中的示例代码如下:
•response.setDateHeader("Expires",-1);
•response.setHeader("Cache-Control","no-cache");
•response.setHeader("Pragma","no-cache");
•并不是所有的浏览器都能完全支持上面的三个响应头,因此最好是同时使用上面的三个响应头。
•Expires数据头:值为GMT时间值,为-1指浏览器不要缓存页面
•Cache-Control响应头有两个常用值:
•no-cache指浏览器不要缓存当前页面。
•max-age:xxx指浏览器缓存页面xxx秒。
过滤器代码:
public class NoCacheFilter implements Filter {public void doFilter(ServletRequest req, ServletResponse resp,FilterChain chain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) req;HttpServletResponse response = (HttpServletResponse) resp;response.setDateHeader("Expires", -1);response.setHeader("Cache-Control", "no-cache");response.setHeader("Pragma", "no-cache");chain.doFilter(request, response);}public void init(FilterConfig filterConfig) throws ServletException {}public void destroy() {}}
web.xml配置: 拦截所需资源
Filter常见应用(3) -- 控制缓存
控制浏览器缓存页面中的静态资源的过滤器:
•场景:有些动态页面中引用了一些图片或css文件以修饰页面效果,这些图片和css文件经常是不变化的,所以为减轻服务器的压力,可以使用filter控制浏览器缓存这些文件,以提升服务器的性能。
过滤器代码:
public class ExpiresFilter implements Filter {private FilterConfig filterConfig;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {this.filterConfig = filterConfig;}@Overridepublic void doFilter(ServletRequest req, ServletResponse resp,FilterChain chain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) req;HttpServletResponse response = (HttpServletResponse) resp;//1.获取用户想访问的资源String uri = request.getRequestURI();//2.得到用户想访问的资源的后缀名String ext = uri.substring( uri.lastIndexOf(".")+1 );//3.得到资源需要缓存的时间String time = filterConfig.getInitParameter(ext);if(time!=null){long t = Long.parseLong(time) * 3600 * 1000;response.setDateHeader("expires", System.currentTimeMillis() + t);}chain.doFilter(request, response);}@Overridepublic void destroy() {// TODO Auto-generated method stub}}
web.xml配置方法
<filter> <filter-name>ExpiresFilter</filter-name> <filter-class>com.kevin.web.ExpiresFilter</filter-class> <init-param> <param-name>css</param-name> <param-value>4</param-value> </init-param> <init-param> <param-name>jpg</param-name> <param-value>1</param-value> </init-param> <init-param> <param-name>js</param-name> <param-value>4</param-value> </init-param> </filter> <filter-mapping> <filter-name>ExpiresFilter</filter-name> <url-pattern>*.css</url-pattern> </filter-mapping> <filter-mapping> <filter-name>ExpiresFilter</filter-name> <url-pattern>*.jpg</url-pattern> </filter-mapping> <filter-mapping> <filter-name>ExpiresFilter</filter-name> <url-pattern>*.js</url-pattern> </filter-mapping>
Filter常见应用(4)
使用Filter实现URL级别的权限认证
•情景:在实际开发中我们经常把一些执行敏感操作的servlet映射到一些特殊目录中,并用filter把这些特殊目录保护起来,限制只能拥有相应访问权限的用户才能访问这些目录下的资源。从而在我们系统中实现一种URL级别的权限功能。
•要求:为使Filter具有通用性,Filter保护的资源和相应的访问权限通过filter参数的形式予以配置。
Filter常见应用(5)
实现用户自动登陆的过滤器
•在用户登陆成功后,发送一个名称为user的cookie给客户端,cookie的值为用户名和md5加密后的密码。
编写一个AutoLoginFilter,这个filter检查用户是否带有名称为user的cookie来,如果有,则调用dao查询cookie的用户名和密码是否和数据库匹配,匹配则向session中存入user对象(即用户登陆标记),以实现程序完成自动登陆
过滤器代码:
public class AutoLoginFilter implements Filter {public void doFilter(ServletRequest req, ServletResponse resp,FilterChain chain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) req;HttpServletResponse response = (HttpServletResponse) resp;if(request.getSession().getAttribute("user")!=null){chain.doFilter(request, response);return;}//1.得到用户带过来的authlogin的cookie,String value = null;Cookie cookies[] = request.getCookies();for(int i=0;cookies!=null && i<cookies.length;i++){if(cookies[i].getName().equals("autologin")){value = cookies[i].getValue();}}//2.得到 cookie中的用户名和密码 if(value!=null){String username = value.split("\\.")[0];String password = value.split("\\.")[1];//3.调用dao获取用户对应的密码UserDao dao = new UserDao();User user = dao.find(username);String dbpassword = user.getPassword();//4.检查用户带过来的md5的密码和数据库中的密码是否匹配,如匹配则自动登陆if(password.equals(WebUtils.md5(dbpassword))){request.getSession().setAttribute("user", user);}}chain.doFilter(request, response);}public void destroy() {// TODO Auto-generated method stub}public void init(FilterConfig filterConfig) throws ServletException {// TODO Auto-generated method stub}}
登录servlet
public class LoginServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {String username = request.getParameter("username");String password = request.getParameter("password");UserDao dao = new UserDao();User user = dao.find(username, password);if(user==null){request.setAttribute("message", "用户名或密码不对!!");request.getRequestDispatcher("/message.jsp").forward(request, response);return;}request.getSession().setAttribute("user", user);request.setAttribute("message", "恭喜,登陆成功!!");//发送自动登陆cookiesendAutoLoginCookie(request,response,user);request.getRequestDispatcher("/message.jsp").forward(request, response);}private void sendAutoLoginCookie(HttpServletRequest request, HttpServletResponse response, User user) {int logintime = Integer.parseInt(request.getParameter("logintime"));Cookie cookie = new Cookie("autologin",user.getUsername() + "." + WebUtils.md5(user.getPassword()));cookie.setMaxAge(logintime);cookie.setPath("/day18");response.addCookie(cookie);}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}}
3. request对象的增强
Servlet API 中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper,(HttpServletRequestWrapper类实现了request接口中的所有方法,但这些方法的内部实现都是仅仅调用了一下所包装的的 request对象的对应方法)以避免用户在对request对象进行增强时需要实现request接口中的所有方法。
上面的乱码过滤就是request增强。
------------------- 脏话 过滤器 --------------------------
//脏话过滤器public class DirtyFilter implements Filter {public void doFilter(ServletRequest req, ServletResponse resp,FilterChain chain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) req;HttpServletResponse response = (HttpServletResponse) resp;DirtyRequest dirtyrequest = new DirtyRequest(request);chain.doFilter(dirtyrequest, response);}public void init(FilterConfig filterConfig) throws ServletException {}public void destroy() {}}class DirtyRequest extends HttpServletRequestWrapper{private List<String> dirtyWords = Arrays.asList("傻B","操蛋","畜生");private HttpServletRequest request;public DirtyRequest(HttpServletRequest request) {super(request);this.request = request;}@Overridepublic String getParameter(String name) {String value = this.request.getParameter(name);if(value==null){return null;}for(String dirtyWord : dirtyWords){if(value.contains(dirtyWord)){value = value.replace(dirtyWord, "****");}}return value;}}
------------------------ HTML 过滤器 ------------------------------
//html转义过滤器public class HtmlFilter implements Filter {public void doFilter(ServletRequest req, ServletResponse resp,FilterChain chain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) req;HttpServletResponse response = (HttpServletResponse) resp;MyHtmlRequest myrequest = new MyHtmlRequest(request);chain.doFilter(myrequest, response);}public void destroy() {// TODO Auto-generated method stub}public void init(FilterConfig filterConfig) throws ServletException {// TODO Auto-generated method stub}}class MyHtmlRequest extends HttpServletRequestWrapper{private HttpServletRequest request;public MyHtmlRequest(HttpServletRequest request) {super(request);this.request = request;}@Overridepublic String getParameter(String name) {String value = this.request.getParameter(name);if(value==null){return null;}return filter(value);} public String filter(String message) { if (message == null) return (null); char content[] = new char[message.length()]; message.getChars(0, message.length(), content, 0); StringBuffer result = new StringBuffer(content.length + 50); for (int i = 0; i < content.length; i++) { switch (content[i]) { case '<': result.append("<"); break; case '>': result.append(">"); break; case '&': result.append("&"); break; case '"': result.append("""); break; default: result.append(content[i]); } } return (result.toString()); }}
4. response对象的增强
Servlet API 中提供了response对象的Decorator设计模式的默认实现类HttpServletResponseWrapper,(HttpServletResponseWrapper类实现了response接口中的所有方法,但这些方法的内部实现都是仅仅调用了一下所包装的的response对象的对应方法)以避免用户在对response对象进行增强时需要实现response接口中的所有方法。
//解决全站压缩public class GzipFilter implements Filter {public void doFilter(ServletRequest req, ServletResponse resp,FilterChain chain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) req;HttpServletResponse response = (HttpServletResponse) resp;BufferResponse myresponse = new BufferResponse(response);chain.doFilter(request, myresponse);//拿出缓存中的数据,压缩后再打给浏览器byte out[] = myresponse.getBuffer();System.out.println("原始大小:" + out.length);ByteArrayOutputStream bout = new ByteArrayOutputStream();GZIPOutputStream gout = new GZIPOutputStream(bout);gout.write(out);gout.close();byte gzip[] = bout.toByteArray();System.out.println("压缩后的大小:" + gzip.length);response.setHeader("content-encoding", "gzip");response.setContentLength(gzip.length);response.getOutputStream().write(gzip);}public void destroy() {}public void init(FilterConfig filterConfig) throws ServletException {}}class BufferResponse extends HttpServletResponseWrapper{private ByteArrayOutputStream bout = new ByteArrayOutputStream();private PrintWriter pw;private HttpServletResponse response;public BufferResponse(HttpServletResponse response) {super(response);this.response = response;}@Overridepublic ServletOutputStream getOutputStream() throws IOException {return new MyServletOutputStream(bout);}@Overridepublic PrintWriter getWriter() throws IOException {pw = new PrintWriter(new OutputStreamWriter(bout,this.response.getCharacterEncoding())); //PrintWriter.write(中国) <br>return pw;}public byte[] getBuffer(){try{if(pw!=null){pw.close();}if(bout!=null){bout.flush();return bout.toByteArray();}return null;}catch (Exception e) {throw new RuntimeException(e);}}}class MyServletOutputStream extends ServletOutputStream{private ByteArrayOutputStream bout;public MyServletOutputStream(ByteArrayOutputStream bout){this.bout = bout;}@Overridepublic void write(int b) throws IOException {this.bout.write(b);}}
------------------------------- 案例: 缓存数据到内存 -------------------------------
过滤器
//缓存数据到内存public class CachedFilter implements Filter {private Map<String,byte[]> map = new HashMap<String,byte[]>();public void doFilter(ServletRequest req, ServletResponse resp,FilterChain chain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) req;HttpServletResponse response = (HttpServletResponse) resp;//1.得到用户请求的uriString uri = request.getRequestURI();//2.看缓存中有没有uri对应的数据byte b[] = map.get(uri);//3.如果缓存中有,直接拿缓存的数据打给浏览器,程序返回if(b!=null){response.getOutputStream().write(b);return;}//4.如果缓存没有,让目标资源执行,并捕获目标资源的输出BufferResponse1 myresponse = new BufferResponse1(response);chain.doFilter(request, myresponse);byte out[] = myresponse.getBuffer();//5.把资源的数据以用户请求的uri为关键字保存到缓存中map.put(uri, out);//6.把数据打给浏览器response.getOutputStream().write(out);}public void init(FilterConfig filterConfig) throws ServletException {}public void destroy() {}}class BufferResponse1 extends HttpServletResponseWrapper{private ByteArrayOutputStream bout = new ByteArrayOutputStream(); //捕获输出的缓存private PrintWriter pw;private HttpServletResponse response;public BufferResponse1(HttpServletResponse response) {super(response);this.response = response;}@Overridepublic ServletOutputStream getOutputStream() throws IOException {return new MyServletOutputStream1(bout);}@Overridepublic PrintWriter getWriter() throws IOException {pw = new PrintWriter(new OutputStreamWriter(bout,this.response.getCharacterEncoding()));return pw;}public byte[] getBuffer(){try{if(pw!=null){pw.close();}return bout.toByteArray();}catch (Exception e) {throw new RuntimeException(e);}}}class MyServletOutputStream1 extends ServletOutputStream{private ByteArrayOutputStream bout;public MyServletOutputStream1(ByteArrayOutputStream bout){ //接收数据写到哪里this.bout = bout;}@Overridepublic void write(int b) throws IOException {bout.write(b);}}
0 0
- JavaWeb -- Servlet Filter 过滤器
- javaWeb-Servlet之Filter(过滤器)
- javaWeb-Servlet之Filter(过滤器二)
- JavaWeb学习篇之----Servlet过滤器Filter
- javaweb--Servlet过滤器Filter简单实现
- JavaWeb学习篇之----Servlet过滤器Filter和监听器
- JavaWeb学习篇之----Servlet过滤器Filter和监听器
- JavaWeb学习篇之----Servlet过滤器Filter和监听器
- JavaWeb开发过滤器Filter
- javaweb---过滤器(Filter)
- JavaWeb过滤器Filter
- javaWeb之过滤器Filter
- 【JavaWeb】之过滤器Filter
- JavaWeb的Filter过滤器
- javaWeb-过滤器filter
- JavaWeb---过滤器Filter---(一)
- JavaWeb---过滤器Filter---(二)
- JavaWeb:过滤器Filter
- diff 和 patch
- 统计分词/无字典分词学习(5):候选片段的过滤方法,边界稳定性
- 使用Rich Edit 控件需要调用 AfxInitRichEdit2()
- AFDX总线协议规范
- zlib的安装与使用
- JavaWeb -- Servlet Filter 过滤器
- SVN 项目管理方法
- 文本分类入门(一)文本分类问题的定义
- “System.Data.DataSet”不包含“GetEnumerator”的公共定义,因此 foreach 语句不能作用于“System.Data.DataSet”类型的变量
- 思维模式的突破
- 电商课题:对付秒杀器等恶意访问行为的简单梳理
- 用hibernate内置方法取对象列表,前台用el表达式取对象的对象出错的原因
- 为什么eclipse下面, adb 运行得不正常
- VS2013不支持多字节编码
原创粉丝点击
热门IT博客
热门问题
老师的惩罚
人脸识别
我在镇武司摸鱼那些年
重生之率土为王
我在大康的咸鱼生活
盘龙之生命进化
天生仙种
凡人之先天五行
春回大明朝
姑娘不必设防,我是瞎子
铁架床总响怎么办
法院判决不公正怎么办
法院枉法裁判怎么办
法官乱判怎么办
别人无原无骂我怎么办
总是放不开自己怎么办
人家骂你怎么办
断奶后奶胀怎么办
断奶过程中涨奶怎么办
断奶奶涨痛厉害怎么办
断奶乳房松弛怎么办
断奶乳房胀怎么办
断奶时奶涨痛怎么办
忌奶涨奶有硬块怎么办
断奶后涨奶很疼怎么办
发际线退后怎么办
婴儿涨肚怎么办
小腿粗怎么办
八字胸怎么办
卵巢黄体破裂怎么办
老公心里出轨怎么办
吃七珍丸肚子疼怎么办
面对妻子性无能怎么办
肋骨宽大怎么办
休学复学手续怎么办
大学复学手续怎么办
泰国佛牌不带了怎么办
心烦时该怎么办
心烦怎么办啊
被下降头怎么办
小米电视不清楚怎么办
腰酸背痛怎么办吃啥药
有了不想要怎么办
思想不集中怎么办
米饭太硬怎么办
克莉丝汀卡过期怎么办
脚掌下有块硬茧怎么办
文件重命名不了怎么办
word不能重命名怎么办
文件无法重命名怎么办
怎么办移动400电话