JavaWeb学习笔记3:HttpServlet(Request&Response)

1-Servlet 配置要点
  1. 全路径匹配
    > 以"/"开始。如:/a、/aa/bb
    > localhost:8080/项目名称/aa/bb
  2. 路径匹配,前半段匹配
    > 以"/“开始 ,但是以” * "结束 。如:/a/* 、/*
    > * 其实是一个通配符,匹配任意文字
    > localhost:8080/项目名称/aa/bb
  3. 以扩展名匹配
    > 写法:以" * "开始 。如:.扩展名、.aa、*.bb

ServletContext 配置全局参数,与Java类似,定义在外面,具体如下:

<!-- 定义全局参数 -->
<context-param>
	<param-name>favorite</param-name>
	<param-value>type and thinking</param-value>
</context-param>
2-ServletContext 获取资源文件(重点要考)

ServletContex有什么作用?

  1. 获取全局配置参数
  2. 获取web工程中的资源
  3. 存取数据,servlet间共享数据域对象

ServletContext 何时创建,何时销毁?

  1. 服务器启动的时候,会为托管的每一个web应用程序,创建一个ServletContext对象
  2. 从服务器移除托管,或者是关闭服务器

ServletContext的作用范围:只要在同一项目中,都可以取。
:A项目存,为什么在B项目取不到的? :ServletContext对象不同

这里就不多BB,直接上我的之前写的一篇博客:Servlet读取文件方式总结

3-ServletContext 获取登录成功总数
  1. 要提供信息,肯定要可视化界面,所以写一个html,要form表单提供信息
  2. 要获取信息,写一个Servlet,并且去web.xml中配置,利用req对象的getParameter方法获取信息
  3. 校验填写信息是否正确,并打印结果,具体代码如下:
    index.html中:
    <body>
    	<h2>请登录!</h2>
    	<form action="login" method="get">
    		账号:<input type="text" name="username">
    		密码:<input type="text" name="password">
    		<input type="submit" value="登录">
    	</form>
    </body>
    
    LoginServlet的doGet中:
    String username = req.getParameter("username");
    String password = req.getParameter("password");
    if(username.equals("hpf")&&password.equals("123456")){
    	System.out.println("login success!");
    	resp.getWriter().write("login success!");
    }else{
    	System.out.println("login faild!");
    	resp.getWriter().write("login faild!");
    }
    
  4. 要实现登录成功的跳转,首先必须还得有一个login_success.html,里面提供一个用于获取次数
  5. 要获取次数,必须还要有一个CountServlet。并且,利用ServletContext来获取次数,并打印于页面
  6. 个人书写代码总结与注意点:

1.html与Servlet的关联,即form中的action所填写的内容必须是web.xml中配置的url-pattern
2.每写一个Servlet(除了新建的时候选择Servlet),否则,一定要手动在web.xml中配置
3.doGet与doPost中的请求和响应对象都要利用好,这里使用到了信息的获取及页面的跳转
4.ServletContext可以设置属性,并且读取属性,这是获取次数的关键所在
5.Servlet路径和html路径实际上在运行时是在同一路径下的,都是在工程目录下,同级

以下为示例的完整代码(完整版):
index.html中:

<body>
	<h2>请登录!</h2>
	<form action="login" method="get">
		账号:<input type="text" name="username">
		密码:<input type="text" name="password">
		<input type="submit" value="登录">
	</form>
</body>

LoginServlet的doGet中:

ServletContext sc = getServletContext();
String username = req.getParameter("username");
String password = req.getParameter("password");
Object count = sc.getAttribute("count");
if(count==null){
	count = 1;
	sc.setAttribute("count", (int)count);
}else{
	sc.setAttribute("count",((int)count+1));
}
if(username.equals("hpf")&&password.equals("123456")){
	System.out.println("login success!");
	//设置状态码
	resp.setStatus(302);
	//定位跳转的位置是哪个页面
	resp.setHeader("Location", "loginSuccess.html");
}else{
	System.out.println("login faild!");
	resp.getWriter().write("login faild!");
}

loginSuccess.html中:

<body>
	<h1>congratulation!login success!</h1>
	<a href="count">点击获取登录成功的次数</a>
</body>

CountServlet的doGet中:

ServletContext sc = getServletContext();
int count = (int)sc.getAttribute("count");
resp.getWriter().write("count:"+count);
4-HttpServletRequest与中文乱码问题

问:HttpServletRequest到底有什么用? 答:这个对象封装了客户端提交过来的一切数据。

  1. 可以获取客户端请求头信息

    //得到一个枚举集合  
    Enumeration<String> headerNames = request.getHeaderNames();
    while (headerNames.hasMoreElements()) {
    	String name = (String) headerNames.nextElement();
    	String value = request.getHeader(name);
    	System.out.println(name+"="+value);
    }
    
  2. 获取客户端提交过来的数据

    String name = request.getParameter("name");
    String address = request.getParameter("address");
    System.out.println("name="+name);
    System.out.println("address="+address);
    -------------------------------------------------
    //name=zhangsan&name=lisi&name=wangwu 一个key可以对应多个值。
    Map<String, String[]> map = request.getParameterMap();
    Set<String> keySet = map.keySet();
    Iterator<String> iterator = keySet.iterator();
    while (iterator.hasNext()) {
    	String key = (String) iterator.next();
    	System.out.println("key="+key + "--的值总数有:"+map.get(key).length);
    	String value = map.get(key)[0];
    	String value1 = map.get(key)[1];
    	String value2 = map.get(key)[2];
    	System.out.println(key+" ======= "+ value + "=" + value1 + "="+ value2);
    }
    //一般情况下,传过来的数据不可能是name=hpf&name=hillain,所以上面的value数组一般不写
    
  3. 获取中文数据
    客户端提交数据给服务器端,若数据中带有中文并出现乱码情况,则可以参照以下方法解决
    1、如果是GET方式:

    //使用代码转码
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    System.out.println("userName="+username+"==password="+password);
    //get请求过来的数据,在url地址栏上就已经经过编码了,所以我们取到的就是乱码
    //tomcat收到了这批数据,getParameter 默认使用ISO-8859-1去解码
    //先让文字回到ISO-8859-1对应的字节数组 , 然后再按utf-8组拼字符串
    username = new String(username.getBytes("ISO-8859-1") , "UTF-8");
    System.out.println("userName="+username+"==password="+password);
    
    //可以在tomcat里面做设置处理,conf/server.xml加上URIEncoding="utf-8"
    //直接在tomcat里面做配置,以后get请求过来的数据永远都是用UTF-8编码
     <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/>
    

    2、如果是POST方式

    request.setCharacterEncoding("UTF-8"); //这行设置一定要写在getParameter之前
    请求体里面的文字编码get方式,用这行,有用吗? ---> 没用
    

关于使用get导致的乱码为什么需要用ISO-8859-1来解,看下图就知道了:
get乱码解释

5-HttpServletResponse与中文乱码问题

问:HttpServletResponse到底有什么用? 答:这个对象负责返回数据给客户端。

//以字符流的方式写数据	
//response.getWriter().write("<b>hello response...</b>");
//以字节流的方式写数据 
response.getOutputStream().write("hello response2222...".getBytes());

响应的数据中有中文,那么有可能出现中文乱码
下面详细说明了2两种出现中文乱码的情况以及如何解决:

  1. 以字符流输出

    response.getWriter()
    //1. 指定输出到客户端的时候,这些文字使用UTF-8编码
    response.setCharacterEncoding("UTF-8");
    //2. 直接规定浏览器看这份数据的时候,使用什么编码来看
    response.setHeader("Content-Type", "text/html; charset=UTF-8");
    response.getWriter().write("这是个测试...");
    
  2. 以字节流输出

    response.getOutputStream()
    //1. 指定浏览器看这份数据使用的码表
    response.setHeader("Content-Type", "text/html;charset=UTF-8");
    //2. 指定输出的中文用的码表
    response.getOutputStream().write("这是个测试...".getBytes("UTF-8"));
    
  3. 不管是字节流还是字符流,直接使用一行代码就可以了

    response.setContentType("text/html;charset=UTF-8");
    
6-HttpServletResponse实现下载文件

其实实现很简单,最简单的莫过于直接利用Tomcat提供下载。即你写一个html,把文件放上去,运行Web,然后鼠标点击即可下载,但是这里的下载是会直接打开的,也就是说如果不是文本,而是压缩包之类的话,是会直接显示乱码的,所以这种方式并不可取。
那就先说一下为什么我们什么都不用做就可以实现下载,这是因为Tomcat里有一个默认的Servlet,也就是DefaultServlet,这个Servlet专门用于处理放在Tomcat服务器上面的静态资源,也就是Html、Css这类的东西。
下面就来手动实现一下利用Response来下载文件:

  1. 先写html,将href改为"Servlet名?filename=文件名.格式"
  2. 写一个Servlet,首先获取数据,然后获取文件路径,设置以对话框的方式下载文件,最后使用流保存
  3. 代码如下:
    download.html:
    <body>
    	<h3>文件下载</h3>
    	<a href="test?filename=lqtzs.png">lqtzs.png</a>
    </body>
    
    HttpServletResponse:
    //1.获取下载的文件名字aa.jpg -- inputStream
    String fileName = req.getParameter("filename");
    //2.获取这个文件在tomcat里面的绝对路径地址
    String path = getServletContext().getRealPath(fileName);
    //让浏览器收到这份资源的时候,以下载的方式提醒用户,而不是直接显示
    resp.setHeader("Content-Disposition", "attachment; filename="+fileName);
    //3.转换成输入法(若没有3,也有对话框,不过没法保存)
    InputStream is = new FileInputStream(path);
    OutputStream os = resp.getOutputStream();
    int len = 0;
    byte[] buffer = new byte[1024];
    while((len = is.read(buffer))!=-1){
    	os.write(buffer,0,len);
    }
    os.close();
    is.close();
    
7-Servlet综合训练

综合训练 - 实现注册,保存数据,跳转到登录,并在线下载
心得与总结:

  1. 首先,如果新建了一个Web工程的话,如果要将这个工程删除,那么一定要先去工作环境中把这个删了
  2. getContextPath.getRealPath(“文件名”)也适用于将要存储的文件,原先并不存在
  3. Writer的写法以及OutputStream的写法有点生疏了,resp的跳转以及刷新等功能还要继续加强学习
  4. resp.setContentType(“text/html;charset=UTF-8”);代码解决中文乱码很重要
  5. 因为我们自己定义的OutputStream要写文件路径,相当于把路径写死了,所以我们在下载的代码中应写resp.getOutputStream,其实很好理解,就是用服务器响应的输出流,将文件输出
  6. 具体Version1完整代码如下:
    regist.html:
    <body>
    	<h3>请注册:</h3>
    	<form action="save" method="get">
    		账号:<input type="text" name="username"><br><br>
    		密码:<input type="password" name="password"><br><br>
    		昵称:<input type="text" name="nickname"><br><br>
    		<input type="submit" value="注册">
    	</form>
    </body>
    
    SaveServlet:
    ServletContext sc = getServletContext();
    //String realPath = sc.getContextPath();
    //System.out.println(realPath);	//测试路径
    //获得Map集合
    Map<String, String[]> pm = req.getParameterMap();
    Set<String> ks = pm.keySet();
    Iterator<String> iterator = ks.iterator();
    Writer os = new FileWriter(sc.getRealPath("user.properties"));
    while(iterator.hasNext()){
    	String key = iterator.next();
    	String value = pm.get(key)[0];
    	String parameter = new String(key+"="+value);
    	System.out.println();
    	System.out.printf(parameter);
    	os.write(parameter);
    	os.append("\n");
    }
    os.close();
    //设置跳转
    resp.setStatus(302);
    resp.setHeader("Location", "login.html");
    
    login.html:
    <body>
    	<h3>请登录:</h3>
    	<form action="login">
    		账号:<input type="text" name="username">
    		密码:<input type="password" name="password">
    		<input type="submit" value="登录">
    	</form>
    </body>
    
    LoginServlet:
    String username_req = req.getParameter("username");
    String password_req = req.getParameter("password");
    Properties ps = new Properties();
    ServletContext sc = getServletContext();
    InputStream is = sc.getResourceAsStream("user.properties");
    ps.load(is);
    String username_ps = ps.getProperty("username");
    String password_ps = ps.getProperty("password");
    resp.setContentType("text/html;charset=UTF-8");
    if(username_req.equals(username_ps)&&password_req.equals(password_ps)){
    	resp.setStatus(302);
    	resp.setHeader("Location", "download.html");
    }else{
    	resp.getWriter().write("账号密码输入错误!");
    	resp.setHeader("refresh", "3;login.html");
    }
    
    download.html:
    <body>
    	<h3>请选择合适文件下载</h3>
    	<a href="download?filename=lqtzs.png">lqtzs.png</a>
    </body>
    
    DownloadServlet:
    //1.获取下载的文件名字aa.jpg -- inputStream
    String fileName1 = req.getParameter("filename");
    System.out.println(fileName1);
    //2.获取文件名的时候,以防中文乱码也要转码
    fileName1 = new String(fileName1.getBytes("ISO-8859-1"),"UTF-8");
    System.out.println(fileName1);
    //3.获取这个文件在tomcat里面的绝对路径地址
    String path = getServletContext().getRealPath(fileName1);
    /*4.如果文件的名字带有中文,那么要对这个文件名进行编码处理
    如果是IE或者Chrome,使用URLEncoding编码
    如果是Firefox,使用Base64编码*/
    String ua = req.getHeader("User-Agent");
    if(ua.contains("Firefox")){
    	fileName1 = DownloadUtil.base64EncodeFileName(fileName1);
    }else{
    	fileName1 = URLEncoder.encode(fileName1, "UTF-8");
    }
    //5.让浏览器收到这份资源的时候,以下载的方式提醒用户,而不是直接显示
    resp.setHeader("Content-Disposition", "attachment; filename="+fileName1);
    InputStream is = new FileInputStream(path);
    OutputStream os = resp.getOutputStream();
    byte[] bytes = new byte[1024];
    int len = -1;
    while((len = is.read(bytes))!=-1){
    	os.write(bytes, 0, len);;
    }
    os.close();
    is.close();
    
HPF-自我总结

  我认为这一部分的重点就是中文乱码的处理以及Html和Servlet之间连接的一种思路了,因为response和request,其实用着用着就会了。而难点可能就是利用输入输出流的操作,因为我之前就犯了个错误,在DownloadServlet书写的时候,Outputstream就没有用resp.getOutputStream,而是随手new了一个,哈哈哈,结果可想而知。
  这是一篇笔记博客,如果能帮到人的话那更好了哈哈哈。Last but not least,学习与坐禅相似,须有一颗恒心。

发布了15 篇原创文章 · 获赞 18 · 访问量 4576

猜你喜欢

转载自blog.csdn.net/oZuoShen123/article/details/105061015