Java_Tomcat_servlet_Filte_会话技术Cookier_ajax_Json学习总结

一、Tomcat

1.1本地Tomcat的安装:

直接解压即可,最好放在没有中文的路径下。本地tomcat的启动,使用bin目录下的startup.bat(开启)shutdown.bat(关闭)。

1.2开启tomcat遇到的问题:

1.2.1:

遇到端口冲突,杀死占用端口号的进程即可

1.2.2:

开启时一闪而过,可能是JAVA_HOME没有配置好
如果JAVA_HOME是好的:那么可以试试下图方式:
在这里插入图片描述
在这里插入图片描述所有路径写到bin目录的上一级,需要将他们都放到path环境变量中。如果还不行,看别人教程。

1.3idea引入本地Tomcat:

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

1.3.1方式二:可以在Maven中引如坐标:
 <build>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <!-- tomcat7的插件, 不同tomcat版本这个也不一样 -->
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.1</version>
                <configuration>
                    <!-- 通过maven tomcat7:run运行项目时,访问项目的端口号 -->
                    <port>8080</port>

                    <!-- 项目访问路径  本例:localhost:9090,  如果配置的aa, 则访问路径为localhost:9090/aa-->
                    <!-- 也可以叫做配置的虚拟路径-->
                    <path>/aa</path><!-- ROOT -->
                    <!-- 这个设置可以解决tomcat7的get请求乱码问题!!!!! -->
                    <uriEncoding>utf-8</uriEncoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

二、Servlet

2.1

servlet是一个接口,是java定义的动态web资源开发技术。
Servlet接口的实现类重写doGet和doPost方法后执行的方式:
Servlet是一个接口,HttpServlet是对GenericServlet的继承,GenericServlet是对Servlet接口的实现tomcat会运行子类(通过@WebServlet(“/xxxx”)虚拟地址找到子类,并将虚拟地址和该类的全类名保存到map集合中,键为“虚拟地址”,值为:“全类名”),在运行子类时会自动使用反射的方法调用子类无参构造函数来创建对象用于调用方法。在子类的构造函数调用时会自行调用父类的无参构造并寻找父类的service()方法进行调用。父类的service()方法对类型请求类型进行判断后调用重写过后的doGet和doPost方法。

2.2service

service是servlet类中的一个方法,是编写后台逻辑的地方。
一般是如下形式:

package cn.web;

import cn.pojo.User;
import cn.service.UserService;

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("/loginServelt")
public class UserLoginServelt extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //用来解决request和respons中接收和传递的参数有中文的问题
    //req和resp是和前端页面进行交互进行数据传递的对象,里面封装了数据内容
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

        String username = req.getParameter("username");
        int password = Integer.parseInt(req.getParameter("password"));

        UserService us = new UserService();
        int i = us.userLogin(username, password);
//        未查询到结果
        if (i == -1) {
            req.setAttribute("msg", "用户名或密码有误");
            req.getRequestDispatcher("/login.jsp").forward(req, resp);
        }
        if (i == 1) {
            resp.sendRedirect(req.getContextPath() + "/success.jsp");
        }
    }
}

配合jsp页面:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录页面</title>
</head>
<body>
<div>
<!--用来接收后台request域中的数据-->
    <h3>${msg}</h3>
</div>
<!--未在pom中配置<path></path>所以需要写上项目路径,如果配置了就不写-->
<form action="/day10JSP-homework/loginServelt" method = post>
  账号: <input type="text" name="username" id="username"><br>
  密码: <input type="password" name="password" id="password"><br>
    <button type="submit" value="提交">登录</button>
</form>
<div>
    <a href="/day10JSP-homework/resiger.jsp">没有账号/注册</a>
</div>
</body>
</html>

2.2.1 request和response对象的一些方法:
//获取uri:localhost:8080之后,?号之前的数据(虚拟路径+资源路径)(/项目名/资源名)
        String requestURI = req.getRequestURI();

//      获取虚拟路径,因为我没有在pom中配置<path>/<path>所以返回的是项目名称
        String contextPath = req.getContextPath();

    // 获取参数,已经被淘汰,后期get和post方法传递方式一样
        String queryString = req.getQueryString();

//       通用获取请求体中的参数值,key与value一一对应--->获取单个值
//        此处表示获取前端form表单中name为“username”的输入框中的数据
        String username = req.getParameter("username");

//        一个键对应多个值,返回值为String[]
        String[] hobbies = req.getParameterValues("hobby");

//返回键值对
        Map<String, String[]> parameterMap = req.getParameterMap();
        Set<String> strings = parameterMap.keySet();
//response:重定向从虚拟路径开始写
resp.sendRedirect(req.getContextPath() + "/login.jsp");

//request:跳转,从资源路径写(servelet中设置的路径)
req.getRequestDispatcher( "/resiger.jsp").forward(req, resp);

其中requset属于域对象,可共享数据,并且域中的数据只在一次求中有效,只要是域都会有的方法:
setAttribute(key, value);getAttribute(key);removeAttribute(key)

2.2.1.1request

本质: 封装了请求部分的对象
目的: 获取跟浏览器消息有关的数据, 其中最重要就是浏览器带过来的参数!!!
出现的问题:
1.post会出现中文乱码问题:
解决:req.setCharaterEncoding(“UTF-8”);
原因:因为Http协议不支持中文, 浏览器传入中文数据, 会经过URLEncode的编码, 将其编程 十六进制的格式, tomcat解码的时候如果你没有设置编码则用ISO-8859-1编码来解码, 肯定出现乱码, 通过上面的那句话就可以设置编码
2.get会出现乱码问题
tomcat7才会出现,你接收到数据, 需要将其打回字节, 然后再用UTF-8组装
String s = ISO-8859-1; byte[] arr = s.getByte(“iso-8859-1”); new String(arr,“utf-8”);
tomcat8不会出现乱码问题,怎么设置, 如果是本地的不用设置. 如果用的maven的插件需要在tomcat的插件中添加一句

<uriEncoding>UTF-8</uriEncoding> 

String URLEncode.encode(要编码的字符串, “字符串原来的字符集”);
将字符串变成%的方式,URLDecode.decode(要解码的字符串, “期望的编码”)
将%的字符串变回原来的样子。

2.2.1.2Response

本质: 帮我们封装响应部分
目的: 设置服务器给浏览器消息数据
功能:
1.setStatus(int 状态码):设置状态码
2.setHeader(“键”, “值”):告诉浏览器服务器的一些信息, 可以控制浏览器的解析方式和行为重定向
1.设置状态码为302
2. 需要设置一个响应头告诉浏览器跳转的路径: location = “路径”
sendRedirect(“路径”);
/虚拟路径/资源路径
特点
1.地址栏会变化
2.对于浏览器而言其实发了多次请求
3.重定向不可以使用request对象共享数据
4.可以访问本工程的资源以及外部资源
5.重定向不可以访问WEB-INF下得东西

2.2.1.3解惑路径问题

绝对路径:
1.客户端路径:
a标签的href, form表单中的action, img中的src都是客户端路径, 经过浏览器地址栏的路径, 重定向也是,完整写法:http://ip地址:端口/虚拟路径/资源路径
简化写法(如果访问本服务下面的东西, 服务器的地址可以省略):/虚拟路径/资源路径
2.服务器路径
转发
必须从/资源路径开始写:原因是tomcat帮你加了/虚拟路径的限制
能够动态获取虚拟路径的地方都建议使用绝对路径:String req.getContextPath();
相对路径
html页面中建议使用相对路径
秘诀:
1. 确认自己的位置
2. 确定目标的位置
3. 通过 ./ 或者…/方式进行调整

2.2.2 对配置servlet的url-pattern(资源路径)
1.绝对路径匹配:"/Demo1"
2.目录匹配:"/user/*" ,只要访问/user/xxx都可以匹配
3.后缀名匹配:"*.m",后缀名不能以/开头
4.通配符:“/”,“/*”,极其不推荐!!!!!
2.2.3 最终步骤
HttpServlet
1.定义一个类去继承HttpServlet
2.重写带Http的service方法
3.在service方法中写逻辑
4.配置一下这个servlet的访问路径
	因为servlet也是java文件, 最后翻译到WEB-INF/classes目录下, WEB-INF下的资源都是比较珍贵的, 不能被浏览器直接访问, 那么告诉tomcat一个访问路径, 类似授权
2.2.4关于servlet编写过多的问题解决办法

我们在写一个小的项目时可能会遇到很多不同的请求,一次我们可能需要创建很多的servlet来实现功能。所以为了简化我们可以将对一个对象的servlet操作合并在一个servlet中。例如有一个User对象,我们就创建一个UserServlet(其中对数据库的操作被分离在service中)而且为再次简化我们又写了一个父类来实现service()方法,这里边还涉及了Mybatis框架看我Mybaits的文章即可,使用目录形式的访问路径代码如下,:

package cn.servlet;

import cn.SqlSessionUtil.CheckCodeUtil;
import cn.pojo.Code;
import cn.pojo.User;
import cn.service.UserService;
import com.alibaba.fastjson.JSON;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.sql.Date;
import java.util.List;
//资源访问路径变成:http://localhost:8080/虚拟路径(或项目名)/user/servlet方法名
@WebServlet("/user/*")
public class UserServlet extends BaseServlet {

    private void checkCode(HttpServletRequest req,HttpServletResponse resp) throws ServletException, IOException{
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        //        首先进行验证码的验证,先获得用户输入的验证码
        String checkCode = req.getParameter("checkCode");
        //        获取从前端传过来的JSON
        BufferedReader reader = req.getReader();
        String s = reader.readLine();
//        将json格式的字符串封装成类
        Code code = JSON.parseObject(s, Code.class);
        //        再获得程序保存在session中的验证码
        String checkImg =String.valueOf(req.getSession().getAttribute("checkimg"));
        System.out.println(req.getSession().getAttribute("checkimg"));
        if (!code.getCheckCode().equalsIgnoreCase(checkImg)){
            System.out.println("y验证码执行");
            resp.getWriter().write("验证码错误");
            return;
        }else{
            System.out.println("验证码正确");
            resp.getWriter().write("success");
        }
    }

    private void addUserServlet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

//        获取从前端传过来的JSON
        BufferedReader reader = req.getReader();
        String s = reader.readLine();
        System.out.println(s);
//        封装成类
        // 封装成类时出现了对象中的属性为null,原因:User类中忘记写set方法了,一直用的有参构造,但是parseObject需要调用set方法进行参数赋值
        User user = JSON.parseObject(s, User.class);
        System.out.println(user);
        UserService userService = new UserService();
        int i2 = userService.addUser(user);
        if (i2==-1){
           resp.getWriter().write(-1);
        }else if (i2==-2){
            resp.getWriter().write(-2);

        }else {
            resp.getWriter().write("注册成功");
        }
//      未使用ajax时的写法
       /* String username = req.getParameter("username");
        int password= Integer.parseInt(req.getParameter("password"));
        String gender = req.getParameter("gender");
        String address = req.getParameter("address");
        Date birthday = Date.valueOf(req.getParameter("birthday"));
        User user = new User(null,username,password,gender,address,birthday);
        UserService userService = new UserService();
        int i2 = userService.addUser(user);
        if (i2==-1){
            req.setAttribute("msg","用户名不能为空");
            req.getRequestDispatcher("/register.jsp").forward(req, resp);

        }else if (i2==-2){
            req.setAttribute("msg","用户密码不能为空");
            req.getRequestDispatcher("/register.jsp").forward(req, resp);

        }else {
            resp.sendRedirect(req.getContextPath()+"/login.jsp");

        }*/
    }

    private void checkCodeServlet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        ServletOutputStream os = resp.getOutputStream();
        String s = CheckCodeUtil.outputVerifyImage(100, 50, os, 4);
        //        将程序产生的验证码,保存到session
        req.getSession().setAttribute("checkimg",s);
    }

    private void deleteServlet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

        int id = Integer.parseInt(req.getParameter("id"));
        UserService userService = new UserService();
        int i1 = userService.deleteUserById(id);
        resp.sendRedirect(req.getContextPath()+"/user/findAllServlet");
    }

    private void findAllServlet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        //resp.setContentType("text/html;charset=utf-8");
        resp.setContentType("text/json;charset=utf-8");
        UserService userService = new UserService();
        List<User> users = userService.findAll();
//        将集合序列化成JSON数据,发送给前端
        String jsonString = JSON.toJSONString(users);
//        将json数据发送个前端
        resp.getWriter().write(jsonString);
        System.out.println(jsonString);
//        if (users.size()==0){
//            req.setAttribute("msg","数据库中没有数据");
//            req.getRequestDispatcher("/success.jsp").forward(req, resp);
//        }else{
//            req.setAttribute("users",users);
//            req.getRequestDispatcher("/showAll.jsp").forward(req, resp);
//        }
    }

    private void loginServlet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
//        获取前端传过来的数据
        String username = req.getParameter("username");
        String decodeusername = URLDecoder.decode(username);

        int password = Integer.parseInt(req.getParameter("password"));
        String isRemeber = req.getParameter("isRemeber");

        UserService userService = new UserService();
        User user = userService.selectByPasswordadnUsername(decodeusername, password);


//      如果相等表示用户勾选了记住密码,创建Cookie保存
//        cookie存储中文需要进行编码
        if ("true".equals(isRemeber)) {
            String usernameEncode = URLEncoder.encode(username);
            Cookie username1 = new Cookie("username", usernameEncode);
            Cookie password1 = new Cookie("password", req.getParameter("password"));
            username1.setMaxAge(60*60*24*7);
            password1.setMaxAge(60*60*24*7);
            resp.addCookie(username1);
            resp.addCookie(password1);
        }else{
//            用户未选中,就删除cookie
            String usernameEncode = URLEncoder.encode(username);
            Cookie username1 = new Cookie("username", usernameEncode);
            Cookie password1 = new Cookie("password", req.getParameter("password"));
            username1.setMaxAge(0);
            password1.setMaxAge(0);
            resp.addCookie(username1);
            resp.addCookie(password1);
        }
//        对登录的用户进行判空
        if (user != null) {
            //获取session对象,将user存入session域中,这样在整个会话期间jsp只需要jstl+el语言通过session的可以就可以取值
            HttpSession session = req.getSession();
            session.setAttribute("user", user);

            resp.sendRedirect(req.getContextPath() + "/success.jsp");
//            resp.sendRedirect(req.getContextPath() + "/register.html");
        } else {
            req.setAttribute("msg", "账号或密码有误");
            req.getRequestDispatcher("/login.jsp").forward(req, resp);
        }
    }

    private void selectOneServlet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

        int uid = Integer.parseInt(req.getParameter("id"));
        UserService userService = new UserService();
//        根据id查询到一个人
        User userById = userService.findUserById(uid);
        req.setAttribute("user",userById);
        req.getRequestDispatcher("/updata.jsp").forward(req, resp);
    }

    private void updataServlet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

        int uid = Integer.parseInt(req.getParameter("uid"));
        String username = req.getParameter("username");
        int password = Integer.parseInt(req.getParameter("password"));
        String gender = req.getParameter("gender");
        String address = req.getParameter("address");
        Date birthday =Date.valueOf(req.getParameter("birthday"));

        User user = new User(uid,username,password,gender,address,birthday);
        UserService userService = new UserService();

        int row = userService.updataUserById(user);
        if (row>0){
            resp.sendRedirect(req.getContextPath()+"/user/findAllServlet");
        }
    }
}


BaseServlet(写它的原因,反射的方法可以根据方法名字随时调用方法):

package cn.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;

public class BaseServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String requestURI = req.getRequestURI();
        int i = requestURI.lastIndexOf("/");
        String methodName = requestURI.substring(i + 1);

//使用反射的方式调用方法简化操作
        Class clazz = this.getClass();
        try {
            Method method = clazz.getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
            method.setAccessible(true);
            //this指代继承这个父类的子类对象
            method.invoke(this,req,resp);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

UserService(这里还抽取了SqlSession的工具类不展示了):

package cn.service;

import cn.SqlSessionUtil.SqlSessionFactorys;
import cn.mapper.UserMapper;
import cn.pojo.User;
import org.apache.ibatis.session.SqlSession;

import java.util.List;

public class UserService {
    /*
    * 添加用户
    * */
    public int addUser(User user){
        SqlSessionFactorys sqlSessionFactorys = new SqlSessionFactorys();
        SqlSession sqlSession = sqlSessionFactorys.getSqlSession();

        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        int row = userMapper.addUser(user);
        sqlSession.commit();
        if (user.getTbUsername().equals("")||user.getTbUsername()==null){
            return -1;
        }
        if (user.getTbPassword()==null){
            return -2;
        }
        return row;
    }
    /*
    * 根据用户名和密码查询用户
    * */
    public User selectByPasswordadnUsername(String username,Integer password){
        SqlSessionFactorys sqlSessionFactorys = new SqlSessionFactorys();
        SqlSession sqlSession = sqlSessionFactorys.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.selectByPasswordandUsername(username, password);
        return user;
    }
    /*
    * 查询所有用户信息
    * */
    public List<User> findAll(){
        SqlSessionFactorys sqlSessionFactorys = new SqlSessionFactorys();
        SqlSession sqlSession = sqlSessionFactorys.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = mapper.findAll();
        return users;
    }
    /*
    * 根据uid查询用户信息
    * */

    public User findUserById(int id){
        SqlSessionFactorys sqlSessionFactorys = new SqlSessionFactorys();
        SqlSession sqlSession = sqlSessionFactorys.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.selectById(id);
        return user;
    }
    /*
    * 根据 id修改用户数据
    * */
    public int updataUserById(User user){
        SqlSessionFactorys sqlSessionFactorys = new SqlSessionFactorys();
        SqlSession sqlSession = sqlSessionFactorys.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        sqlSession.commit();
        int i = userMapper.updataUser(user);
        return i;
    }
    /*
    * 删除用户
    * */
    public int deleteUserById(int id){
        SqlSessionFactorys sqlSessionFactorys = new SqlSessionFactorys();
        SqlSession sqlSession = sqlSessionFactorys.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        int i = userMapper.deleteUser(id);
        sqlSession.commit();
        return i;
    }
}

SqlSessionFactorys工具类:

package cn.SqlSessionUtil;


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 java.io.IOException;
import java.io.InputStream;

public class SqlSessionFactorys {
    private static SqlSession sqlSession;

    static {
        String resource = "Mybatis-config.xml";
        try {
            InputStream in = Resources.getResourceAsStream(resource);
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
            SqlSessionFactory build = sqlSessionFactoryBuilder.build(in);
            sqlSession = build.openSession();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public SqlSession getSqlSession() {
        return sqlSession;
    }
}

三、Filter过滤器

filter和servlet一样属于web里面的三大重点之一。作用: 抽取多个资源的共性操作,比如京东的一些操作,在你没有登录前是不可用的。页面请求时会被拦截,服务器响应时也会被拦截是一个环形。就像:
页面---->过滤器1------>过滤器2------>服务器
|
<-------- 过滤器1<------- 过滤器2<-------

使用步骤

1. 定义一个类实现javax.Filter接口
2.重写里面抽象方法:doFilter方法很重要
3.在doFilter中编写共性操作
4.放行
	chain.doFilter(req,resp);
5. 配置一下
	注解
		@WebFilter("拦截路径"):里面填写需要拦截的路径
			“/*”:拦截所有
		过滤的执行顺序和过滤器类名有关系, 按照类名自然顺序来执行

xml方法(执行顺序只和filter-mapping配置的上下顺序有关系):

  <filter>
        <filter-name>bbb</filter-name>
        <filter-class>cn.itcast.web.filter.FilterDemo4</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>bbb</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

有白名单和黑名单两种方法:
白名单方法(全部拦截,设置不需要拦截的路径):

package cn.Filter;

import javax.jws.WebService;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebFilter("/user/*")
public class UserFilter implements Filter {
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        //      白名单方式挑选不需要过滤的路径
//        强制类型转换
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        req.setCharacterEncoding("utf-8");
        String requestURI = req.getRequestURI();
//        判断session中有没有user对象,如果有证明登录过
        HttpSession session = req.getSession();
        Object user = session.getAttribute("user");
        if (user != null) {
//            登录过
            filterChain.doFilter(req, resp);
        } else {
//            没登陆过
//           白名单
            String[] path = new String[]{"/user/addUserServlet", "/user/checkCodeServlet", "/user/loginServlet"};
            for (int i = 0; i < path.length; i++) {
                if (requestURI.contains(path[i])) {
                    filterChain.doFilter(req, resp);
                    return;
                }
            }
            req.setAttribute("msg", "你还没有登录");
            req.getRequestDispatcher("/login.jsp").forward(req, resp);
        }

    }

    public void init(FilterConfig filterConfig) throws ServletException {

    }

    public void destroy() {

    }
}

黑名单方法:则是将需要拦截的路径全部写在@WebFilter(“拦截路径”)中,例如:
@WebFilter(“/loginServlet”,“/registerServlet”,“/findAllServlet”,…)。

四、会话技术

会话技术的使用就是为了使数据共享,保证一次会话的多次请求有效

4.1Cookie客户端会话技术

原理:将数据保存到客户端浏览器中,每次访问的时候cookie会将数据携带进入服务器。我们进行获取操作即可
比如我的登录操作,可以进行用户名和密码的保存就是用到了cookie方式。

操作:
1.将cookie发送到浏览器:
	resp.addCookie(cookie对象)
		setHeader("set-cookie","name=zs")
2.从浏览器端读取cookie:
	Cookie[] req.getCookies();
		遍历数组找到自己想要的cookie
			getHeader("cookie");通过;进行切割
3.控制cookie存活时间
	默认值是一个负数, 代表一次会话有效,存在内存中, 当浏览器关闭,会消失
	setMaxAge(秒值):`(60*60*24)`一天
Cookie的创建方式:
1.构造
	Cookie(String key, String value)
2.成员方法
	String getName();获取键
	String getValue();获取值
可能遇到的问题:
Cookie在tomcat7 以及以前不支持中文的, tomcat8以及之后支持中文, 但是不支持特殊字符, "空格",":,"
String  URLEncode.encode(要编码的字符串, "UTF-8");编码成十六进制+%的方式
String URLDecode.decode("要解码的字符串","utf-8");将十六进制+%变成中文

代码如下:

private void loginServlet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
//        获取前端传过来的数据
        String username = req.getParameter("username");
        String decodeusername = URLDecoder.decode(username);

        int password = Integer.parseInt(req.getParameter("password"));
        String isRemeber = req.getParameter("isRemeber");

        UserService userService = new UserService();
        User user = userService.selectByPasswordadnUsername(decodeusername, password);


//      如果相等表示用户勾选了记住密码,创建Cookie保存
//        cookie存储中文需要进行编码
        if ("true".equals(isRemeber)) {
            String usernameEncode = URLEncoder.encode(username);
             //创建cookie用来保存数据
            Cookie username1 = new Cookie("username", usernameEncode);
            Cookie password1 = new Cookie("password", req.getParameter("password"));
            // 设置存活时间7天
            username1.setMaxAge(60*60*24*7);
            password1.setMaxAge(60*60*24*7);
            //将cookie响应给前端浏览器
            resp.addCookie(username1);
            resp.addCookie(password1);
        }else{
//            用户未选中,就删除cookie
            String usernameEncode = URLEncoder.encode(username);
           
            Cookie username1 = new Cookie("username", usernameEncode);
            Cookie password1 = new Cookie("password", req.getParameter("password"));
            username1.setMaxAge(0);
            password1.setMaxAge(0);
            resp.addCookie(username1);
            resp.addCookie(password1);
        }
//        对登录的用户进行判空
        if (user != null) {
            //获取session对象,将user存入session域中,这样在整个会话期间jsp只需要jstl+el语言通过session的可以就可以取值
            HttpSession session = req.getSession();
            session.setAttribute("user", user);

            resp.sendRedirect(req.getContextPath() + "/success.jsp");
//            resp.sendRedirect(req.getContextPath() + "/register.html");
        } else {
            req.setAttribute("msg", "账号或密码有误");
            req.getRequestDispatcher("/login.jsp").forward(req, resp);
        }
    }

前端页面login.jsp:

<%@ page import="java.net.URL" %>
<%@ page import="java.net.URLDecoder" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!--使用jstl<c:if>语句是需要导入包-->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>登录</title>
</head>
<body>
<div>${msg}</div>
<div>
    <form action="/day12JspUser/user/loginServlet" method="post">
    <!--使用cookie.键名.value可以取出存在cookie中对应键中的值-->
        账号(用户名):<input type="text" name="username" id="username" value="${cookie.username.value}"><br>
        密码: <input type="password" name="password" id="password" value="${cookie.password.value}"><br>
        <!--使用jstl语言可以进行判断-->
        <c:if test="${cookie.username.value!=null}">
            记住密码:<input type="checkbox" name="isRemeber" value="true" checked><br>
        </c:if>
        <c:if test="${cookie.username.value==null}">
            记住密码:<input type="checkbox" name="isRemeber" value="true"><br>
        </c:if>
        <button type="submit" name="bt" value="bt">登录</button>
    </form>
</div>
<%--<div><a href="/day12JspUser/register.jsp">没有账号?/注册</a> </div>--%>
<div><a href="/day12JspUser/register.html">没有账号?/注册</a> </div>
</body>
</html>

Session(也是一个域对象,使用范围:一次会话)

一次会话的多次请求获取的是同一个session
原理:
原来Session基于Cookie的, 当我们调用getSession(), 会检查客户端有没有带JSESSIONID的Cookie,如果没有则, **认为第一次访问, 则会创建一个新的Session对象, 并且将这个Session的id以Cookie的形式存储到客户端浏览器, 这样就保证了在一次会话下,多个请求的seesion是同一个,**如果新来一个浏览器开启了新一次会话则会给新浏览器创建新的session下一次就会携带, 则不会创建的新的Session找的还是原来的session对象。
步骤:
1.获取session对象:req.getSession();
2.使用session,和request域的使用方式相同
setAttr------put
getAttr------get
removeAttr------remove
注意事项:
1.当浏览器不关闭, 服务器关闭, session还是不是同一个???
答:对象不是同一个,但是数据一样, 因为TOMCAT有个活化(反序列化), 钝化(序列化), tomcat在正常关闭的时候, 会将session中的数据保存到硬盘上, 然后重新启动会读到内存中, 但是id是不变的.
2.当服务器不关闭, 浏览器关闭, session还是同一个???
答:默认不是的, 又开了一次新的会话, 其实不是session不见了, session默认30分钟才销毁,而是打开session钥匙不见, JSESSIONID这个cookie默认的maxAge是负数, 一次会话有效. 我们是可以调整钥匙存活时间达到这个目的, 但是不推荐!!!

使用session来保存注册时的验证码,因为两个servlet之间是没有数据交互的,所以需要用到共享数据:
产生验证码图片的工具类:

package cn.SqlSessionUtil;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Random;

/**
 * 生成验证码工具类
 */
public class CheckCodeUtil {

    public static final String VERIFY_CODES = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static Random random = new Random();



    /**
     * 输出随机验证码图片流,并返回验证码值(一般传入输出流,响应response页面端,Web项目用的较多)
     *
     * @param w
     * @param h
     * @param os
     * @param verifySize
     * @return
     * @throws IOException
     */
    public static String outputVerifyImage(int w, int h, OutputStream os, int verifySize) throws IOException {
        String verifyCode = generateVerifyCode(verifySize);
        outputImage(w, h, os, verifyCode);
        return verifyCode;
    }

    /**
     * 使用系统默认字符源生成验证码
     *
     * @param verifySize 验证码长度
     * @return
     */
    public static String generateVerifyCode(int verifySize) {
        return generateVerifyCode(verifySize, VERIFY_CODES);
    }

    /**
     * 使用指定源生成验证码
     *
     * @param verifySize 验证码长度
     * @param sources    验证码字符源
     * @return
     */
    public static String generateVerifyCode(int verifySize, String sources) {
        // 未设定展示源的字码,赋默认值大写字母+数字
        if (sources == null || sources.length() == 0) {
            sources = VERIFY_CODES;
        }
        int codesLen = sources.length();
        Random rand = new Random(System.currentTimeMillis());
        StringBuilder verifyCode = new StringBuilder(verifySize);
        for (int i = 0; i < verifySize; i++) {
            verifyCode.append(sources.charAt(rand.nextInt(codesLen - 1)));
        }
        return verifyCode.toString();
    }

    /**
     * 生成随机验证码文件,并返回验证码值 (生成图片形式,用的较少)
     *
     * @param w
     * @param h
     * @param outputFile
     * @param verifySize
     * @return
     * @throws IOException
     */
    public static String outputVerifyImage(int w, int h, File outputFile, int verifySize) throws IOException {
        String verifyCode = generateVerifyCode(verifySize);
        outputImage(w, h, outputFile, verifyCode);
        return verifyCode;
    }



    /**
     * 生成指定验证码图像文件
     *
     * @param w
     * @param h
     * @param outputFile
     * @param code
     * @throws IOException
     */
    public static void outputImage(int w, int h, File outputFile, String code) throws IOException {
        if (outputFile == null) {
            return;
        }
        File dir = outputFile.getParentFile();
        //文件不存在
        if (!dir.exists()) {
            //创建
            dir.mkdirs();
        }
        try {
            outputFile.createNewFile();
            FileOutputStream fos = new FileOutputStream(outputFile);
            outputImage(w, h, fos, code);
            fos.close();
        } catch (IOException e) {
            throw e;
        }
    }

    /**
     * 输出指定验证码图片流
     *
     * @param w
     * @param h
     * @param os
     * @param code
     * @throws IOException
     */
    public static void outputImage(int w, int h, OutputStream os, String code) throws IOException {
        int verifySize = code.length();
        BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        Random rand = new Random();
        Graphics2D g2 = image.createGraphics();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        // 创建颜色集合,使用java.awt包下的类
        Color[] colors = new Color[5];
        Color[] colorSpaces = new Color[]{Color.WHITE, Color.CYAN,
                Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE,
                Color.PINK, Color.YELLOW};
        float[] fractions = new float[colors.length];
        for (int i = 0; i < colors.length; i++) {
            colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];
            fractions[i] = rand.nextFloat();
        }
        Arrays.sort(fractions);
        // 设置边框色
        g2.setColor(Color.GRAY);
        g2.fillRect(0, 0, w, h);

        Color c = getRandColor(200, 250);
        // 设置背景色
        g2.setColor(c);
        g2.fillRect(0, 2, w, h - 4);

        // 绘制干扰线
        Random random = new Random();
        // 设置线条的颜色
        g2.setColor(getRandColor(160, 200));
        for (int i = 0; i < 20; i++) {
            int x = random.nextInt(w - 1);
            int y = random.nextInt(h - 1);
            int xl = random.nextInt(6) + 1;
            int yl = random.nextInt(12) + 1;
            g2.drawLine(x, y, x + xl + 40, y + yl + 20);
        }

        // 添加噪点
        // 噪声率
        float yawpRate = 0.05f;
        int area = (int) (yawpRate * w * h);
        for (int i = 0; i < area; i++) {
            int x = random.nextInt(w);
            int y = random.nextInt(h);
            // 获取随机颜色
            int rgb = getRandomIntColor();
            image.setRGB(x, y, rgb);
        }
        // 添加图片扭曲
        shear(g2, w, h, c);

        g2.setColor(getRandColor(100, 160));
        int fontSize = h - 4;
        Font font = new Font("Algerian", Font.ITALIC, fontSize);
        g2.setFont(font);
        char[] chars = code.toCharArray();
        for (int i = 0; i < verifySize; i++) {
            AffineTransform affine = new AffineTransform();
            affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize / 2, h / 2);
            g2.setTransform(affine);
            g2.drawChars(chars, i, 1, ((w - 10) / verifySize) * i + 5, h / 2 + fontSize / 2 - 10);
        }

        g2.dispose();
        ImageIO.write(image, "jpg", os);
    }

    /**
     * 随机颜色
     *
     * @param fc
     * @param bc
     * @return
     */
    private static Color getRandColor(int fc, int bc) {
        if (fc > 255) {
            fc = 255;
        }
        if (bc > 255) {
            bc = 255;
        }
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r, g, b);
    }

    private static int getRandomIntColor() {
        int[] rgb = getRandomRgb();
        int color = 0;
        for (int c : rgb) {
            color = color << 8;
            color = color | c;
        }
        return color;
    }

    private static int[] getRandomRgb() {
        int[] rgb = new int[3];
        for (int i = 0; i < 3; i++) {
            rgb[i] = random.nextInt(255);
        }
        return rgb;
    }

    private static void shear(Graphics g, int w1, int h1, Color color) {
        shearX(g, w1, h1, color);
        shearY(g, w1, h1, color);
    }

    private static void shearX(Graphics g, int w1, int h1, Color color) {

        int period = random.nextInt(2);

        boolean borderGap = true;
        int frames = 1;
        int phase = random.nextInt(2);

        for (int i = 0; i < h1; i++) {
            double d = (double) (period >> 1)
                    * Math.sin((double) i / (double) period
                    + (6.2831853071795862D * (double) phase)
                    / (double) frames);
            g.copyArea(0, i, w1, 1, (int) d, 0);
            if (borderGap) {
                g.setColor(color);
                g.drawLine((int) d, i, 0, i);
                g.drawLine((int) d + w1, i, w1, i);
            }
        }

    }

    private static void shearY(Graphics g, int w1, int h1, Color color) {

        int period = random.nextInt(40) + 10; // 50;

        boolean borderGap = true;
        int frames = 20;
        int phase = 7;
        for (int i = 0; i < w1; i++) {
            double d = (double) (period >> 1)
                    * Math.sin((double) i / (double) period
                    + (6.2831853071795862D * (double) phase)
                    / (double) frames);
            g.copyArea(i, 0, 1, h1, 0, (int) d);
            if (borderGap) {
                g.setColor(color);
                g.drawLine(i, (int) d, i, 0);
                g.drawLine(i, (int) d + h1, i, h1);
            }

        }

    }
}


前端页面请求验证码:

  <form id="form" action="" method="post">
        用户名:<input type="text" name="username" id="username" value="陈庆旭1"><br>
        密码:<input type="password" name="password" id="password" value="123456"><br>
        性别:<input type="radio" name="gender" value="0"><input type="radio" name="gender" value="1"><br>
        地址:<input type="text" name="address" id="address" value="sdfsdfa"><br>
        生日:<input type="date" name="birthday" id="birthday"><br>
        验证码:<input name="checkCode" type="text" id="checkCode">
        <!--向CheckCodeServlet发出请求-->
        <img id="checkCodeImg" src="/day12JspUser/user/checkCodeServlet">
        <a href="#" id="checkImg">看不清楚</a><br>
        <button type="button" name="bt" id="bt" value="bt">注册</button>
    </form>
    
    <!--使用ajax框架axios,进行异步请求-->
    <script>
    document.querySelector("#bt").onclick=function (){
        //给验证码一个异步请求
        axios({
            method: "post",
            url:"/day12JspUser/user/checkCode",
            data:{
                checkCode:document.querySelector("#checkCode").value
            }
        }).then(function (resp){
            if (resp.data=="验证码错误"){
                alert("验证码错误");
            }
            if(resp.data=="success"){
            <!--JSON字符串的格式-->
                var formData = {
                    tbUsername: "",
                    tbPassword: "",
                    tbAddress: "",
                    tbBirthday: "",
                    tbGender: "",
                }
                //   获取表单中的数据
                formData.tbUsername = document.querySelector("#username").value;
                formData.tbPassword = document.querySelector("#password").value;
                formData.tbAddress = document.querySelector("#address").value;
                formData.tbBirthday = document.querySelector("#birthday").value;
                //   对于单选框单独处理,会返回一个数组
                let genders = document.getElementsByName("gender");

                for (let i = 0; i < genders.length; i++) {
                    if (genders[i].checked) {
                        formData.tbGender = genders[i].value;
                    }
                }
                axios({
                    method: "post",
                    url: "/day12JspUser/user/addUserServlet",
                    data: formData
                }).then(function (resp) {
                
                <!%--resp是后端的response给的响应值%-->
                    if (resp.data=="注册成功"){
                        location.href="/day12JspUser/login.jsp"
                    }
                    if (resp.data == -1){
                        alert("用户名不能为空")
                    }
                    if (resp.data == -2){
                        alert("密码不能为空")
                    }
                })
            }
        });


    }
    // 给a标签绑定点击事件
    document.querySelector("#checkImg").onclick = function () {
        let milliseconds = new Date().getMilliseconds();
        document.querySelector("#checkCodeImg").src = "/day12JspUser/user/checkCodeServlet?" + milliseconds;
    }
</script>

产生验证码图片的CheckCodeServlet:

 private void checkCodeServlet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        ServletOutputStream os = resp.getOutputStream();
        String s = CheckCodeUtil.outputVerifyImage(100, 50, os, 4);
        //        将程序产生的验证码,保存到session
        req.getSession().setAttribute("checkimg",s);
    }

点击注册后会先跳转到checkCode(也是一个servlet),经过判断后再跳转到addUserServlet中:
checkCode用来验证,验证码输入的正确性:

private void checkCode(HttpServletRequest req,HttpServletResponse resp) throws ServletException, IOException{
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        //        首先进行验证码的验证,先获得用户输入的验证码
        String checkCode = req.getParameter("checkCode");
        //        获取从前端传过来的JSON
        BufferedReader reader = req.getReader();
        String s = reader.readLine();
//        将json格式的字符串封装成类
        Code code = JSON.parseObject(s, Code.class);
        //        再获得程序保存在session中的验证码
        String checkImg =String.valueOf(req.getSession().getAttribute("checkimg"));
        System.out.println(req.getSession().getAttribute("checkimg"));
        if (!code.getCheckCode().equalsIgnoreCase(checkImg)){
         
            resp.getWriter().write("验证码错误");
            return;
        }else{
          
            resp.getWriter().write("success");
        }
    }

里边的Code类视为了方便造的一个实体类:

package cn.pojo;

public class Code {
    private String checkCode;

    public Code(String checkCode) {
        this.checkCode = checkCode;
    }

    public Code() {
    }

    public String getCheckCode() {
        return checkCode;
    }

    public void setCheckCode(String checkCode) {
        this.checkCode = checkCode;
    }

    @Override
    public String toString() {
        return "Code{" +
                "checkCode='" + checkCode + '\'' +
                '}';
    }
}

addUserServlet重点是接收前端用axiso传递的参数:
 private void addUserServlet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

//        获取从前端传过来的JSON,即用户输入的验证码
        BufferedReader reader = req.getReader();
        String s = reader.readLine();
        System.out.println(s);
//        封装成类
        // 封装成类时出现了对象中的属性为null,原因:User类中忘记写set方法了,一直用的有参构造,但是parseObject需要调用set方法进行参数赋值
        User user = JSON.parseObject(s, User.class);
        System.out.println(user);
        UserService userService = new UserService();
        int i2 = userService.addUser(user);
        if (i2==-1){
           resp.getWriter().write(-1);
        }else if (i2==-2){
            resp.getWriter().write(-2);

        }else {
            resp.getWriter().write("注册成功");
        }
//      未使用ajax时的写法
       /* String username = req.getParameter("username");
        int password= Integer.parseInt(req.getParameter("password"));
        String gender = req.getParameter("gender");
        String address = req.getParameter("address");
        Date birthday = Date.valueOf(req.getParameter("birthday"));
        User user = new User(null,username,password,gender,address,birthday);
        UserService userService = new UserService();
        int i2 = userService.addUser(user);
        if (i2==-1){
            req.setAttribute("msg","用户名不能为空");
            req.getRequestDispatcher("/register.jsp").forward(req, resp);

        }else if (i2==-2){
            req.setAttribute("msg","用户密码不能为空");
            req.getRequestDispatcher("/register.jsp").forward(req, resp);

        }else {
            resp.sendRedirect(req.getContextPath()+"/login.jsp");

        }*/
    }

五、ajax

作用:使得前后端的交流变得更加方便
好处:
1.客户端体验连续的
2.异步从来不会主动更新页面 , 支持局部刷新效率高
使用的是axiso框架。
先导入js文件

<script src="js/axios-0.18.0.js"></script>

使用格式:

<script>

    document.querySelector("button").onclick = function () {
        //发送异步请求
        /*
        * get请求
        * */
      /*  axios({
            method: "get",
            url:"/day12-Filter/TestServlet?username=zs",
        }).then(function (resp){
            alert(resp.data);
        })*/

        /*
        * post请求
        * */
        axios({
            method:"post",
            url:"/day12-Filter/TestServlet",
            data:"username=zs",
        }).then(function (resp){
            alert(resp.data);
        })

    }

</script>

简便格式,不建议使用:

axios.get(url).then(function(result){


})

axios.post(url, 参数).then(function(result)){


}

使用ajax传递参数演示过了,在Session出的前端页面处。
展示接收参数:

<script>
    window.onload = function (){
        axios({
            method:"get",
            url:"/day12JspUser/user/findAllServlet",
        }).then(function (resp){
            let datas = resp.data;
            let tableData = " <tr>\n" +
                "        <th>序号</th>\n" +
                "        <th>用户名</th>\n" +
                "        <th>用户密码</th>\n" +
                "        <th>性别</th>\n" +
                "        <th>地址</th>\n" +
                "        <th>生日</th>\n" +
                "        <th>操作</th>\n" +
                "    </tr>";
            let gender;
            for (let i = 0; i < datas.length; i++) {
                let user = datas[i];
                if(user.tbGender==1){
                    gender="女"
                }else{
                    gender="男"
                }
                //user.bir其实执行的也是User类中的getBir方法,和user.tbBirthday一样的效果
                tableData += " <tr>\n" +
                    "            <td>"+(i+1)+"</td>\n" +
                    "            <td>"+user.tbUsername+"</td>\n" +
                    "            <td>"+user.tbPassword+"</td>\n" +
                    "            <td>"+gender+"</td>\n" +
                    "            <td>"+user.tbAddress+"</td>\n" +
                    "            <td>"+user.tbBirthday+"</td>\n" +
                    "            <td><a href=\"/day12JspUser/user/selectOneServlet?id="+user.tbUid+"\">修改</a>|<a\n" +
                    "                    href=\"/day12JspUser/user/deleteServlet?id="+user.tbUid+"\">删除</a></td>\n" +
                    "        </tr>"
                document.querySelector("table").innerHTML=tableData;
            }
        })
    }

</script>

再来一个展示后端数据的页面,用于修改操作的数据回显:

 window.onload = function () {
        //获取从另一个页面传过来的地址中的参数值
        C1 = window.location.href.split("?")[1];
        uid = C1.split("=")[1];

        axios({
            method: "get",
            url: "/day12JspUser/user/selectOneServlet?id=" + uid
        }).then(function (resp) {
            let us = resp.data;
            document.querySelector("#uid").value = us.tbUid;
            document.querySelector("#username").value = us.tbUsername;
            document.querySelector("#password").value = us.tbPassword;
            document.querySelector("#address").value = us.tbAddress;
            document.querySelector("#birthday").value = us.tbBirthday;
            let genders = document.getElementsByName("gender");
            if (us.tbGender == 0) {
                genders[0].checked = true;
            }
            if (us.tbGender == 1) {
                genders[1].checked = true;
            }
        })
    }

六、JSON串

本质就是字符串
键必须使用双引号, 值如果是数字类型或者boolean类型可以不用引号, 其他类型都要双引号引起来,演示:

 var formData = {
                    tbUsername: "",
                    tbPassword: "",
                    tbAddress: "",
                    tbBirthday: "",
                    tbGender: "",
                }

最后显示:
在这里插入图片描述

1.json字符串 转成:JSON对象
JSON.parse(json字符串),因为要获取json的数据, 需要使用JSON打点调用
2.JSON对象 转成: json字符串
JSON.stringify(JSON对象),因为传参的时候要的json字符串, 所有js框架都会帮json对象转成字符串
3.语法:
{}:代表对象
[]:代表数据
4.在maven中导入依赖

 <dependency> 
      <groupId>com.alibaba</groupId>  
      <artifactId>fastjson</artifactId>  
      <version>1.2.62</version> 
    </dependency>

java对象 ----> json字符串
java数组或集合—>json字符串

JSON.toJsonString(java对象),例如:

 @Test
public void test1(){
    List<User> list = new ArrayList<>();
    list.add(new User("aaa",18,178,80, new Date()));
    list.add(new User("aaa",18,178,80, new Date()));
    list.add(new User("aaa",18,178,80, new Date()));
    list.add(new User("aaa",18,178,80, new Date()));


    String s = JSON.toJSONString(list);

}

json字符串(String类型) ----> java对象
JSON.parseObject(json字符串),例如:

    @Test
public void test3() {
    String s = "{\"age\":18,\"birthday\":\"2021-10-23\",\"height\":178,\"weight\":80}";
    User user = JSON.parseObject(s, User.class);
    System.out.println(user);
}

json字符串 -----> java集合
JSON.parseArray(json字符串, java对象),例如:

	  @Test
public void test4(){
    String s = "[{\"age\":18,\"birthday\":\"2021-10-23\",\"height\":178,\"weight\":80},{\"age\":18,\"birthday\":\"2021-10-23\",\"height\":178,\"weight\":80}]";
    List<User> users = JSON.parseArray(s, User.class);

}

@JSONField
format:可以编写日期的格式
serialize:是否需要序列化
例如:

public class User {
    //在将user对象转成json时候不转化name
    @JSONField(serialize = false)
    private String name;
    //在将user对象变成json的时候,birthday按照yyyy-MM-dd的方式转换
    @JSONField(format="yyyy-MM-dd")
    private Date birthday;
    private int age;
    private int height;
    private int weight;
}

转换函数的使用:

//        获取从前端传过来的JSON
        BufferedReader reader = req.getReader();
        //因为传过来的JSON串多长都是一行,所以读取一行就够了
        String s = reader.readLine();
        System.out.println(s);
//        封装成类
        // 封装成类时出现了对象中的属性为null,原因:User类中忘记写set方法了,一直用的有参构造,但是parseObject需要调用set方法进行参数赋值
        User user = JSON.parseObject(s, User.class);

传数据的前端:

 if(resp.data=="success"){
                //存储成JSON格式
                var formData = {
                    tbUsername: "",
                    tbPassword: "",
                    tbAddress: "",
                    tbBirthday: "",
                    tbGender: "",
                }
                //   获取表单中的数据
                formData.tbUsername = document.querySelector("#username").value;
                formData.tbPassword = document.querySelector("#password").value;
                formData.tbAddress = document.querySelector("#address").value;
                formData.tbBirthday = document.querySelector("#birthday").value;
                //   对于单选框单独处理,会返回一个数组
                let genders = document.getElementsByName("gender");
                //如果被勾选则赋值
                for (let i = 0; i < genders.length; i++) {
                    if (genders[i].checked) {
                        formData.tbGender = genders[i].value;
                    }
                }
                axios({
                    method: "post",
                    url: "/day12JspUser/user/addUserServlet",
                    data: formData
                }).then(function (resp) {
                    if (resp.data=="注册成功"){
                        location.href="/day12JspUser/login.jsp"
                    }
                    if (resp.data == -1){
                        alert("用户名不能为空")
                    }
                    if (resp.data == -2){
                        alert("密码不能为空")
                    }
                })
            }

传过来的Json串格式:
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值