20211017
前后端传值案例
前端的值如何传到后端
方式1:前端form表单提交
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<!-- action 传递到后端的url -->
<!--/给前端解析:代表 协议名+主机名+端口号 == http://localhost:8083/-->
<!-- method 属性代表该表单传输的方式是get或者post -->
<form action="./login.do" method="get">
<!-- 需要传到后端的文本值,通常用input输入框+name属性 -->
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<!-- 在表单内 一定要有一个type=submit 的按钮 -->
<button type="submit">登录</button>
</form>
</body>
</html>
LoginServlet.java
package com.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
//地址全称为:http://localhost:8080/demo20211015/login.do
@WebServlet("/login.do")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决响应中文乱码
resp.setContentType("text/html;charset=utf-8");
//获取前端传来的值
//req.getParameter通过请求的name获取到请求的值
//跟前端input name一致
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println("用户名为:" + username);
System.out.println("密码为:" + password);
if ("admin".equals(username) && "123".equals(password)) {
//告诉用户登录成功
//获取响应的字符输出流
resp.getWriter().write("<h1>" + username + "登录成功</h1>");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
regist.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册</title>
</head>
<body>
<form action="./regist.do" method="get">
用户名<input type="text" name="username"><br>
密码<input type="password" name="password"><br>
重复密码<input type="password" name="repassword"><br>
性别(单选框)<input type="radio" name="gender" value="male">男<input type="radio" name="gender" value="female">女<br>
兴趣爱好(多选框)<input type="checkbox" name="hobby" value="java">java<input type="checkbox" name="hobby" value="python">python<input
type="checkbox" name="hobby" value="php">php<br>
省份(下拉框)<select name="province">
<option value="beijing">北京</option>
<option>上海</option>
<option>广东</option>
<option>福建</option>
</select><br>
自我介绍(多行文本框)<textarea name="introduction"></textarea>
<button type="submit">注册</button>
<button type="reset">重置</button>
</form>
</body>
</html>
RegistServlet.java
package com.servlet;
import com.bean.User;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/regist.do")
public class RegistServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决响应中文乱码
resp.setContentType("text/html;charset=utf-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
String gender = req.getParameter("gender");
//对于多选框等 使用 getParameterValues
String[] hobby = req.getParameterValues("hobby");
String province = req.getParameter("province");
String introduction = req.getParameter("introduction");
User user = new User(username, password, gender, hobby, province, introduction);
System.out.println(user);
//获取响应的字符输出流
resp.getWriter().write("<h1>注册成功</h1>");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
HttpServletRequest
请求
Tomcat将前端所有请求信息(包括请求头和请求体),封装成HttpServletRequest对象。我们在Java端,是处在服务器的角度去编程。解决怎么从前端拿到值。有一种情况特殊,通过HttpServletRequest 给前端传值(请求转发)。
常用API
package com.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/demo03.do")
public class Demo03Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
///demo20211015/demo03.do
//获取请求的URI 资源路径
System.out.println(req.getRequestURI());
//http://localhost:8083/demo20211015/demo03.do
//获取请求的URL 资源全路径
System.out.println(req.getRequestURL());
//0:0:0:0:0:0:0:1
//获取客户端的IP地址
System.out.println(req.getRemoteHost());
//zh-CN,zh;q=0.9
//获取请求头信息
System.out.println(req.getHeader("Accept-Language"));
//GET
//获取请求方式
System.out.println(req.getMethod());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//无论get方式还是post方式 都执行同一段逻辑
doGet(req, resp);
}
}
请求转发
用的最多的:在Servlet给域属性赋值,在JSP对域属性取值。
服务器收到请求后,从一个资源跳转到另外资源的操作。本质上是服务器内部跳转。
特点:1.地址栏不会变化
2.只能跳转服务器内部资源
3.可以带信息跳转
4.一次请求
package com.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/demo04.do")
public class Demo04Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//请求转发:在多个Servlet之间进行转发
//转发的对象是:同一个request对象和同一个response对象
//可以实现请求参数的共享和request域属性的共享
String username = req.getParameter("username");
//域属性设置
//域:像HashMap一样 以键值对存储数据的对象
//域的 key 都是String;value 都是Object
//对域 进行属性的赋值
// req.setAttribute();
//对域 进行属性的取值
// req.getAttribute()
req.setAttribute("name1", "value1");
req.getRequestDispatcher("/demo05.do").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
package com.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/demo05.do")
public class Demo05Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String name1 = (String) req.getAttribute("name1");
System.out.println(name1);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
请求转发在实际案例中的应用
/**
* 处理分页功能
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void page(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
IOException {
//1 获取请求的参数 pageNo 和 pageSize
int pageNo = WebUtils.parseInt(req.getParameter("pageNo"), 1);
int pageSize = WebUtils.parseInt(req.getParameter("pageSize"), Page.DEFAULT_PAGE_SIZE);
//2 调用GoodsService.page(pageNo,pageSize):Page 对象
Page<Product> page = productService.page(pageNo, pageSize);
//3 保存Page 对象到Request 域中
req.setAttribute("page", page);
//4 请求转发到/admin/product_list.jsp 页面
req.getRequestDispatcher("/admin/product_list.jsp").forward(req, resp);
}
<%
// List<Product> products = (List<Product>) request.getAttribute("products");
Page<Product> productsPage = (Page<Product>) request.getAttribute("page");
%>
<%
for (int i = 0; i < productsPage.getItems().size(); i++) {
Product product = productsPage.getItems().get(i);
%>
<tr>
<td><%= product.getId()%>
</td>
<td><%= product.getName()%>
</td>
<td><%= product.getPrice()%>
</td>
<td><%= product.getCategory()%>
</td>
<td><%= product.getpNum()%>
</td>
<td>
<img src=" <%=DataConsts.IMG_UPLOAD_PATH + product.getImgUrl()%> "
style="width: 150px; height: 150px;" alt="..."
class="img-thumbnail">
</td>
<td><%= product.getDescription()%>
</td>
<td>
<button class="btn btn-info" data-toggle="modal" data-target="#productModal">修改</button>
<button class="btn btn-danger">删除</button>
</td>
</tr>
<%
}
%>
域对象
servlet中,域对象有3种。
1.HttpServletRequest:一次请求内有效,所以要有请求转发,在多个Servlet中共享一个Request对象。
2.HttpSession:一次会话有效
3.ServletContext:整个工程运行的过程中都有效。
域对象:和HashMap结构一致,但是以String作为键,以Object作为值。
关键方法:
public void setAttribute(String name, Object o);
public Object getAttribute(String name);
区别:作用域的不同
HttpServletResponse
响应
Tomcat将所有需要返回给前端响应的信息,封装成HttpServletResponse对象。解决怎么给前端返回值。
response返回给前端信息
1.字节流
获取响应的字节输出流
resp.getOutputStream()
可以用作文件下载。
两个方法只能同时使用一个
//500 getWriter() has already been called for this response
PrintWriter writer = resp.getWriter();
ServletOutputStream outputStream = resp.getOutputStream();
response实现文件下载
package com.servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@WebServlet("/download.do")
public class DownloadFileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//getWriter() has already been called for this response
// PrintWriter writer = resp.getWriter();
ServletOutputStream outputStream = resp.getOutputStream();
//用File文件类 指向作为下载的文件
File file = new File("D:\\imgUpload\\1.jpg");
//通过设置响应头信息,告诉浏览器 接下来的数据 是一个需要被下载的文件
resp.setHeader("content-disposition", "attachment;filename=" + "1.jpg");
//获取文件的输入流 对源文件进行读取
FileInputStream fis = new FileInputStream(file);
//定义一个缓冲字节数组 用于字节数据的搬运
byte[] buffer = new byte[1024];
int length = 0;
while ((length = fis.read(buffer)) != -1) {
outputStream.write(buffer);
outputStream.flush();
}
fis.close();
outputStream.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件下载</title>
</head>
<body>
<a href="./download.do">点击这里进行文件下载</a>
</body>
</html>
2.字符流
resp.getWriter()
//解决响应中文乱码
resp.setContentType("text/html;charset=utf-8");
重定向
客户端向服务器发送请求,然后服务器给客户端一串地址,让客户端自行访问。原有的网页、网址已经停止服务。
1.两次请求
2.可以跳转到服务器外部的网址
3.无法带信息跳转
登录成功跳转首页,登录失败跳转回登录页面
if ("admin".equals(username) && "123".equals(password)) {
//告诉用户登录成功
//获取响应的字符输出流
// resp.getWriter().write("<h1>" + username + "登录成功</h1>");
//请求重定向
//http://localhost:8083/ 这里的斜杠是唯一一个后端特殊的斜杠
//和前端的/意思相同
//因为这个字符串 最终是给浏览器进行解析跳转的
resp.sendRedirect("./index.html");
} else {
resp.sendRedirect("./login.html");
}
ServletConfig
Servlet配置信息类
web.xml
<!-- 给Tomcat配置Servlet程序-->
<servlet>
<servlet-name>Demo01Servlet</servlet-name>
<!-- 记录这个Servlet在后端的全限定类名 -->
<servlet-class>com.servlet.Demo01Servlet</servlet-class>
<init-param>
<param-name>datasource</param-name>
<param-value>mysql:jdbc://localhost:3306/bookstote</param-value>
</init-param>
</servlet>
<servlet-mapping>
<!-- 通过相同的servlet-name,将<servlet-class> 和 <url-pattern> 联系在一起 -->
<servlet-name>Demo01Servlet</servlet-name>
<!-- 配置前端浏览器的访问地址 -->
<!-- /给服务器解析的时候,表示:协议名+主机名+端口号+项目名称 -->
<!-- / === http://localhost:8083/demo20211015/ -->
<url-pattern>/demo01.do</url-pattern>
</servlet-mapping>
/**
* 对Servlet初始化时 执行的方法
*
* @param config
* @throws ServletException
*/
@Override
public void init(ServletConfig config) throws ServletException {
//1.获取在web.xml中配置的别名 servlet-name
System.out.println(config.getServletName());
//2.获取在web.xml中配置的 init-param
System.out.println(config.getInitParameter("datasource"));
//3.获取到域对象之一 ServletContext
System.out.println(config.getServletContext());
System.out.println("Demo01Servlet 被初始化");
}
ServletContext
表示Servlet上下文对象。一个web工程只有一个ServletContext对象。是域对象。当工程启动时,创建。工程停止销毁。
作用:1.作为域对象,进行数据的存取
2.获取当前工程路径
3.获取工程在硬盘上的部署绝对路径
package com.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/demo06.do")
public class Demo06Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取到ServletContext对象
ServletContext servletContext = this.getServletContext();
//2.获取当前的工程路径
// /demo20211015
System.out.println(servletContext.getContextPath());
//3.获取工程部署在硬盘上的绝对路径
System.out.println("整个工程的绝对路径" + servletContext.getRealPath("/"));
System.out.println("hello.html的绝对路径" + servletContext.getRealPath("/hello.html"));
//4.获取web.xml的context-param
String bookName = servletContext.getInitParameter("bookName");
System.out.println(bookName);
//5.作为域对象使用
servletContext.setAttribute("book", "钢铁是怎样炼成的");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
package com.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/demo07.do")
public class Demo07Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//域对象取值
ServletContext servletContext = this.getServletContext();
String book = (String) servletContext.getAttribute("book");
System.out.println("书名:" + book);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
<context-param>
<param-name>bookName</param-name>
<param-value>book01</param-value>
</context-param>
作业
在web/client中创建register.html,后端创建LoginServlet和RegisterServlet,实现登录和注册功能。并且使用重定向跳转到对应页面。