Servlet体系结构
我们将来开发B/S架构的web项目,都是针对HTTP协议,所以我们自定义Servlet,会继承HttpServlet
@WebServlet("/demo4") public class ServletDemo2 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("get......"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("post......"); } }
运行之后我们访问请求路径,从代码可以看出我们这个Servlet里面有两个方法,一个doGet()和doPost()方法,当我们直接输入访问路径,默认的是执行get方法
运行结果:
对于post请求来说,我们得写一个表单来请求当前Servlet资源
运行结果:
1)页面跳转
2)
HttpServlet中为什么要根据请求方式的不同,调用不同方法?
post和get请求参数的位置不一样,post请求参数的位置在请求体里面,get请求参数在请求行里面,当我们继承Servlet接口里面,需要根据请求的方式不同,来进行分别的处理,需要在service方法里面先获取请求方式
Servlet urlPattern配置
Servlet想要被访问,必须配置其访问路径(urlPattern)
1.一个Servlet,可以配置多个urlPattern
WebServlet(urlPatterns = {"/demo4","/demo5"}) public class ServletDemo4 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("demo4 get......"); } }
2.urlPattern配置规则
1)精确匹配
2)目录匹配
注意:当一个路径同时满足精确匹配和目录匹配的时候,精确匹配的优先级大于目录匹配*
3)扩展名匹配
4)任意匹配
/*的优先级高于/
/和/的区别
当我们项目中的Servlet配置了“/”会覆盖掉tomcat中的DefaultServlet,当其他的url-pattern都匹配不上时都会走这个Servlet
当我们的项目中配置了“/”,意味着匹配任意访问路径
配置任意访问路径会导致我们的任意访问资源无法使用,所以一般不要去配置它
优先级:精确路径>目录路径>扩展名路径>/>/
Request和Response介绍
Request:获取请求数据
Response:设置响应数据
示例代码:
@WebServlet("/demo2") public class ServletDemo2 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("get......"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //使用request对象,获取请求数据 String name = req.getParameter("name"); //使用response对象,设置响应数据 resp.setHeader("content-type","text/html;charaset=utf-8"); resp.getWriter().write("<h1>"+name+",欢迎您!</h1>"); System.out.println("post......"); } }
Request
Request继承体系
Request获取请求数据
请求数据分为3部分:
1.请求行:
2.请求体:
字符输入流:一般用于文本的情况下
字节输入流:一般用于文件和图片的情况下
示例代码:
第一步:创建表单
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/req1" method="post"> <input type="text" name="username"> <input type="password" name="password"> <input type="submit"> </form> </body> </html>
第二步:编写dopost请求
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取post 请求体:请求参数 //1.获取字符输入流 BufferedReader br = req.getReader(); //2.读取数据 String line = br.readLine(); System.out.println(line); }
运行结果:
3.请求头:
Request通用方式获取请求参数
GET请求方式和POST请求方式 区别主要在于获取请求参数的方式不一样,可以提供一种获取请求参数的方式,从而同一doGet和doPost方法
假设我们现在按原来的方法接收到了数据,但是数据时一条长长的字符串,我们还要拆分,这样是不是,有些麻烦
于是request就很贴心的为我们提供了一种方法
示例代码:
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //GET请求限制 System.out.println("get...."); //1.获取所有参数的Map集合 Map<String,String[]> map = req.getParameterMap(); for(String key:map.keySet()){ System.out.print(key+":"); //获取值 String[] values = map.get(key); for (String value:values){ System.out.print(value+" "); } System.out.println(); } //根据key获取参数值,数组 String[] hobbies = req.getParameterValues("hobby"); for(String hobby:hobbies){ System.out.println(hobby); } //根据key,获取单个参数值 String username = req.getParameter("username"); String password = req.getParameter("password"); System.out.println(username); System.out.println(password); }
同样的方法也能在doPost里面,我们完全可以在post请求里面填写一句this.doGet(req,resp);
请求参数中文乱码–post解决方案
当我们从表单post发送请求提交表单后的时候,request接收数据会乱码
(tomcat8及以后的版本,get方式不会乱码,post方式会乱码)
原因:post底层是通过getReader获取一个字符输入流,通过流的方式读取信息,该流的编码形式不是utf-8,但页面是utf-8的
解决方案:在请求里设置字符输入流的编码为UTF-8
请求参数中文乱码–get解决方案
get请求方式乱码不能用post乱码方式解决
乱码原因:
编码和解码不一致
拿一个代码举例
public class URLDemo { public static void main(String[] args) throws UnsupportedEncodingException { String username = "张三"; //1.URL编码 String encode = URLEncoder.encode(username, "utf-8"); System.out.println(encode); //URL解码 String decode = URLDecoder.decode(encode,"gbk"); System.out.println(decode); } }
运行结果:
*
由此可以看出因为编码和解码的不一致,导致我们运行结果不是我们想看到的
解决办法:
因为tomcat底层的方法是写死的,我们没有办法改变,但是我们可以想到它两个数据间的字节是一样的(二进制),我们可以把乱码数据转成二进制数据,再把二进制字节数据变成我们想要的数据*
public class URLDemo { public static void main(String[] args) throws UnsupportedEncodingException { String username = "张三"; //1.URL编码 String encode = URLEncoder.encode(username, "utf-8"); System.out.println(encode); //URL解码 String decode = URLDecoder.decode(encode,"ISO-8859-1"); System.out.println(decode); //3.转为字节数据 byte[] bytes = decode.getBytes("ISO-8859-1"); for(byte b:bytes){ System.out.print(b+" "); } System.out.println(); //4.将字节数组转为字符串 String s = new String(bytes, "utf-8"); System.out.println(s); } }
运行结果: