前言
Java Web中有3大组件
- Servlet
- Filter(过滤器)
- Listener(监听器)
3大组件的功能如下
- Filter功能: 类似于Django中的中间件,可以在Servlet之前拦截请求和响应。
- Servlet功能: 执行后台业务逻辑,处理客户端请求和响应。
- Listener功能:用于监视Request、Session和ServletContext这三大域对象的创建、销毁以及域对象中存储对象的增加和减少事件,一旦域对象发生不同事件,即执行相应的动作。
一、Filter(过滤器)
Filter类似于Django中的中间件,可以在Servlet之前拦截请求和响应,检查请求和响应是否合法?
1.
package com.zhanggen.filter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.*; import java.io.IOException; import java.util.Date; public class LogFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("进入目标资源之前" + new Date().toLocaleString()); HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; String loginURI = "/day07-filter-json/loginServlet"; String secretToken = "s8170hhdk101hhdu"; String requestURI = request.getRequestURI(); //如果请求路径不是登录页面 if (!loginURI.equals(requestURI)) { String userToken = (String) request.getSession().getAttribute("token"); if (userToken != null && userToken.equals(secretToken)) { //放行请求 filterChain.doFilter(servletRequest, servletResponse); } } else { //跳转到登录页面 response.sendRedirect("/day07-filter-json/login.html"); } System.out.println("离开目标资源之后" + new Date().toLocaleString()); } @Override public void destroy() { } }
3.1.配置文件配置
<?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_3_1.xsd" version="3.1"> <!--过滤器配置--> <filter> <filter-name>logFilter</filter-name> <filter-class>com.zhanggen.filter.LogFilter</filter-class> </filter> <filter-mapping> <filter-name>logFilter</filter-name> <!-- 拦截请求的规则--> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <!--设置默认首页--> <welcome-file>login.html</welcome-file> </welcome-file-list> </web-app>
3.2.注解配置
@WebFilter("/*") public class LogFilter implements Filter {
1.创建过滤器链
2.1.配置文件配置
过滤链的执行顺序:根据filter-mapping在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_3_1.xsd" version="3.1"> <!--过滤器链配置--> <filter> <filter-name>logFilter</filter-name> <filter-class>com.zhanggen.filter.LogFilter</filter-class> </filter> <filter> <filter-name>AFilter</filter-name> <filter-class>com.zhanggen.filter.AFilter</filter-class> </filter> <filter> <filter-name>BFilter</filter-name> <filter-class>com.zhanggen.filter.BFilter</filter-class> </filter> <!-- 根据filter-mapping的先后顺序决定过滤器的执行顺序--> <filter-mapping> <filter-name>logFilter</filter-name> <!-- 拦截请求的规则--> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>AFilter</filter-name> <!-- 拦截请求的规则--> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>BFilter</filter-name> <!-- 拦截请求的规则--> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <!--设置默认首页--> <welcome-file>login.html</welcome-file> </welcome-file-list> </web-app>
2.2.注解配置
过滤链的执行顺序:根据过滤器类名称的字符排序,值小的先执行
三、Listener(监听器)
web中的监听器在开发中使用的比较少,主要用于监听web三大域对象:Request、Session、ServletContext.
主要监听这三个域对象的创建和销毁以及域对象中存储对象的增加和减少。
web中的监听器一共有8个(扩展)分别用于监听不同的域对象。
ServletContextListener 监听ServletContext对象的创建和销毁
HttpSessionListener 监听HttpSession对象的创建和销毁
ServletRequestListener 监听ServletRequest对象的创建和销毁
ServletContextAttributeListener 监听ServletContext对象的数据的变化
HttpSessionAttributeListener 监听HttpSession对象的数据的变化
ServletRequestAttributeListener 监听ServletRequest对象的数据的变化
HttpSessionBindingListener 监听自己被绑定、解绑到HttpSession中
HttpSessionActivationListener 监听自己被钝化或激活了
1.创建监听器
package com.zhanggen.listener; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; @WebListener public class MyServletContextListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent servletContextEvent) { System.out.println("Tomcat创建完成了。。"); } @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { System.out.println("Tomcat即将销毁。。"); } }
2.配置监听器
可以通过2中方式配置1个监听器。
2.1.配置文件配置
<?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_3_1.xsd" version="3.1"> <!-- 配置一个监听器--> <listener> <listener-class>com.zhanggen.listener.MyServletContextListener</listener-class> </listener> <welcome-file-list> <!--设置默认首页--> <welcome-file>login.html</welcome-file> </welcome-file-list> </web-app>
2.2.注解配置
在Java中通过以下工具可以实现json序列化。
介绍 | |
---|---|
Jsonlib | Java类库,需要导入的jar包较多 |
Gson | google提供的一个简单的json转换工具 |
Fastjson | alibaba技术团队提供的一个高性能的json转换工具 |
Jackson |
Jackson完成数据转换使用的类是ObjectMapper,它有两个主要方法:
- String writeValueAsString(Object obj): 将一个对象转换为json字符串
- T readValue(String json, Class clazz): 将一个字符串转换为指定类型的对象
1.导入jar包
2.json序列化
Java对象转换成json字符串
package com.zhanggen.test; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.zhanggen.domain.User; import org.junit.Test; import java.util.ArrayList; import java.util.HashMap; //Java对象转换成json字符串 public class Object2json { @Test //1.对象-->json public void testObject2Json() throws JsonProcessingException { // 创建1个对象 User user = new User("a001", "张三丰", "男", 29, "武当山", "112", "1@qq.com"); //将对象转换成json字符串 String userJosn = new ObjectMapper().writeValueAsString(user); System.out.println(userJosn); } @Test //2.ArrayList-->json public void testList2Json() throws JsonProcessingException{ ArrayList<User> userList = new ArrayList<>(); userList.add(new User("a001", "张三丰", "男", 129, "武当山", "112", "1@qq.com")); userList.add(new User("a002", "冲虚道长", "男", 59, "武当山", "14", "2@qq.com")); String userListJosn = new ObjectMapper().writeValueAsString(userList); System.out.println(userListJosn); } @Test //2.ArrayList-->json public void testMap2Json() throws JsonProcessingException{ HashMap<String,String> userMap=new HashMap(); userMap.put("张三丰","129"); userMap.put("冲虚道长","29"); String userMapJson = new ObjectMapper().writeValueAsString(userMap); System.out.println(userMapJson); } }
3.json反序列化
json字符串转换成Java中的对象
package com.zhanggen.test; import com.fasterxml.jackson.databind.ObjectMapper; import com.zhanggen.domain.User; import org.junit.Test; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; //把json字符串转换成Java中的对象 public class Json2Object { @Test //1.json--->对象 public void testJson2Object() throws IOException { //准备1个对象json字符串 String jsonString = "{\"id\":\"a001\",\"name\":\"张三丰\",\"sex\":\"男\",\"age\":29,\"address\":\"武当山\",\"qq\":\"112\",\"email\":\"1@qq.com\"}"; //将对象json字符串转换为对象 User userObject = new ObjectMapper().readValue(jsonString, User.class); System.out.println(userObject); } //2.json-->ArrayList @Test public void testJson2List() throws IOException { String josnString = "[{\"id\":\"a001\",\"name\":\"张三丰\",\"sex\":\"男\",\"age\":129,\"address\":\"武当山\",\"qq\":\"112\",\"email\":\"1@qq.com\"},{\"id\":\"a002\",\"name\":\"冲虚道长\",\"sex\":\"男\",\"age\":59,\"address\":\"武当山\",\"qq\":\"14\",\"email\":\"2@qq.com\"}]"; List userList = new ObjectMapper().readValue(josnString, List.class); System.out.println(userList); } //3.json-->map @Test public void testJson2Map() throws IOException { String jsonString = "{\"张三丰\":\"129\",\"冲虚道长\":\"29\"}"; Map userMap = new ObjectMapper().readValue(jsonString, Map.class); System.out.println(userMap); } }
4.Servlet接收和响应json数据
在Servlet后台,可以通过
- 字节流
- 字符流
2种I/O流,接收和响应json数据。
--------------------------------------------------------------------
package com.zhanggen.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.*; @WebServlet("/LoginServlet") public class LoginServlet extends HttpServlet { @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //0.设置请求头和响应头编码 response.setContentType("application/json;charset=UTF-8"); request.setCharacterEncoding("utf-8"); //1.接收json数据 BufferedReader reader = request.getReader(); String json = reader.readLine(); System.out.println(json); reader.close(); //2.响应json数据 PrintWriter out = response.getWriter(); out.write("{\"name\":\"张根\"}"); out.close(); } }
--------------------------------------------------------------------
package com.zhanggen.servlet; import com.fasterxml.jackson.databind.ObjectMapper; import com.zhanggen.domain.User; import javax.servlet.ServletException; import javax.servlet.ServletInputStream; 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.*; @WebServlet("/LoginServlet") public class LoginServlet extends HttpServlet { @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //0.设置请求头和响应头编码 response.setContentType("application/json;charset=UTF-8"); request.setCharacterEncoding("utf-8"); String contentType = request.getContentType(); //1.接收json字符串反序列化成Java对象 BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream) request.getInputStream(), "utf-8")); StringBuffer sb = new StringBuffer(""); String temp; while ((temp = br.readLine()) != null) { sb.append(temp); } br.close(); //1.1.反序列化,json字符串-----》Java对象 System.out.println("json字符串---》" + sb.toString()); User userObject = new ObjectMapper().readValue(sb.toString(), User.class); System.out.println("Java对象---》" + userObject); //2.响应json字符串 //2.1.创建1个对象 User user = new User("a001", "张三丰", "男", 29, "武当山", "112", "1@qq.com"); //2.2.将对象转换成json字符串 //2.3.序列化:Java对象----》json字符串 String userJosn = new ObjectMapper().writeValueAsString(user); // 2.4通过字节输入流从byte数组中获取数据 InputStream is = new ByteArrayInputStream(userJosn.getBytes("utf-8")); //2.5 从response对象中获取1个字节输出流 ServletOutputStream op = response.getOutputStream(); //2.6.通过字节输入流读取到字节数据,输出到字节输出流中 int len; byte[] byteArray = new byte[1024]; while ((len = is.read(byteArray)) != -1) { op.write(byteArray, 0, len); } //2.7.缓冲区完成 op.flush(); } }
--------------------------------------------------------------------
前台如果使用的是ajax提交的post的请求体中携带的参数,后台接收的时候必须使用输入流接收。
使用hutool工具包,将输入流读成原来的json字符串。
//测试接收和响应json数据 private void testJson(HttpServletRequest request, HttpServletResponse response) throws IOException { //1. 前台如果使用的是ajax提交的post的请求体中携带的参数,后台接收的时候必须使用输入流接收 //1-1 接收数据称为数据流 ServletInputStream inputStream = request.getInputStream(); //1-2 使用hutool工具包,将输入流读成原来的json字符串 String json1 = IoUtil.read(inputStream, "utf-8"); //1-3 将json串再转换为一个Student对象 Student student = new ObjectMapper().readValue(json1, Student.class); System.out.println(student); //2. 调用service进行更新 student.setName("张根"); String json2 = new ObjectMapper().writeValueAsString(student); response.getWriter().write(json2); }