尚硅谷Java-web(全新技术栈,全程实战):Servlet技术

一、设置编码

Tomcat8之前,设置编码:
        1)get请求方式:

                 //get方式目前不需要设置编码(只针对于Tomcat8之前)
                // 如果是get请求发送的中文数据,转码稍微有点麻烦只针对于(Tomcat8之前)
                String fname = request.getParameter("fname");
                //1.将字符串打散成字节数组
                byte[] bytes = fname.getBytes("ISO-8859-1");
                //2.将字节数组按照设定的编码重新组装成为字符串
                fname = new String(bytes,"UTF-8");

这幅图片是是为了是我的文章看起来不是很单调^_^


                2)post请求方式:

                //post方式下,设置编码,防止中文乱码
                request.setCharacterEncoding("utf-8"); //设置request对象的解码方式

        Tomcat8开始,设置编码,只需针对与post方式
                   request.setCharacterEncoding("utf-8");
        注意:
                需要注意的是,设置编码值一句代码必须在所有获取参数动作之前

二、Servlet的关系继承

1) 继承关系
        javax.servlet.Servlet 接口
                javax.servlet.GenericServlet 抽象类
                        javax.servlet.http.HttpServlet 抽象子类

2)相关方法(三个重要方法)
        javax.servlet.Servlet 接口中三个重要的方法:
                void init(config) - 初始化方法
                void service(request,response) - 服务方法
                void destory() - 销毁方法

        javax.servlet.GenericServlet 抽象类中实现了初始化和销毁方法,没有实现服务方法:
                void service(request,response) - 仍然是抽象的

        

        javax.servlet.http.HttpServlet 抽象子类中实现了这个 service 服务方法:
                void service(request,response) - 不是抽象的,并且其中方法用的是 this.service() 表明实际执行的是子类中再重写的 service 服务方法


                1:String method = req.getMethod;获取请求的方法

 


                2:各种if判断,根据请求方式不同,决定去调用不同的do方法
                if (method.equals("GET")) {
                        ·····
                } else if (method.equals("HEAD")) {
                        ·····
                } else if (method.equals("POST")) {
                        ·····
                } ·····
                3:在HttpServlet这个抽象类中,do方法都差不多:
                protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws                     ServletException, IOException {
                        String msg = lStrings.getString("http.method_get_not_supported");
                        this.sendMethodNotAllowed(req, resp, msg);
                }
                private void sendMethodNotAllowed(HttpServletRequest req, HttpServletResponse                      resp, String msg) throws IOException {
                        String protocol = req.getProtocol();
                        if (protocol.length() != 0 && !protocol.endsWith("0.9") &&                                                        !protocol.endsWith("1.0")) {
                                resp.sendError(405, msg);
                        } else {
                                resp.sendError(400, msg);
                        }
                }

3)小结:
        1.继承关系: HttpServlet -> GenericServlet -> Servlet
        2.Servlet中的核心方法: init() , service() , destroy()
        3.服务方法: 当有请求过来时,service方法会自动响应(其实是 tomcat 容器调用的)
                在 HttpServlet 中我们会去分析请求的方式:到底是 get、post、head 还是delete 等等
                然后再决定调用的是哪个 do 开头的方法
                那么在 HttpServlet 中这些 do 方法默认都是 405 的实现风格,要我们子类去实现对应的             方法,否则默认会报405错误
          4.因此,我们在新建 Servlet 时,我们会去考虑请求方法,从而决定重写哪个 do 方法

三、Servlet的生命周期

        1)生命周期:

                从出生到死亡的过程就是生命周期。对应 Servlet 中的三个方法:init(), service(), destroy()


        2)默认情况下:

                第一次接收请求时出生,这个 Servlet 会进行实例化(调用构造方法)、初始化(调用init())、然后服务(调用service())
                从第二次请求开始,每一次都只有服务,就没有实例化和初始化的过程了
                当容器关闭时,其中的所有的 servlet 实例会被销毁,调用销毁方法

public class Demo2servlet extends HttpServlet {

    public Demo2servlet() {
        System.out.println("正在实例化!!!");
    }

    @Override
    public void init() throws ServletException {
        System.out.println("正在初始化!!!");
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("正在服务!!!");
    }

    @Override
    public void destroy() {
        System.out.println("正在销毁!!!");
    }
}

        3)通过案例我们发现:

                — Servlet 实例 tomcat 只会创建一个,所有的请求都是这个实例去响应。
                — 默认情况下,第一次请求时,tomcat 才会去实例化,初始化,然后再服务,这样的好处是什么: 提高系统的启动速度,只有创建对象,就是说有请求,才创建 servlet 对象。这样的缺点是什么: 第一次请求时,耗时较长

                — 因此得出结论:

                        如果需要提高系统的启动速度,当前默认情况就是这样。
                        如果需要提高响应速度,我们应该设置 Servlet 的初始化时机。

        4)Servlet 的初始化时机:

                默认是第一次接收请求时,实例化,初始化
                我们可以通过修改 web.xml 文件中 Servlet 的 <load-on-startup> 标签来设置 servlet 启动的先后顺序,数字越小,启动越靠前,最小值0

修改配置文件:

<servlet>
        <servlet-name>Demo2servlet</servlet-name>
        <servlet-class>servlets.Demo2servlet</servlet-class>
        <load-on-startup>1</load-on-startup>
</servlet>

        5)Servlet 在容器中是:单例的、多线程情况下是线程不安全的

                1:单例:

                        所有的请求都是同一个实例去响应
                2:线程不安全:
                       一个线程需要根据这个实例中的某个成员变量值去做逻辑判断。但是在中间某个时机,另一个线程改变了这个成员变量的值,从而导致第一个线程的执行路径发生了变化

               3: 我们已经知道了servlet是线程不安全的,给我们的启发是:尽量的不要在 servlet 中定义成员变量。如果不得不定义成员变量,那么不要去:①不要去修改成员变量的值;②不要去根据成员变量的值做一些逻辑判断。

四、HTML协议

        1)HTTP 称之为 超文本传输协议。
        2)Http是无状态的

       3)Htpp请求响应包含两个部分:请求和响应


                - 请求:


            请求包含三个部分: 1.请求行 ; 2.请求消息头 ; 3.请求主体
                1:请求行包含是三个信息: 1. 请求的方式 ; 2.请求的URL(资源地址);3.请求的协议版本(一般都是 HTTP1.1)


                2:请求消息头中包含了很多客户端需要告诉服务器的信息,比如:我的浏览器型号、版本、我能接收的内容的类型、我给你发的内容的类型、内容的长度等等


                        3:请求体,三种情况

                                get 方式,没有请求体,但是有一个 queryString
                                post 方式,有请求体,form data
                                json 格式,有请求体,request payload


                - 响应:


                响应也包含三个部分: 1. 响应行 ; 2.响应头 ; 3.响应体
                1:响应行包含三个信息:1.协议版本;2.响应状态码(200);3.响应状态(ok)
                2:响应头:包含了服务器的信息;服务器发送给浏览器的信息(内容的媒体类型、编码、内容长度等)
                3:响应体:响应的实际内容(比如请求 add.html 页面时,响应的内容就是<html><head><body><form…)

五、会话

1)Http 是无状态的
  • HTTP 无状态 :服务器无法判断这两次请求是同一个客户端发过来的,还是不同的客户端发过来的
  • 无状态带来的现实问题:第一次请求是添加商品到购物车,第二次请求是结账;如果这两次请求服务器无法区分是同一个用户的,那么就会导致混乱
  • 通过会话跟踪技术来解决无状态的问题。

2)会话跟踪技术
  • 客户端第一次发请求给服务器,服务器获取 session,获取不到,则创建新的,然后响应给客户端
  • 下次客户端给服务器发请求时,会把 sessionID 带给服务器,那么服务器就能获取到了,那么服务器就判断这一次请求和上次某次请求是同一个客户端,从而能够区分开客户端
  • 常用的API
  1. 1创建会话的 API:

        request.getSession() -> 获取当前的会话,没有则创建一个新的会话
        request.getSession(true) -> 效果和不带参数相同
        request.getSession(false) -> 获取当前会话,没有则返回 null,不会创建新的

  1. 2其他常用 API:

        session.getId() -> 获取 sessionID
        session.isNew() -> 判断当前 session 是否是新的
        session.getMaxInactiveInterval() -> session 的非激活间隔时长,默认1800秒
        session.invalidate() -> 强制性让会话立即失效

3)session 保存作用域:
  • session 保存作用域是和具体的某一个 session 对应
  • 常用的API:

        void session.setAttribute(k,v)
        Object session.getAttribute(k)
        void removeAttribute(k)

六、服务器内部转发以及客户端重定向

     1)服务器内部转发:request.getRequestDispatcher("...").forward(request,response);
  • 一次请求响应的过程,对于客户端而言,内部经过了多少次转发,客户端是不知道的
  • 地址栏没有变化
2)客户端重定向:response.sendRedirect("....");
  • 两次请求响应的过程。客户端肯定知道,请求的 URL 有变化
  • 地址栏有变化

七、thymeleaf

1)添加thymeleaf的jar包

我给你们找好了:http://t.csdnimg.cn/mQaI5

2)新建一个Servlet类ViewBaseServlet
public class ViewBaseServlet extends HttpServlet {

    private TemplateEngine templateEngine;

    @Override
    public void init() throws ServletException {
        // 1.获取ServletContext对象
        ServletContext servletContext = this.getServletContext();
        // 2.创建Thymeleaf解析器对象
        ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);
        // 3.给解析器对象设置参数
        // ①HTML是默认模式,明确设置是为了代码更容易理解
        templateResolver.setTemplateMode(TemplateMode.HTML);
        // ②设置前缀
        String viewPrefix = servletContext.getInitParameter("view-prefix");
        templateResolver.setPrefix(viewPrefix);
        // ③设置后缀
        String viewSuffix = servletContext.getInitParameter("view-suffix");
        templateResolver.setSuffix(viewSuffix);
        // ④设置缓存过期时间(毫秒)
        templateResolver.setCacheTTLMs(60000L);
        // ⑤设置是否缓存
        templateResolver.setCacheable(true);
        // ⑥设置服务器端编码方式
        templateResolver.setCharacterEncoding("utf-8");
        // 4.创建模板引擎对象
        templateEngine = new TemplateEngine();
        // 5.给模板引擎对象设置模板解析器
        templateEngine.setTemplateResolver(templateResolver);
    }

    protected void processTemplate(String templateName, HttpServletRequest req, HttpServletResponse resp) throws IOException {
        // 1.设置响应体内容类型和字符集
        resp.setContentType("text/html;charset=UTF-8");
        // 2.创建WebContext对象
        WebContext webContext = new WebContext(req, resp, getServletContext());
        // 3.处理模板数据
        templateEngine.process(templateName, webContext, resp.getWriter());
    }
}
3)在web.xml文件中添加配置
  • 配置前缀 view-prefix
  • -配置后缀 view-suffix
        <context-param>
            <param-name>view-prefix</param-name>
            <param-value>/</param-value>
        </context-param>
        <context-param>
            <param-name>view-suffix</param-name>
            <param-value>.html</param-value>
        </context-param>

4)使得我们的Servlet继承ViewBaseServlet
5)根据逻辑视图名称 得到 物理视图名称

//此处的视图名称是 index
//那么thymeleaf会将这个 逻辑视图名称 对应到 物理视图 名称上去
//逻辑视图名称: index
//物理视图名称: view-prefix + 逻辑视图名称 + view-suffix
//所以真实的视图名称是 : [ / index .html
super.processTemplate("index",request,response);

八、结尾

给大家分享一下自己的笔记,因我最近要应付其它的考试,所以只写了一部分给大家,希望对大家有帮助!

有大佬想要帮我补充一下可以分享到评论中!!

  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
java.lang.IllegalStateException: Optional int parameter 'id' is present but cannot be translated into a null value due to being declared as a primitive type. Consider declaring it as object wrapper for the corresponding primitive type. at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.handleNullValue(AbstractNamedValueMethodArgumentResolver.java:263) ~[spring-web-5.3.24.jar:5.3.24] at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:116) ~[spring-web-5.3.24.jar:5.3.24] at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:122) ~[spring-web-5.3.24.jar:5.3.24] at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:179) ~[spring-web-5.3.24.jar:5.3.24] at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:146) ~[spring-web-5.3.24.jar:5.3.24] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.24.jar:5.3.24] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.24.jar:5.3.24] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.24.jar:5.3.24] at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.24.jar:5.3.24] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1071) ~[spring-webmvc-5.3.24.jar:5.3.24] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:964) ~[spring-webmvc-5.3.24.jar:5.3.24] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.24.jar:5.3.24] at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.24.jar:5.3.24]
07-23

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值