目录
一.HTTP请求数据与响应数据
1.Http请求数据有哪三部分?
请求行(有描述请求方式)
请求头(key:value形式)
请求体(Post请求使用)
2.GET与POST请求有哪些区别?
GET请求的请求参数在请求行中,POST请求参数在请求体中
GET请求参数大小有限制,POST无限制
3.Http响应数据有哪三部分?
响应行(有响应状态码,200表示响应成功,404表示找不到资源)
响应头(key:value形式)
响应体(存放响应数据)
4.在IDEA中使用Web服务器:Tomcat
Web服务器作用:封装http协议,能够在上面部署项目,对外提供服务。
1.使用maven创建的Web模板工程
2.右上角找到EditConfiguration选项可在IDEA中启动Tomcat(请确保本地已安装好tom猫)
3.在deployment加入项目后, 接下来就能启动项目了
二.HttpServlet快速入门
B/S架构中使用的HTTPServlet实现了Servlet接口,辨别了请求方式。
项目结构
pom文件中导入javax.servlet-api,commons-io(简化输入输出流以便传输图片)
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
1.HTTPServlet类的初步使用
1.要如何做才能让浏览器访问到这个HttpServlet资源? 在类上注解设置访问路径(也可以在web.xml配置) 启动项目后访问http://localhost/web_demo1_war/demo1即可访问到此资源 2.访问该路径后,用不同的方式(post与get)发送请求分别用到什么方法?)
@WebServlet("/demo1")
public class Demo1 extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("直接访问资源会使用get方法");
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("建立表单(在index.jsp中)发送请求会用post方法");
}
}
index.jsp
<html>
<body>
<form action="/web_demo1_war/demo1" method="post">
<input name="username"><input type="submit">
</form>
</body>
</html>
2.如何让多个访问路径都能够访问到同一个Servlet?
可在注解上设置多个路径(url),也可以设置特殊路径
@WebServlet(urlPatterns = {"/demo2/*","*.demo2"})
public class Demo2 extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("访问demo2目录下 或者 后缀名为demo2的所有资源");
}
}
3.处理请求
1.如何获取请求中信息,能获得哪些信息? 通过doGet方法中的req对象的方法获取请求信息 能偶获得请求行,请求头,请求传递的参数,请求的路径等信息 2.如何同时处理get请求与post请求? 3.如何获取请求体的完整数据?
@WebServlet("/req1")
public class Demo1 extends HttpServlet {
@Override
//访问req1?username=zhang
protected void doGet(HttpServletRequest req, HttpServletResponse resp){
System.out.print("获取请求方式:");
System.out.println(req.getMethod());
System.out.print("获取请求头,如浏览器版本信息(请求头不分大小写):");
System.out.println(req.getHeader("user-agent"));
System.out.print("获取请求传递的参数:");
System.out.println(req.getQueryString());
System.out.print("获取虚拟目录");
System.out.println(req.getContextPath());
System.out.print("获取资源标识符:");
System.out.println(req.getRequestURI());
System.out.print("获取统一资源定位符:");
System.out.println(req.getRequestURL().toString());
}
@Override
//访问html/req1.html填写表单,使用post发送请求
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
System.out.println("2.不同请求方式也能用相同方法处理数据,在doPost方法中也能掉用doGet方法处理相同内容的数据。");
this.doGet(req,resp);
System.out.println("3.请求体的信息可以用字节/字符输入流获取,不需要关闭输入流(跟随request消除)");
System.out.println(req.getReader().readLine());
}
}
req1.html
<!DOCTYPE html>
<html lang="en">
<body>
<form action="/web_demo1_war/req1" method="post">
<input name="username">
<input type="submit">
</form>
</body>
</html>
4.有哪些方式处理请求信息传递的参数?
@WebServlet("/req2")
public class Demo2 extends HttpServlet {
@Override
//req2?username=coya&password=123456&hobby=1&hobby=2
protected void doGet(HttpServletRequest req, HttpServletResponse resp){
System.out.println("1.根据name获取单个参数:");
System.out.println(req.getParameter("username"));
System.out.println("2.根据name获取多个参数:");
String[] hobbies = req.getParameterValues("hobby");
//在这里使用Arrays的方法转换成Stream流的话会出现空指针错误
for (String hobby : hobbies) {System.out.print(hobby+" ");}
System.out.println();
System.out.println("3.获取所有参数的Map<String,String[]>集合");
req.getParameterMap().forEach((s, strings) -> {
System.out.print(s+":");
StringJoiner sj = new StringJoiner(",");
for (String string : strings) {sj.add(string);}
System.out.println(sj);
});
}
//html/req2.html
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
this.doGet(req, resp);
}
}
req2.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/web_demo1_war/req2" method="post">
<input name="username">用户名<br>
<input name="password" type="password">密码<br>
<input type="checkbox" name="hobby" value="1">爵士
<input type="checkbox" name="hobby" value="2">布鲁斯<br>
<input type="submit">
</form>
</body>
</html>
5.解决post请求乱码:给请求设置编码
@WebServlet("/req3")
//html/req3.html输入张三
public class Demo3 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
req.setCharacterEncoding("UTF-8");
System.out.println(req.getParameter("username"));
}
}
req3.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/web_demo1_war/req3" method="post">
<input name="username">用户名<br>
<input type="submit">
</form>
</body>
</html>
6.请求转发有哪些特点?
1.请求转发可携带新数据传递到另一个服务器内部资源 2.浏览器地址栏不变 3.可在多个资源中共享请求数据
@WebServlet("/req4")
public class Demo4 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
req.setAttribute("msg","请求转发的信息");
req.getRequestDispatcher("/req5").forward(req,resp);
}
}
@WebServlet("/req5")
public class Demo5 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
System.out.println(req.getAttribute("msg"));
}
}
7.重定向相比于请求转发的不同点
1.可定向到外部资源(百度), 2.浏览器地址栏变化 3.不能在多个资源共享请求数据 4.对于重定向到Servlet的路径需要加项目名称(虚拟目录)在请求转发中不需要加项目名称
@WebServlet("/resp1")
public class Demo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
System.out.println("重定向,可先设置状态码302,再设置响应头Header为新地址,这里使用简化写法");
resp.sendRedirect(req.getContextPath()+"/demo1");
}
}
重定向,可先设置状态码302,再设置响应头Header为新地址,这里使用简化写法
8.如何响应字符数据到浏览器?如何解决数据响应乱码的问题?
@WebServlet("/resp2")
public class Demo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("解决响应数据乱码可设置文本格式与编码格式");
resp.setContentType("text/html;charset=UTF-8");
System.out.println("使用字符流响应字符数据");
resp.getWriter().write("<h1>字符数据</h1>");
}
}
9.如何响应字节数据(传图片)?
@WebServlet("/resp3")
public class Demo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("响应字节数据,需要用到字节输出流");
FileInputStream fis = new FileInputStream("C:\\Users\\33428\\Pictures\\壁纸\\2.png");
IOUtils.copy(fis,resp.getOutputStream());
fis.close();
}
}
响应字节数据,需要用到字节输出流
三.登录注册案例
1.写静态HTML资料到web-app目录下
2.准备创建数据库表User表,只有id,用户名和密码列
3.准备好JDBC+Mybatis+servlet的依赖
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.32</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.5</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency>
4.创建mybatis-config.xml,mapper.xml,pojo类
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <typeAliases> <package name="org.example.pojo"/> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <package name="org.example.mapper"/> </mappers> </configuration>
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="org.example.mapper.UserMapper"> </mapper>
public class User { private Integer id; private String username; private String password; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public User(String username, String password) { this.username = username; this.password = password; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + '}'; } }
5.编写接口方法
public interface UserMapper { @Select("select * from user where username=#{username} and password=#{password} ;") User select(User user); @Select("select * from user where username=#{username}") User selectByUsername(String username); @Insert("insert into user values(null,#{username},#{password})") void add(User user); }
6.在html文件表单里面加上虚拟目录,提交方式为post
7.创建登录与注册servlet,在servlet完成接收请求与响应数据,创建工具类快速openSession
@WebServlet("/loginServlet") public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { req.setCharacterEncoding("UTF-8"); User reqUser = new User(req.getParameter("username"),req.getParameter("password")); System.out.println("输入的用户信息为:"+reqUser); SqlSession sqlSession=SqlSessionFactoryUtil.getssf().openSession(true); User user = sqlSession.getMapper(UserMapper.class).select(reqUser); System.out.println("查询到的用户为:"+user); resp.setContentType("text/html;charset=utf-8"); PrintWriter writer = resp.getWriter(); if (user!=null)writer.write("登录成功"); else writer.write("登录失败"); sqlSession.close(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } }
@WebServlet("/registerServlet") public class RegisterServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { req.setCharacterEncoding("UTF-8"); User user = new User(req.getParameter("username"), req.getParameter("password")); System.out.println("输入的用户信息为:"+user); SqlSession sqlSession= SqlSessionFactoryUtil.getssf().openSession(true); UserMapper userMapper =sqlSession.getMapper(UserMapper.class); resp.setContentType("text/html;charset=utf-8"); PrintWriter writer = resp.getWriter(); if (userMapper.selectByUsername(user.getUsername()) == null) { writer.write("注册成功"); userMapper.add(user); } else writer.write("注册失败"); sqlSession.close(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req,resp); } }
public class SqlSessionFactoryUtil { static SqlSessionFactory sqlSessionFactory; static { try { sqlSessionFactory = new SqlSessionFactoryBuilder() .build(Resources.getResourceAsStream("mybatis-config.xml")); }catch (Exception e){ e.printStackTrace(); } } public static SqlSessionFactory getssf(){ return sqlSessionFactory; } }
案例有严重的缺陷(如输入为空也可注册),正常操作可注册登录
案例前端资源可前往黑马官方领取(b站javaweb2021年的课程)