Servlet

Servlet和jsp

b/s:浏览器请求,服务器响应

c/s:客户端请求,服务器响应

资源:

动态资源(jsp,servlet):不同用户访问同一动态资源的时候得到的结果可能会不一样

静态资源(jpg,png,css,js,html):不同用户访问同一静态资源时得到的结果一样

Servlet

即server applet,运行在服务器上的小程序,定义了一套浏览器如何访问服务器的规则,本质上是一个接口Servlet

生命周期

创建Servlet对象后---------->初始化(调用 init () 方法)--------->处理/响应客户端的请求(调用 service() 方法)--------->销毁(调用 destroy() 方法,最后由 JVM 的垃圾回收器进行垃圾回收)

  1. 首先定义类并实现Servlet接口,重写其中的方法

    方法作用
    initservlet的初始化方法,当第一次访问该servlet的时候执行该初始化方法(生命周期可以更改,可以通过修改初始化方法,令服务器一启动就执行初始化方法(如下))
    serviceservlet的服务方法每一次访问该servlet的时候都会执行该服务方法
    destroyservlet的销毁方法,当服务器正常关闭时,执行该销毁方法
  2. web.xml的配置文件,如下

  1. 与一相同,继承Servlet接口

  2. 无需在web.xml中进行配置,而是通过@WebServlet注解,可以代替web.xml中所有关于该servlet的配置,将url填写在该注解后的括号中

  1. 直接继承GenericServlet类,GenericServlet是一个抽象类,对init和destroy方法进行了空实现,只需实现service方法

  2. 同样使用注解

四(请求)

  1. 继承HttpServlet,重写doGet和doPost方法,默认请求方式为get,所以默认调用doGet方法,当请请求方式为post时调用doPost方法(可采用嵌套方式,即在doGet方法内调用doPost方法,这样,无论使用什么请求都会调用doPost方法)

  2. 新建jsp页面

get请求和post请求的区别

get请求:在地址栏中拼接参数,参数不能存放太大,大概2k左右,相对来说不安全;查询效率高于post请求;get请求没有请求体,只有query string

post请求:请求参数放在请求体中,相对来说更安全,查询效率没有get高

五(注解写法)

使用@WebServlet注解时,可使用多种方法

  • 第一种:@WebServlet("/servletDemo5")

  • 第二种(多路径写法):@WebServlet({"/xxx","/yyy"})

  • 第三种(只要后缀为.can的路径都可以访问):@WebServlet("*.can")

  • 第四种(只要前缀为/user/的路径都可以访问):@WebServlet("/user/*")

  • 第五种(可以绑定所有,但优先级低于已经绑定的url,并且可以访问.jsp后缀的文件(当地址栏输入xxx.jsp时会跳转到jsp页面),而不会跳转到servletDemo5):@WebServlet("/")

  • 第六种(可以绑定所有,但优先级低于已经绑定的url,匹配不到.jsp后缀的文件(当地址栏输入xxx.jsp时会匹配为servletDemo5),并且会把.jsp后缀的文件匹配到servletDemo5):@WebServlet("/*")

Request

参数中的request是客户端传入的,即doGet和doPost方法的形参

中文乱码问题

request.setCharacterEncoding("utf-8");

获取参数(表单中name属性的值)

String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println(username+":"+password);

路径

System.out.println(request.getRequestURL());// 完整路径
System.out.println(request.getRequestURI());// 部分路径

获取地址栏拼接参数(只有get请求有)(略)

System.out.println(request.getQueryString());

获取请求头中的值(略)

System.out.println(request.getHeader("Host"));

域对象

四大域对象(page(jsp有效),request(一次请求),session(一次会话),servletContext(application--jsp中的名字)(当前web应用))

// 域对象:能够在一定的范围内共享数据
// request的作用域在一次请求和一次响应之间
// xxx.setAttribute即为设置域对象
request.setAttribute("username","张三");// 参数为“名值对”
//由于request作用范围是一次请求一次响应,浏览器访问requestDemo1视为一次请求,若要获取username的值,就需要在本次响应中返回,而不能再次调用requestDemo2进行返回,但可以使用请求转发,如下
System.out.println(request.getAttribute("username"));

请求转发

// 当访问requestDemo1时,地址栏仍为requestDemo1,但由requestDemo2返回值,不能跳转到外部资源
// 由于请求转发是一次请求,所以使用请求转发,仍可以调用到requestDemo2,可以获取username的值,而不需要在地址栏输入进行二次请求
// 获取请求转发器
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/requestDemo2");
// 请求转发
requestDispatcher.forward(request,response);

实例

登录功能

@WebServlet("/requestLoginTest")
public class RequestLoginTest extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
​
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取表单中的账号密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        // 获取到登录页面和登陆成功页面的请求转发器
        RequestDispatcher requestDispatcher1 = request.getRequestDispatcher("/login.jsp");
        RequestDispatcher requestDispatcher2 = request.getRequestDispatcher("/successful.jsp");
        // 账号密码判断
        if (username.equals("zhangsan")) {
            if (password.equals("123456")) {
                // 登录成功,通过请求转发跳转到登陆成功页面
                requestDispatcher2.forward(request,response);
            } else {
                // 设置域对象,用于在登录页面通过${requestScope.end}展示值
                request.setAttribute("end","密码错误");
                requestDispatcher1.forward(request,response);
            }
        } else {
            request.setAttribute("end","账号错误");
            requestDispatcher1.forward(request,response);
        }
    }
}

Response

常见响应状态码:

  • 200:成功响应,正常的状态码

  • 302:重定向,正常的状态码

  • 404:请求资源找不到(查看访问的路径是否正确,查看访问的资源福否被编译进out目录)

  • 405:请求的方法不允许(后端无法接收前端的请求方式)

  • 403:请求被拒绝(在爬虫中加上请求头user-agent)

  • 500:服务器内部出错(在idea控制台中查看报错信息)

乱码问题

response.setContentType("text/html;charset=utf-8");

写入数据

// 将数据写给前端,在没有处理的情况下会直接显示在前端网页上
response.getWriter().write("张三");

重定向

response.sendRedirect("/login.jsp");

请求转发和重定向

请求转发重定向
一次请求两次请求
在服务器内部进行资源跳转,不能访问外部资源服务器会告诉浏览器访问什么资源,可以访问外部资源
地址栏没有发生变化地址栏发生了变化
浏览器不知道服务器内部做了什么浏览器接收到重定向的消息后再进行访问

Cookie

会话(多次请求,多次响应)技术,运行在客户端上

解决多次请求和多次响应之间共享数据的问题

创建cookie

// value可以存储中文,但在存储空格时需要进行编码和解码
String value = "月 亮";
String encode = URLEncoder.encode(value, "utf-8");
Cookie cookie = new Cookie("name",encode);

添加cookie

// cookie的存储时间默认在浏览器关闭后就消失
// 设置getMaxAge();可让关闭后还能存在
// 当参数为正整数时,是多少就是多少秒
// 当参数为0时,删除该cookie
// 当参数为-1时,就是默认情况
cookie.getMaxAge();
// 把cookie添加到响应中,让浏览器能存储它
response.addCookie(cookie);

拿到请求中的cookie

Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
    String name = cookie.getName();
    // 解码
    if ("name".equals(name)) {
        String value = cookie.getValue();
        String decode = URLDecoder.decode(value,"utf-8");
        System.out.println(name+":"+decode);
    }
}

实例

登录注册

@WebServlet("/cookieLoginTest")
public class CookieLoginTest extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 解决乱码问题
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        RequestDispatcher requestDispatcher = request.getRequestDispatcher("/login.jsp");
        // 标志位,判断是否是第一次登录
        boolean flag = true;

        if (username.equals("zhangsan")) {
            if (password.equals("123456")) {
                // 登陆成功时,记录登录时间
                Date date = new Date();
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
                String format1 = format.format(date);

                // 遍历cookie
                Cookie[] cookies = request.getCookies();
                for (Cookie cookie : cookies) {
                    String name = cookie.getName();
                    // 第一次访问时,没有名为name的cookie,所以不进入该if
                    if (name.equals("name")) {
                        String value = cookie.getValue();
                        String decode = URLDecoder.decode(value, "utf-8");
                        response.getWriter().write( "欢迎,您上次登录的时间为" + decode);
                        flag = false;
                    }
                }
                if (flag) {
				   //request.setAttribute("welcome", "欢迎,这是您第一次登录");
				   //requestDispatcher.forward(request, response);
                    // 将数据写给前端(使用cookie时,尽量不使用请求转发)?
                    response.getWriter().write("欢迎,这是您第一次登录!");
                }
                // 将时间添加到cookie中
                String encode = URLEncoder.encode(format1, "utf-8");
                Cookie cookie1 = new Cookie("name", encode);
                response.addCookie(cookie1);
            } else {
                request.setAttribute("end", "密码错误");
                // 使用请求转发,如果使用了request域,使用重定向后,request就失效了,因为超出了作用域范围
                requestDispatcher.forward(request, response);
            }
        } else {
            request.setAttribute("end", "账号不存在");
            requestDispatcher.forward(request, response);
        }
    }
}

Session

会话技术,存储在服务器上(相对于cookie更加安全)

session依赖cookie而存活,当浏览器第一次访问服务器时,会生成一把“钥匙”,即Set-Cookie:JSESSIONID=xxx,在后续的访问中,浏览器都会携带该同一钥匙,若钥匙相同,则可以访问到服务器获取值;在关闭浏览器后,cookie销毁,重启浏览器,会重新生成一把“钥匙”,由于重新生成的钥匙和原钥匙不匹配,所以无法得到相应的值,要解决该问题就需要增大cookie的生命周期

拿到session对象

HttpSession session = request.getSession();

设置域对象

session.setAttribute("name","zhangsan");

设置生命周期添加

// 让浏览器关闭后再启动依旧能访问到服务器中的session数据(增大cookie的生命周期)
// 拿到当前session的钥匙,JSESSIONID的值,并设置存活时间
String id = session.getId();
Cookie cookie = new Cookie("JSESSIONID",id);
cookie.setMaxAge(500);
response.addCookie(cookie);

ServletContext

作用域为全局

得到对象添加值

javax.servlet.ServletContext servletContext = request.getServletContext();
servletContext.setAttribute("config","xxxxx");

Filter过滤器

1.通过@WebFilter()对指定文件进行过滤,括号中为需要过滤的文件

2.在doFilter方法中对过滤的文件进行操作

3.放行

filterChain.doFilter(servletRequest,servletResponse);

实例

对所有文件进行拦截,只放行login.jsp页面和requestLoginTest,若登录成功后,可以访问所有文件

// requestLoginTest
@WebServlet("/requestLoginTest")
public class RequestLoginTest extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        HttpSession session = request.getSession();
        if (username.equals("zhangsan")) {
            if (password.equals("123456")) {
                // 新建session域对象,标志位判断是否登陆成功
                session.setAttribute("flag", true);
                // 若之前输入账号密码出现错误,会出现提示,在登录成功后删除提示
                session.removeAttribute("name");
                session.removeAttribute("pass");
                // 登陆成功,重定向到登陆成功页面
                response.sendRedirect("/successful.jsp");
            } else {
                // 标志位判断没有登录成功过,在过滤器中就不会放行
                session.setAttribute("flag", false);
                // 域对象,用于显示在login.jsp界面提示用户
                session.setAttribute("pass","密码错误");
                // 当密码错误时,会删除账号不存在的提示,而出现密码错误的提示
                session.removeAttribute("name");
                response.sendRedirect("/login.jsp");
            }
        } else {
            session.setAttribute("flag", false);
            session.setAttribute("name","账号不存在");
            session.removeAttribute("pass");
            response.sendRedirect("/login.jsp");
        }
    }
}
// 过滤器
@WebFilter("/*")// 可以对所有文件进行过滤
public class FilterTest implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
        // 放行与登录相关的页面
        if (httpServletRequest.getRequestURI().equals("/login.jsp") || httpServletRequest.getRequestURI().equals("/requestLoginTest")) {
            filterChain.doFilter(httpServletRequest,httpServletResponse);
        } else {
            // 与登录不相关时,进行判断,是否成功登陆过
            Object flag = httpServletRequest.getSession().getAttribute("flag");
            if (flag == null) {
                httpServletResponse.sendRedirect("/login.jsp");
            } else {
                // 不为空时,判断标志位
                Boolean Tflag = (Boolean) flag;
                // 如果标志位为true,说明成功登陆过,放行
                if (Tflag) {
                    filterChain.doFilter(httpServletRequest,httpServletResponse);
                } else {
                    httpServletResponse.sendRedirect("/login.jsp");
                }
            }
        }
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}

JSP

java server pages

jsp脚本

用于嵌入java代码使用的脚本

1.该脚本放置在该jsp被编译后的servlet类中的service方法中

<%
    System.out.println("hello");
    int a = 5;
%>

2.该脚本用于输出到页面上

<%=
    a
%>

3.该脚本作为全局变量来使用,放在类体里面

<%!
    int b = 5;
%>

jsp指令

用于配置技术jsp页面使用的

指令格式:<%@ %>

1.page指令

其中errorPage和isErrorPage(发生错误的页面通过errorPage绑定跳转路径,被调用的错误页面通过isErrorPage绑定为true,实现两者的跳转)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

2.include指令

用于导入页面资源,让别的页面能显示到该页面,可在body中引入

<%@ include file="/successful.jsp"%>

3.taglib指令

用于导入资源,相当于java导包

<%@ taglib prefix="c" uri="" %>

jsp内置对象

pageContext

session

request

application(servletContext)

<--不需要创建,直接调用-->
pageContext.setAttribute("username","zhangsan");

MVC

model:模型层

view:视图层

controller:控制层

El表达式

格式:${表达式}

<%
    pageContext.setAttribute("username","zhangsan");
    request.setAttribute("username","lisi");
    session.setAttribute("username","wangwu");
    application.setAttribute("username","zhaoliu");
%>
${pageScope.username}
${requestScope.username}
${sessionScope.username}
${applicationScope.username}
<--当没有域名时,默认从作用域最小的域开始查找数据-->
${username}
<--算术运算符,逻辑运算符-->
${1>1}

JSTL

1.首先在web包下创建lib包,导入jstl的jar包

创建lib包,导入jar包,点击Add as library,打开Project Structure中的Problems,解决后可以使用

2.在jsp页面中引入

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

3.常用标签

<body>
<%
    request.setAttribute("ifMarried", true);

    Calendar instance = Calendar.getInstance();
    int i = instance.get(Calendar.DAY_OF_WEEK);
    request.setAttribute("weekDay",i-1);

    ArrayList<String> strings = new ArrayList<>();
    strings.add("zhangsan");
    strings.add("lisi");
    request.setAttribute("items",strings);
%>
<%--c:if    里面的test属性必有,值为boolean值,true为显示里面内容,false不显示,一般配合el表达式使用--%>
<c:if test="${ifMarried}">
    xxx结婚了
</c:if>
<c:if test="${!ifMarried}">
    xxx没有结婚了
</c:if>

<%--c:choose    相当于java中的switch语句,一般配合c:when来使用--%>
<c:choose>
    <c:when test="${weekDay==1}">星期一</c:when>
    <c:when test="${weekDay==2}">星期二</c:when>
    <c:when test="${weekDay==3}">星期三</c:when>
    <c:when test="${weekDay==4}">星期四</c:when>
    <c:when test="${weekDay==5}">星期五</c:when>
</c:choose>

<%--c:forEach   相当与 for(int a = 1;a<10;a+=2){System.out.println(a);}--%>
<c:forEach var="a" begin="1" end="10" step="2">
    ${a}
</c:forEach>
<%--items内可以放置集合等可以遍历的容器,varStatus表示循环变量的状态--%>
<c:forEach items="${items}" var="a" varStatus="b">
    ${a}---------${b.index}
</c:forEach>
</body>

JSON

java script object notation js对象的表示法,用来做网络中传输的一种格式,简洁,明了,不冗余,本质就是一串字符串

<script>
    // JSON对象
    // 值为可以为字符串,数字,布尔值,null,js对象,js数组
    let user = {
        "name":"zhangsan",
        "age":18
    }
    // 转换成JSON字符串
    let s = JSON.stringify(user);
    alert(s);
    // 取值 对象.键名
    console.log(user.name);
    //遍历
    let school = ["清华","北大","西南石油"];
    for (let i = 0; i < school.length; i++) {//fori
        console.log(school[i]);
    }
    for (let x of school) {//forof
        console.log(x);
    }
    for (const x in school) {//forin
        console.log(school[x]);
    }
</script>

java对象-->js对象

// 转换出来为一个js对象的json表达式
User user = new User();
user.setAge(15);
user.setName("moon");
System.out.println(user);
// 将java对象转换成js对象的方法
ObjectMapper objectMapper = new ObjectMapper();
System.out.println(objectMapper.writeValueAsString(user1));

//list转换为一个js数组
ArrayList<String> strings = new ArrayList<>();
strings.add("aaa");
strings.add("bbb");
strings.add("ccc");
ObjectMapper objectMapper = new ObjectMapper();
System.out.println(objectMapper.writeValueAsString(strings));

//转换出来为一个对象数组
User user1 = new User();
ArrayList<User> users = new ArrayList<>();
users.add(user);
users.add(user1);
ObjectMapper objectMapper = new ObjectMapper();
System.out.println(objectMapper.writeValueAsString(users));

//map转换出来为一个js对象
Map<String,String> map = new HashMap();
map.put("name","zhangsan");
map.put("age","zhangsan");
ObjectMapper objectMapper = new ObjectMapper();
System.out.println(objectMapper.writeValueAsString(map));

Ajax

优点:异步,局部刷新

同步:浏览器对服务器发送请求,在等待服务器响应的过程中,什么都不能做

异步:浏览器不需要等待服务器响应,在等待服务器响应的过程中,可以做任何事

ajax使用

1.创建jsp页面,并引入jquery(在web目录下新建static目录,并将jquery放在该目录下)

2.页面中添加事件,在事件函数中使用ajax

<body>
<span>用户名:</span><input id="username" type="text" οnblur="userNameJudge()"><span id="usernameJudge"></span><br>
<span>密码:</span><input id="password" type="password"><br>
<button type="button" οnclick="login()">登录</button>
<script>
    // 用于登录对账号密码的判断
    function login() {
        var username = $("#username").val();
        var password = $("#password").val();
        $.ajax({
            // 请求的url(旅行的目的地)
            url:"/ajaxServlet",
            // 请的方式(出行方式)
            type:"post",
            // 请求携带的参数(同行人)
            data:{
                "username":username,
                "password":password
            },
            // 返回时参数的格式
            dataType:"json",
            // 成功回调后执行的函数
            // rs接收后端传送的数据,即response.getWriter().write(string);
            success:function (rs) {
                if (rs.code == 200) {
                    alert(rs.msg)
                    // 账号密码正确,跳转页面
                    location.href="/successful.jsp"
                } else {
                    alert(rs.msg)
                }
            }
        })
    }

    // 用于对用户名是否可用判断
    function userNameJudge() {
        var username = $("#username").val();
        $.ajax({
            url:"/usernameJudge",
            type:"post",
            data:{
                "username":username,
            },
            dataType:"json",
            success:function (rs) {
                if (rs.code == 200) {
                    // 新增样式
                    $("#usernameJudge").css({'color':'green'});
                    // 新增内容
                    $("#usernameJudge").html(rs.msg);
                } else {
                    $("#usernameJudge").css({'color':'red'});
                    $("#usernameJudge").html(rs.msg);
                }
            }
        })
    }
</script>
</body>
// 账号密码判断的servlet
@WebServlet("/ajaxServlet")
public class AjaxServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        ResultInfo resultInfo;
        if ("zhangsan".equals(username)) {
            if ("123456".equals(password)) {
                // 密码正确,封装信息
                resultInfo = new ResultInfo(200,"登录成功",null);
            } else {
                resultInfo = new ResultInfo(500,"密码错误",null);
            }
        } else {
            resultInfo = new ResultInfo(500,"账号不存在",null);
        }
        // 将封装好的信息通过json格式传递给前端
        ObjectMapper objectMapper = new ObjectMapper();
        String string = objectMapper.writeValueAsString(resultInfo);
        response.getWriter().write(string);
    }
}
// 新建一个结果类ResultInfo
public class ResultInfo {
    // 自己定义的状态码
    private Integer code;
    // 响应信息
    private String msg;
    // 响应的数据
    private Object data;
    
    (有参无参构造方法)
    (get和set方法)
    (toString方法)
}

Maven

概念

Maven是一个项目管理工具,它包含了一个对象模型。一组标准集合,一个依赖管理系统。和用来运行定义在生命周期阶段中插件目标和逻辑。

核心功能

Maven的核心功能是合理叙述项目间的依赖关系,通俗点就是通过pom.xml文件的配置获取jar包不用手动的去添加jar包

Maven坐标

  • groupId:Maven项目隶属的实际项目

  • artifactld:当前项目的模块名称

  • version:当前模块的版本

仓库

当maven项目需要jar包时,第一时间寻找本地仓库中的jar包,当本地仓库没有需要的jar包时,就会在中央仓库寻找,但当配置了私服时,会优先前往私服寻找,私服中没有,才会去中央仓库中寻找

maven项目结构

lifeCycle插件

1.clean

用于清除之前构建生成的所有文件

其中具体为清除Target目录中的所有文件,包括该目录

删除了install生成的所有文件

2.compile

编译项目的源代码,主要是java文件

一般是编译scr/main/java或是scr/test/java里面的文件

3.deploy

复制最终的包至远程仓库

共享给其它开发人员和项目

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值