Servlet
-
Servlet 是 Java提供的一门动态web资源开发技术
-
Servlet 是 JavaEE 规范之一,其实就是一个接口,将来我们需要定义Servlet类实现Servlet接口,并由web服务器运行Servlet
快速入门
-
创建 web 项目,导入 Servlet 依赖坐标
<!--Servlet--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency>
-
创建:定义一个类,实现 Servlet 接口,并重写接口中所有方法,并在service方法中输入一句话
-
配置:在类上使用@WebServlet 注解,配置该 Servlet的访问路径
-
访问:启动Tomcat,浏览输入URL 访问该Servlet
package com.wen;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
@WebServlet("/demo1")
public class ServletDemo1 implements Servlet {
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("Servlet hello world...");
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {}
@Override
public ServletConfig getServletConfig() {return null;}
@Override
public String getServletInfo() {return null;}
@Override
public void destroy() {}
}
Servlet体系
Servlet urlPattern配置
-
一个Servlet,可以配置多个 urlPattern
@WebServlet(urlPattern = {"/demo1", "/demo2"})
-
urlPattern 配置规则
XML 配置方式编写 Servlet
-
Servlet 从3.0版本后开启支持使用注解配置,3.0版本前只支持 XML 配置文件的配置方式
-
步骤:
-
编写 Servlet 类
-
在 web.xml 中配置该 Servlet
<!--Servlet 全类名--> <servlet> <servlet-name>demo4</servlet-name> <servlet-class>com.wen.ServletDemo4</servlet-class> </servlet> <!--Servlet 访问路径--> <servlet-mapping> <servlet-name>demo4</servlet-name> <url-pattern>/demo4</url-pattern> </servlet-mapping>
-
Request
-
请求数据分为3部分:
-
请求行:
// 请求行:GET/request-demo/req1?username=zhangsan HTTP/1.1 String getMethod():获取请求方式:GET String getContextPath():获取虚拟目录(项目访问路径):/request-demo StringBuffer getRequestURL():获取URL(统一资源定位符): http://localhost:8080/request-demo/req1 String getRequestURI():获取URL(统一资源标识符:/request-demo/req1 String getQueryString():获取请求参数(GET方式):username=zhangsan&password=123
-
请求头:
// 请求头:User-Agent:Mozilla/5.0 Chrome/91.0.4472.106 String getHeader(String name):根据请求头名称,获取值
-
请求体:
// 请求体:username=lishi&password=123 ServletInputStream getInputStream():获取字节输入流 BufferedReader getReader():获取字符输入流
-
Request 通用方式获取请求参数
Map<String,String[]> getParameterMap():获取所有参数Map集合
String[] getParameterValues(String name):根据名称获取参数值(数组)
String getParameter(String name):根据名称获取参数值(单个值)
Map<String, String[]> map = request.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();
}
请求参数中文乱码解决
// POST 获取参数的方式,getReader()
// POST解决方法:设置输入流编码
request.setCharacterEncoding("UTF-8"); // 设置字符输入流的编码
// GET 获取参数的方式,getQueryString()
// 乱码原因:tomcat进行URL解码,默认的字符集ISO-8859-1
// 通用方法(GET/POST):先编译,再解码
String username = request.getParameter("username");
username = new String(username.getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8);
Tomcat 8.0 之后,已将GET请求乱码问题解决,设置默认的解码方式为UTF-8
URL编码实现
// 编码
URLEncoder.encode(str,"UTF-8");
// 解码
URLDecoder.decode(s,"ISO-8859-1");
请求转发
-
请求转发(forward):一种在服务器内部的资源跳转
-
实现方式
request.getRequestDispatcher("资源B路径").forward(request,response);
-
请求转发资源间共享数据:使用Request对象
void setAttribute(String name,Object o):存储数据到 request 域中 Object getAttribute(String name):根据 Key,获取值 void removeAttribute(String name):根据 key,删除该键值对
-
特点:
-
浏览器地址栏路径不发生变化
-
只能转发到当前服务器的内部资源
-
一次请求,可以在转发的资源间使用request共享数据
-
Response
-
响应数据分为3部分:
-
响应行:
// 请求行:HTTP/1.1 200 OK void setStatus(int sc):设置响应状态码
-
响应头:
// 请求头:Content-Type:text/html void setHeader(String name,String value):设置响应头键值对
-
响应体:
// 请求体:<html><head></head><body></body></html> PrintWriter getWriter():获取字符输出流 ServletOutputStream getOutputStream():获取字节输出流
-
Response 完成重定向
-
重定向(Redirect):一种资源跳转方式
-
实现方式:
resp.setStatus(302); resp.setHeader("Location","资源B的虚拟路径"); // 简化方式完成重定向 resp.sendRedirect("资源B的虚拟路径");
-
特点:
-
浏览器地址栏路径发生变化
-
可以重定向到任意位置的资源(服务器内部、外部均可)
-
两次请求,不能在多个资源使用request共享数据
-
路径问题
-
明确路径谁使用
-
浏览器使用:需要加虚拟目录(项目访问路径)
-
服务端使用:不需要加虚拟目录
-
Response 响应字符数据
// 解析html,并解决中文乱码问题
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
// response.setHeader("content-type","text/html"); // 可以解析html,但有中文乱码问题
writer.write("<h1>中文</h1>");
// 流不需要关闭,随着响应结束,response 对象销毁,由服务器关闭
// 注意中文乱码问题
Response 响应字节数据
// 读取文件
FileInputStream fis = new FileInputStream("E:\\File\\1.png");
// 获取response 字节输出流
ServletOutputStream os = response.getOutputStream();
IOUtils.copy(fis,os);
<!--复制工具类-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
HttpServlet原理伪实现
public class MyHttpServlet2 implements Servlet {
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
// 1. 获取请求方式
String method = request.getMethod();
// 2. 判断
if("GET".equals(method)){
// get方式的处理逻辑
doGet(req,res);
}else if("POST".equals(method)){
// POST方式的处理逻辑
doPost(req,res);
}
}
}
public class ServletDemo2 extends MyHttpServlet2 {
@Override
protected void doGet(ServletRequest req, ServletResponse res) {
System.out.println("get...");
}
@Override
protected void doPost(ServletRequest req, ServletResponse res) {
System.out.println("post...");
}
}
注册
package com.wen.web;
import com.wen.mapper.UserMapper;
import com.wen.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
@WebServlet(name = "RegisterServlet", value = "/registerServlet")
public class RegisterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 接收数据
String username = request.getParameter("username");
String password = request.getParameter("password");
User user = new User();
user.setUsername(username);
user.setPassword(password);
// 调用MyBatis完成查询
// 获取 SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取SqlSession对象,用它来执行SQL
SqlSession sqlSession = sqlSessionFactory.openSession();
// 获取Mapper
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// UserMapper 接口的代理对象, 调用方法
// 判断用户名是否存在
User user01 = userMapper.selectByUsername(username);
if (user01 == null) {
userMapper.add(user);
// 提交事务
sqlSession.commit();
} else {
// 获取字符输出流,并设置content type
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("用户名存在");
}
// 释放资源
sqlSession.close();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}