HttpServletRequest&HttpServletResponse
HttpServletRequest&HttpServletResponse
1.Servlet配置方式
-
全路径匹配
以/开始,如/a,/HelloServlet
访问方式:localhost:8080/项目名称/a
-
路径匹配,前半段匹配
以/开始,以*结束,如/b/*,/*
访问方式:localhost:8080/项目名称/b/任意
-
扩展名匹配
没有/,以*开始,如*.aa
访问方式:localhost:8080/项目名称/任意.aa
2.ServletContext
Servlet上下文,每个web工程都只有一个ServletContext对象,即在一个web工程中无论在哪个Sevlet里获取到的ServletContext都是同一个。在B项目重无法取到A项目的ServletContext,因为ServletContext对象不同。
2.1作用
2.1.1获取全局配置参数
- web.xml
<!--全局配置参数,哪个Servlet都可以拿到-->
<context-param>
<param-name>producer</param-name>
<param-value>wang</param-value>
</context-param>
- HelloServlet03
//获取ServletContext对象
ServletContext servletContext = getServletContext();
//1.获取全局参数
String producer = servletContext.getInitParameter("producer");
System.out.println(producer);
2.1.2获取web工程中的资源
- config.properties
name=zhangsan
- HelloServlet3
//2.获取web工程中的资源
//2.1法一:先获取config.properties在tomcat里的绝对路径,再new InputStream
String realPath = servletContext.getRealPath("");//获取项目在tomcat里的根目录
System.out.println(realPath);//D:\IDEA.workspace\Demo01\out\artifacts\Demo1_war_exploded2\
String realPath1 = servletContext.getRealPath("file/config.properties");
System.out.println(realPath1);//D:\IDEA.workspace\Demo01\out\artifacts\Demo1_war_exploded2\file\config.properties
Properties p=new Properties();
InputStream is=new FileInputStream(realPath1);
p.load(is);
System.out.println(p.getProperty("name"));
//2.2法二:直接给相对路径,通过getResourceAsStream获取资源流对象
InputStream resourceAsStream1 = servletContext.getResourceAsStream("file/config.properties");
p.load(resourceAsStream1);
System.out.println(p.getProperty("name"));
- 通过classLoader获取web工程下的资源
InputStream resourceAsStream = HelloServlet3.class.getClassLoader().getResourceAsStream("../../file/config.properties");
/*
此处classLoader的路径为:D:\IDEA.workspace\Demo01\out\artifacts\Demo1_war_exploded2\WEB-INF\classes,所以需要往上找两级,才能获取config.properties的相对路径
*/
p.load(resourceAsStream);
System.out.println(p.getProperty("name"));
2.1.3存取数据,servlet间共享数据
-
login.html
<form action="LoginServlet" method="get"> 账号:<input type="text" name="username"><br/> 密码:<input type="text" name="password"><br/> <input type="submit" value="登录"> </form>
-
LoginServlet
public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1.获取数据 String username = req.getParameter("username"); String password = req.getParameter("password"); PrintWriter pw=resp.getWriter(); //2.校验数据 if (username.equals("abc")&&password.equals("123")){ ServletContext servletContext = getServletContext(); //2.1获取以前登录成功的次数 Integer count =(Integer) servletContext.getAttribute("count"); if(null==count){ count=0; } //2.2登录成功次数加1 servletContext.setAttribute("count",count+1); //2.3跳转到login_success.html //设置状态码,302表示临时重定向,常用于页面跳转 resp.setStatus(302); //Location为固定写法,后面为要跳转的页面 resp.setHeader("Location","login_success.html"); }else{ pw.write("login failed"); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
关于resp.setHeader("Location","login_success.html"),可参见E:\6.1java就业班全套视频\10.HTTP&Servlet(9集)\me第2套 参考学习\code&资料\资料\Http1.1规范.pdf
- login_success.html
<a href="CountServlet">获取网站登录成功次数</a>
-
CountServlet
public class CountServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext servletContext = getServletContext(); Integer count = (Integer) servletContext.getAttribute("count"); PrintWriter writer = resp.getWriter(); writer.print(count); /* 此处用writer()方法时,弹出了下载对话框,可能是因为writer里有方法是阻塞的,换成print()方法即可*/ } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
3.HttpServletRequest
这个对象封装了客户端提交过来的所有数据。
3.1作用
3.1.1获取客户端请求头信息
Enumeration<String> headerNames = req.getHeaderNames();
while(headerNames.hasMoreElements()){
String name = headerNames.nextElement();
String value = req.getHeader(name);
System.out.println("name="+name+"\t"+"value="+value);
}
3.1.2获取客户端提交过来的数据
-
获取单个值
如:name=zhangsan&password=123
String username = req.getParameter("username");
String password = req.getParameter("password");
-
获取多个值
name=zhangsan&name=lisi&name=wangwu 一个key对应多个值
Map<String, String[]> parameterMap = req.getParameterMap();
Set<String> keySet = parameterMap.keySet();
Iterator<String> iterator = keySet.iterator();
while (iterator.hasNext()){
String key = iterator.next();
String[] strings = parameterMap.get(key);
for (String s:strings){
System.out.println(s);
}
}
3.1.3获取中文数据乱码问题
客户端提交数据给服务器端,如果数据中带有中文,可能出现乱码,可参照以下方法解决。
-
Get请求
1.代码转码
String username = req.getParameter("username"); String password = req.getParameter("password"); System.out.println(username+"\t"+password); //get请求过来的数据,在url地址栏上就已经经过编码了,所以我们取到的就是乱码,tomcat收到了这批数据,getParameter默认使用ISO-8859-1去解码 //先让文字回到ISO-8859-1对应的字节数组 , 然后再按utf-8组拼字符串 username = new String(username.getBytes("ISO-8859-1") , "UTF-8");
- 修改tomcat配置文件
直接在tomcat里面做配置,以后get请求过来的数据永远都是用UTF-8编码。可以在tomcat里面conf/server.xml的Connector标签上加上URIEncoding="utf-8"。
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/>
-
Post请求
req.setCharacterEncoding("UTF-8"); //设置请求体里的文字编码,要写在req.getParameter之前
4.HttpServletResponse
负责返回数据给客户端。
4.1作用
4.1.1输出数据到页面
//1.以字符流的方式写数据
resp.getWriter().write("hello response");
//2.以字节流的方式写数据
resp.getOutputStream().write("hello response".getBytes());
4.1.2响应中文数据乱码问题
- 以字符流输出
//1.指定输出到客户端时,这些文字使用UTF-8编码
resp.setCharacterEncoding("UTF-8");
//2.规定浏览器看这份数据时使用UTF-8编码
resp.setHeader("Content-Type","text/html;charset=UTF-8");//固定写法,参见Http 1.1规范
resp.getWriter().write("今天周一");
- 以字节流输出
//1.规定浏览器看这份数据时使用UTF-8编码
resp.setHeader("Content-Type", "text/html;charset=UTF-8");
//2. 指定输出的中文用的码表
resp.getOutputStream().write("今天周一".getBytes("UTF-8"));
不管是字节流还是字符流,直接一行代码搞定:
resp.setContentType("text/html;charset=UTF-8");
然后再写数据即可。
5.下载资源案例
5.1直接以超链接方式下载
直接以超链接的方式下载,不写任何代码。 也能够下载东西下来。原因是tomcat里面有一个默认的Servlet:DefaultServlet 。这个DefaultServlet专门用于处理放在tomcat服务器上的静态资源。
- download.html
<a href="file/aa.jpg">aa.jpg</a><br>
<a href="file/bb.txt">bb.txt</a><br>
<a href="file/cc.rar">cc.rar</a><br>
<a href="file/黑马.png">黑马.png</a><br>
5.2手动编码实现下载
- download.html
<a href="DownloadServlet?filename=aa.jpg">aa.jpg</a><br>
<a href="DownloadServlet?filename=bb.txt">bb.txt</a><br>
<a href="DownloadServlet?filename=cc.rar">cc.rar</a><br>
<a href="DownloadServlet?filename=黑马.png">黑马.png</a><br>
- DownloadServlet
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取要下载的文件名称
String filename = req.getParameter("filename");
System.out.println(filename);
//2.获取此文件在tomcat里的绝对路径
String realPath = getServletContext().getRealPath("file/" + filename);
//解决文件下载时文件名中的中文乱码问题
//获取客户端类型
String clientType = req.getHeader("User-Agent");
System.out.println(clientType);
if(clientType.contains("Firefox")){
//如果是火狐浏览器
byte[] bytes=filename.getBytes("UTF-8");
filename=new String(bytes,0,bytes.length,"ISO-8859-1");
}else{
//Edge,chrome等
filename = URLEncoder.encode(filename, "UTF-8");
}
//当用户点击链接时,让浏览器弹出下载框,而不是直接展示
resp.setHeader("Content-Disposition","attachment; filename="+filename);
//3.转换成输入流
InputStream is=new FileInputStream(realPath);
OutputStream os=resp.getOutputStream();
byte[] b=new byte[1024];
while(is.read(b)!=-1){
os.write(b,0,b.length);
}
os.close();
is.close();
}