一、Servlet是什么?
运行在服务端的Java小程序,是动态资源规范,代码层面上Sevlet就是一个接口。
二、怎么开发一个Servlet(步骤)?
- 自定义一个类,要继承HttpServlet类
- 重写service方法,该方法主要就是用于处理用户请求的服务方法
- HttpServletRequest 代表请求对象,是有请求报文经过tomcat转换而来的,通过该对象可以获取请求中的信息
- HttpServletResponse 代表响应对象,该对象会被tomcat转换为响应的报文,通过该对象可以设置响应中的信息
- Servlet对象的生命周期(创建,初始化,处理服务,销毁)是由tomcat管理的,无需我们自己new
- HttpServletRequest HttpServletResponse 两个对象也是有tomcat负责转换,在调用service方法时传入给我们用的
代码
public class UserServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求中的参数
String username = req.getParameter("username");
if("atguigu".equals(username)){
//通过响应对象响应信息
resp.getWriter().write("NO");
}else{
resp.getWriter().write("YES");
}
}
}
为Servlet配置请求的映射路径
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0">
<!--
servlet-name 自定义的name值,要求:同一对标签的name要相同
url-pattern 定义页面的请求地址,注意:请求地址必须使用/开头这里的请求地址是不包含:application context
-->
<servlet>
<!--给UserServlet起一个别名-->
<servlet-name>userServlet</servlet-name>
<servlet-class>com.atguigu.servlet.UserServlet</servlet-class>
</servlet>
<servlet-mapping>
<!--关联别名和映射路径-->
<servlet-name>userServlet</servlet-name>
<!--可以为一个Servlet匹配多个不同的映射路径,但是不同的Servlet不能使用相同的url-pattern-->
<url-pattern>/userServlet</url-pattern>
</servlet-mapping>
</web-app>
三、生命周期
- 测试生命周期时,需要重写init(),service(),destroy()方法
- servlet生命周期:
第一次请求:
- 匹配请求地址,找到对应的处理类,判断该类的对象是否存在,不存在的情况下,创建servlet对象。如果存在则直接调用。调取init()进行初始化,仅执行一次
- 如果重写了父类的service(),则此时调取service()处理用户名
- 没有重写service(),重写了doget()和dopost():父类的service()会根据请求的方法判断是get还是post,如果get,则调取doget(),如果post,调取doPost()
第二次及以后的请求:
- 直接调取service()方法处理请求
- 销毁:当服务器关闭时,调取destroy(),销毁servlet对象
注意:实际编写代码只需要重写service()
四、初始化参数
init(SevletConfig config){},需求:在程序中加载一个spring.xml配置文件
局部初始化参数使用:
<servlet>
<servlet-name>aa</servlet-name>
<servlet-class>
com.atguigu.web.Test1Servlet
</servlet-class>
<!-- parameter 参数 param-name 自定义的参数名 param-value 参数值 -->
<init-param>
<param-name>configname</param-name>
<param-value>springmvc.xml</param-value>
</init-param>
</servlet>
@Override
public void init(ServletConfig config) throws ServletException
String configname = config.getInitParameter("configname");
System.out.println("configname="+configname);
}
全局初始化参数使用:
<context-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</context-param>
<servlet></servlet>
System.out.println("------------获取全局初始化参数---------------");
/* ServletContext servletContext = config.getServletContext();
String encoding = servletContext.getInitParameter("encoding");*/
String encoding = config.getServletContext().getInitParameter("encoding");
System.out.println("encoding="+encoding);
load-on-startup标签
<servlet>
<load-on-startup></load-on-startup>
</servlet>
作用:
- (1) 可以让指定的servlet在服务器启动时就创建对象并调取init()
- (2) 取值为正整数,数值越小,优先级越高
五、页面发送请求的方式:
<a href="/application context/自定义的请求"> get
<form action="/application context/自定义的请求"> get/post</form>
window.location="/application context/自定义的请求" get
通过注解使用
@WebServlet(
name = "userServlet",
//value = "/user",
urlPatterns = {"/userServlet1","/userServlet2","/userServlet"},
initParams = {@WebInitParam(name = "encoding",value = "UTF-8")},
loadOnStartup = 6
)
public class UserServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String encoding = getServletConfig().getInitParameter("encoding");
System.out.println(encoding);
// 获取请求中的参数
String username = req.getParameter("username");
if("atguigu".equals(username)){
//通过响应对象响应信息
resp.getWriter().write("NO");
}else{
resp.getWriter().write("YES");
}
}
}
上面的代码主要用于替换Servlet配置,注解和xml这两种方式只能二选一,但是要注意我们不能删除web.xml文件
六、HttpServletRequest
- (1) 请求行
获取请求方式: request.getMethod()
获取请求地址: request,getRequestURI() request,getRequestURL();
- (2)请求头: request.getHeader(String key)
请求头是什么?类似于下面这种:
- (3) 请求体:
String request.getParameter(String key)
Map<String,String[]> request.getParameterMap();
String [] request.getParameterValues();
下面是一个例子来展示他们的用法:
<!--
a标签和location发送数据的语法:
href="/application Context/自定义的请求?key=value&key2=value2&key3=value2"
第一个参数使用?拼接,第二个及以后的参数使用&拼接
location="/application Context/自定义的请求?key=value&key2=value2&key3=value2"
-->
<a href="/testreq?uname=张三&uage=18&usex=男">测试HttpServletRequest</a>
<form action="/testreq" method="post">
用户名:<input type="text" name="uname"><br>
年龄:<input type="text" name="uage"><br>
性别:<input type="radio" name="usex" value="boy"> 男
<input type="radio" name="usex" value="gril"> 女<br>
爱好:<input type="checkbox" name="like" value="吃饭">吃饭
<input type="checkbox" name="like" value="睡觉">睡觉
<input type="checkbox" name="like" value="打豆豆">打豆豆<br>
<input type="submit">
</form>
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
@WebServlet("/testreq")
public class RequestServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("requestServlet被执行");
System.out.println("--------请求行--------------");
System.out.println("请求方式:"+req.getMethod());
System.out.println("请求地址:"+req.getRequestURI());// /testreq
System.out.println("请求地址2:"+req.getRequestURL()); // http://localhost/testreq
System.out.println("-------------请求头----------------");
String connection = req.getHeader("Connection");
String host = req.getHeader("Host");
String referer = req.getHeader("Referer");
System.out.println(connection+","+host+","+referer);
System.out.println("-----------请求体(发送的数据)----------");
String uname = req.getParameter("uname");
String usex = req.getParameter("usex");
String uage = req.getParameter("uage");
int age=Integer.parseInt(uage);
System.out.println(uname+","+usex+","+age);
//将发送的数据封装到Map集合中
Map<String, String[]> parameterMap = req.getParameterMap();
Set<String> keySet = parameterMap.keySet();//获取所有的key
for (String key : keySet) {
String[] values = parameterMap.get(key);
System.out.println(key+","+ Arrays.toString(values));
}
//获取复选框中的一组数据
String[] likes = req.getParameterValues("like");
System.out.println(Arrays.toString(likes));
}
}
转发:
req.getRequestDispatcher("/testrequest2").forward(req,resp);
七、HttpServletResponse
响应一个字符串给客户端:
//响应一个字符串给客户端
//使用场景:1.返回JSON字符串给客户端 2.返回一段js代码给客户端
//建议:输出语句最好只执行一次
resp.setContentType("text/html;charset=utf-8");//解决响应字符串乱码的问题
resp.getWriter().write("{name:'zhangsan',message:'这是我返回给客户端的字符串'}");
resp.getWriter().write("<script>alert('登录成功');</script>");
响应一个页面或一个新的请求给客户端:
//响应一个页面给客户端 resp.sendRedirect("跳转的页面路径");
//resp.sendRedirect("/result/success.html");
resp.sendRedirect("/testrequest2");
转发和重定向最主要的一个区别是: 转发地址只改变一次,重定向地址会改变两次,所以它们的地址有所差异
八、web乱码问题处理
//1.接收的数据乱码
request.setCharacterEncoding("utf-8");//必须加载service()方法的第一行
//2.响应给客户端字符串时出现乱码
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("");