Servlet获取参数
这里用一个小的表单网页举例
html代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>add</title>
</head>
<body>
<form action="add" method="post">
名称:<input type="text" name="name"><br/>
价格:<input type="text" name="price"><br/>
库存:<input type="text" name="count"><br/>
备注:<input type="text" name="remark"><br/>
<input type="submit" value="添加">
</form>
</body>
</html>
流程:
1.用户发送请求,action=add
2.项目中,web.xml中找到url-pattern = /add
3.web.xml找第十一行servlet-name = AddServlet
4.web.xml中找和servlet-mapping中servlet-name一致的servlet
5.web.xml找第八行的servlet-class ->AddServlet
6.用户发送的是post请求(method = post),因此tomcat会执行AddServlet中的doPost方法
Java代码:
注意:需要导入HttpServlet类,该类通过如下方法导入
通过找到对应项目,通过+号 Library 导入tomcat导入对应包
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author ZHR
* @version 1.0
**/
public class AddServlet extends HttpServlet {
@Override
//响应网页中的post请求
//HttpServletRequest req 将客户端的请求封装成Request
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取参数
//req.getParameter()根据网页中标签的name获取对应的value值
String name = req.getParameter("name");
String price = req.getParameter("price");
String count = req.getParameter("count");
String remark = req.getParameter("remark");
System.out.println(name);
System.out.println(price);
System.out.println(count);
System.out.println(remark);
}
}
web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>AddServlet</servlet-name>
<servlet-class>AddServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AddServlet</servlet-name>
<url-pattern>/add</url-pattern>
</servlet-mapping>
</web-app>
<!--
1.用户发送请求,action=add
2.项目中,web.xml中找到url-pattern = /add
3.找第十一行servlet-name = AddServlet
4.找和servlet-mapping中servlet-name一致的servlet
5.找第八行的servlet-class ->AddServlet
6.用户发送的是post请求(method = post),因此tomcat会执行AddServlet中的doPost方法
-->
输出结果:
常见问题:
设置编码
加入编码格式后的Java代码:
import com.sun.net.httpserver.HttpsServer;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author ZHR
* @version 1.0
**/
public class AddServlet extends HttpServlet {
@Override
//响应网页中的post请求
//HttpServletRequest req 将客户端的请求封装成Request
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//get方式目前不需要设置编码(基于tomcat8)
//post方式下,设置编码,防止中文乱码
//需要注意的是,设置编码的这一句代码需要在所有获取参数代码之前
req.setCharacterEncoding("UTF-8");
//获取参数
//req.getParameter()根据网页中标签的name获取对应的value值
String name = req.getParameter("name");
String price = req.getParameter("price");
String count = req.getParameter("count");
String remark = req.getParameter("remark");
System.out.println(name);
System.out.println(price);
System.out.println(count);
System.out.println(remark);
}
}
继承关系以及service方法
生命周期
2.默认情况下,第一次请求时,tomcat才会实例化,初始化。
优点:提高系统的启动速度
缺点:第一次请求时,耗时较长
因此需要设置Servlet的初始化时机
在web.xml中
3.Servlet容器是单例的,线程不安全的
单例:所有的请求都是同一个实例去响应
线程不安全:一个线程需要根据这个实例中的某个成员变量值去做逻辑判断,但是在中间的某个时机,另一个线程改变了这个成员变量的值,从而导致第一个线程路径发生变化
解决方案:
1.尽量不要在Servlet中定义成员变量
2.如果需要成员变量,不要修改成员变量的值或者不要用成员变量进行逻辑判断
HTTP协议
Session
一.为什么要引入会话跟踪技术
http 是无状态的
例如:第一次请求是加入购物车,第二次请求是结账。
如果服务器不能区分是否是同一用户的,则会发生混乱。
二.会话跟踪技术
1.简单图示:
2.基本原理:
即服务器根据客户端的 sessionId 来区分不同的客户端
3.常用API
代码演示:
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* @author ZHR
* @version 1.0
**/
public class demo01 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取session , 如果获取不到,则创建新的
HttpSession session = req.getSession();
System.out.println(session.getId());
//判断当前session是否是新的
System.out.println(session.isNew());
//获取session的非激活间隔时长,默认为1800s
System.out.println(session.getMaxInactiveInterval());
//设置session的非激活间隔时长
session.setMaxInactiveInterval(60);
System.out.println(session.getMaxInactiveInterval());
//获取对话创建时间
System.out.println(session.getCreationTime());
//获取对话上一次进入的时间
System.out.println(session.getLastAccessedTime());
}
}
三.session保存作用域
服务器端转发和客户端重定向
1.介绍和方法
2.示意图
(1) 服务器端转发
(2) 客户端重定向
Thymeleaf - 视图模板技术
一.配置步骤:
1) 添加thymeleaf的jar包
1.新建一个lib文件夹,将jar包都复制粘贴到该文件夹中
2.点击右键,点击Add as Library
3.点击OK
4.打开Project Structure,找到Modules,点击加号,点击Library,找到lib,完成添加
5.在Problems中找到Fix,点击 Add “lib” to the artifact
2) 新建一个Servlet类ViewBaseServlet
在src中添加ViewBaseServlet类
该类代码如下:
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ViewBaseServlet extends HttpServlet {
private TemplateEngine templateEngine;
@Override
public void init() throws ServletException {
// 1.获取ServletContext对象
ServletContext servletContext = this.getServletContext();
// 2.创建Thymeleaf解析器对象
ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);
// 3.给解析器对象设置参数
// ①HTML是默认模式,明确设置是为了代码更容易理解
templateResolver.setTemplateMode(TemplateMode.HTML);
// ②设置前缀
String viewPrefix = servletContext.getInitParameter("view-prefix");
templateResolver.setPrefix(viewPrefix);
// ③设置后缀
String viewSuffix = servletContext.getInitParameter("view-suffix");
templateResolver.setSuffix(viewSuffix);
// ④设置缓存过期时间(毫秒)
templateResolver.setCacheTTLMs(60000L);
// ⑤设置是否缓存
templateResolver.setCacheable(true);
// ⑥设置服务器端编码方式
templateResolver.setCharacterEncoding("utf-8");
// 4.创建模板引擎对象
templateEngine = new TemplateEngine();
// 5.给模板引擎对象设置模板解析器
templateEngine.setTemplateResolver(templateResolver);
}
protected void processTemplate(String templateName, HttpServletRequest req, HttpServletResponse resp) throws IOException {
// 1.设置响应体内容类型和字符集
resp.setContentType("text/html;charset=UTF-8");
// 2.创建WebContext对象
WebContext webContext = new WebContext(req, resp, getServletContext());
// 3.处理模板数据
templateEngine.process(templateName, webContext, resp.getWriter());
}
}
3) 在web.xml文件中添加配置
- 配置前缀 view-prefix
- 配置后缀 view-suffix
配置文件代码如下:
<!-- 配置上下文参数 -->
<context-param>
<param-name>view-prefix</param-name>
<param-value>/</param-value>
</context-param>
<context-param>
<param-name>view-suffix</param-name>
<param-value>.html</param-value>
</context-param>
根据逻辑视图名称 得到 物理视图名称
此处的视图名称是 index
那么thymeleaf会将这个 逻辑视图名称 对应到 物理视图 名称上去
逻辑视图名称 : index
物理视图名称 : view-prefix + 逻辑视图名称 + view-suffix
所以真实的视图名称是: / index .html
4) 使得我们的Servlet继承ViewBaseServlet
二.简单实例
通过自定义的List集合,将数据导入到表格中
使用thymeleaf的标签
th:if , th:unless , th:each , th:text
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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* @author ZHR
* @version 1.0
**/
//Servlet从3.0版本开始支持注解方式的注册
@WebServlet("/index")
public class IndexServlet extends ViewBaseServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
List<Fruit> list = new ArrayList<>(4);
for(int i = 0; i<4 ;i++){
Fruit fruit = new Fruit("苹果",10,10,100);
list.add(fruit);
}
//保存到作用域
HttpSession session = req.getSession();
session.setAttribute("list",list);
//此处视图是index
//那么thymeleaf会将这个 逻辑视图名称 对应到物理视图名称上去
//逻辑视图 index
//物理视图 view-prefix + 逻辑视图名称 + view-suffix
//所以真是视图是 /index.html
super.processTemplate("index",req,resp);
}
}
注意:
1.//Servlet从3.0版本开始支持注解方式的注册
@WebServlet("/index")
2.通过下列代码来处理模板
super.processTemplate("index",req,resp);
html代码:
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="test.css">
</head>
<body>
<div id="container">
<table id="table_fruit">
<tr >
<th >名称</th>
<th >单价</th>
<th>数量</th>
<th>操作</th>
</tr>
<tr th:if="${#lists.isEmpty(session.list)}">
<td colspan="4">库存为空</td>
</tr>
<!-- if是判断是否为条件真 unless是判断是否为条件假 each是叠代,从session.list中依次取出一个对象赋给fruit -->
<tr th:unless="${#lists.isEmpty(session.list)}" th:each="fruit : ${session.list}">
<td th:text="${fruit.getName()}">苹果</td>
<td th:text="${fruit.getNum()}">5</td>
<td th:text="${fruit.getPrice()}">20</td>
<td><img src="1.jpg" height="24px" /></td>
</tr>
</table>
</div>
</body>
</html>
css代码:
body{
margin: 0;
padding: 0;
}
div{
position: relative;
float: left;
}
#container{
width: 80%;
height: 100%;
border: 1px solid blue;
margin-left: 10%;
}
#table_fruit , #table_fruit th , #table_fruit tr , #table_fruit td {
border: 1px solid gray;
/* 边框合并 */
border-collapse: collapse;
/* 居中 */
text-align: center;
line-height: 28px;
}
#table_fruit{
width: 60%;
margin-top: 120px;
margin-left: 20%;
}
#table1{
/* 边框合并 */
border-collapse: collapse;
/* 居中 */
text-align: center;
line-height: 28px;
width: 40%;
margin-left: 30%;
}
.btn{
width: 90px;
height: 24px;
}
保存作用域
原始情况下,保存作用域我们可以认为有四个:
page(页面级别,现在几乎不用), request(一次请求响应范围) , session(一次会话范围) , application(整个应用程序范围)
1) request:一次请求响应范围
即通过客户端重定向不能访问(两次请求),而通过服务端转发可以访问(一次请求)
2) session:一次会话范围有效
只要是同一次对话,均可获得
通过下列代码获取Session
HttpSession session = req.getSession();
3) application: 一次应用程序范围有效
通过下列代码获取application
ServletContext application = req.getServletContext();
路径问题
注意绝对路径和base标签的用法