目录

  • MVC
    • 网页获取动态资源逻辑
    • 定义
      • 举个
    • 优缺点
    • 参考博客
  • 三层架构
    • 举个
    • 优缺点
    • MVC和三层架构的区别
    • 参考博客
  • Servlet
    • 工作模式
    • Servlet的开发流程
      • web.xml配置servlet
      • @注解配置servlet
    • 映射路径通配符
    • Servlet的生命周期
    • ServletConfig接口
    • HttpServlet抽象类
      • 为什么?
        • GenericServlet抽象类
      • 回到HttpServlet
          • service(HttpServletRequest, HttpServletResponse)自定义方法,根据请求的方式去调用不同的方法
      • 为什么定义成抽象类?
    • Servlet中四个重要的对象
    • 转发和重定向
      • 转发
      • 重定向
      • 转发和重定向的区别
    • 一个Servlet小demo
    • 小结
    • 参考博客

MVC

MVC(Model View Controller)是软件工程中的一种软件架构模式,它把软件系统分为模型视图控制器三个基本部分。以一种业务逻辑、界面显示、数据分离的方式组织代码,将业务逻辑聚集到一个部件里面(模型),在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。

网页获取动态资源逻辑

  1. 网页界面
  2. 请求转发
  3. 接收请求
  4. 处理请求
  5. 返回数据

定义

  • M:Model,模型。
    • 完成具体的业务操作,如:查询数据库,封装对象
  • V:view视图。JSP、HTML等来进行数据展示
  • C:Controller控制器。 Servlet
    • 获取View的请求
    • 调用模型将数据交给视图进行展示

举个

控制器Controller 的作用就是将ModelView一一对应起来

优缺点

【优点】

  1. 耦合性低,方便维护,可以利于分工协作
  2. 重用性高

【缺点】

  1. 使得项目架构变得复杂,对开发人员要求高

参考博客

MVC与三层架构理解

三层架构

通常意义上的三层架构就是将整个业务应用划分为:界面层[表示层] UI(User Interface layer)、业务逻辑层BLL(Business Logic Layer)、数据访问层DAL(Data access layer)。

区分层次的目的是为了“高内聚低耦合” 的思想

举个

任何一层发生变化都不会影响到另外一层!!!

优缺点

【优点】

  1. 开发人员可以只关注整个结构中的其中某一层;
  2. 可维护性高,可扩展性高
  3. 可以降低层与层之间的依赖;
  4. 有利于标准化;
  5. 利于各层逻辑的复用

【缺点】

  1. 降低了系统的性能。如果不采用分层式结构,很多业务可以直接造访数据库,以此获取相应的数据,如今却必须通过中间层来完成
  2. 有时会导致级联的修改,这种修改尤其体现在自上而下的方向。如果在表示层中需要增加一个功能,为保证其设计符合分层式结构,可能需要在相应的业务逻辑层和数据访问层中都增加相应的代码
  3. 增加了开发成本

MVC和三层架构的区别

参考博客

MVC与三层架构理解

Servlet

是用Java编写的服务器端程序。其主要功能在于交互式地浏览和修改数据,生成动态Web内容。

工作模式

  • 客户端发送请求至服务器
  • 服务器启动并调用Servlet,Servlet根据客户端请求生成响应内容并将其传给服务器
  • 服务器将响应返回客户端

在mvc架构中,servlet在其中承担的作用是controller,控制器。

控制器作用:

  • 获取View的请求
  • 调用模型(M)将数据交给视图(V)进行展示

web应用是基于http协议的,http协议有请求报文(request)和响应报文(request),请求报文就是浏览器向服务器发送的数据形成的数据对象,同理,响应报文就是服务器向浏览器发送的数据形成的信息,而http协议有两个重要的方法,一个是POST,一个是GET,这两个方法就是向浏览器发送请求的方法。

servlet能够读取请求报文的内容,并对报文进行处理。

Servlet的开发流程

狭义上讲,servlet是java语言实现的一个类,所以我们就要根据这个类进行相应的扩展开发。

具体流程如下:

  1. 编写一个java类,继承HttpServlet类(需要导入servlet-api.jar
  2. 重写HttpServlet类的doGet方法和doPost方法
  3. 配置web.xml文件,或者使用注解对servlet进行配置

web.xml配置servlet

配置格式示例

<webapp>    <servlet>    <servlet-name>MyServlet</servlet-name>    <servlet-class>cn.roobtyan.servlet.FirstServlet</servlet-class>  <init-param>            <param-name>first</param-name>            <param-value>第一个初始化参数</param-value>        </init-param>        <init-param>            <param-name>second</param-name>            <param-value>第二个初始化参数</param-value>        </init-param>        <load-on-startup>0</load-on-startup>  </servlet>      <servlet-mapping>    <servlet-name>MyServlet</servlet-name>    <url-pattern>/first</url-pattern>  </servlet-mapping></webapp>

访问/first的时候,服务器会把请求交给MyServlet进行处理。

标记容器何时加载servlet(实例化并调用init()方法)
为负值或者没有配置 ,则容器会当Servlet被请求时加载
为正整数或者0,则容器在应用启动时就加载并初始化
值越小,servlet的优先级越高,就越先被加载。值相同时,容器就会自己选择顺序来加载。

@注解配置servlet

@WebServlet(name = "LoginServlet",urlPatterns = {"/login"})public class LoginServlet extends HttpServlet {

映射路径通配符

/*#任意路径都映射到这个servlet/bluemson/*#/bluemsun下的任意路径映射到该servlet

url要么以/开头,要么以*开头,其他的都是非法的

Servlet的生命周期

一般来讲,servlet只会初始化一次,也就是整个过程中只存在一个servlet对象,即便是有多次访问,依然只有一个对象,这个对象是可以复用的。

所以servlet是单实例多线程的。

Servlet接口

public interface Servlet {    void init(ServletConfig var1) throws ServletException; //获得ServletConfig    ServletConfig getServletConfig();    void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;     String getServletInfo();     void destroy();}

其中init(),service(),destroy()比较关键,体现了Servlet的生命周期。

  • init方法只会调用一次,只是在创建servlet实例的时候才会创建

  • service方法,是进行数据处理的,只要接受了一次请求,就会被调用一次

  • destroy方法,销毁servlet对象的时候调用。停止服务器或者重新部署web应用时销毁servlet对象,同样也是调用一次

ServletConfig接口

public interface ServletConfig {  //返回当前servlet的名字    String getServletName();//返回ServletContext(web应用的上下文)  //每个web应用对应一个ServletContext,定义了servlet用来与servlet容器通信的多种方法    ServletContext getServletContext();//可以根据名字来获取servlet的初始化参数    String getInitParameter(String var1);//获取出初始化参数的参数名    Enumeration<String> getInitParameterNames();}

HttpServlet抽象类

虽然是抽象类但是没有抽象方法!

为什么?

每次要新建一个servlet都要实现Servlet接口,重写这好几个方法太麻烦啦!于是GenericServlet抽象类出现了。

GenericServlet抽象类

该类实现了Servlet, ServletConfig两个接口并重写了方法。

//只有一个抽象方法在继承GenericServlet时要实现public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

注意这里有两个重载的init()方法

  • init(ServletConfig)是 GenericServlet 抽象类实现 servlet接口要实现的init方法,实现了原来Servlet的功能
  • init()是GenericServlet 抽象了自己新添加的init方法,目的是让继承该抽象类的servlet被加载并初始化时可以自己做些自定义的初始化

这时,如果我们继承GenericServlet 抽象类再写servlet已经简单多了。而继承了它的HttpServlet更加简单。

回到HttpServlet

该抽象类继承了GenericServlet 抽象类,并且重写了GenericServlet 中唯一的抽象方法service(ServletRequest,ServletRespone)方法

其中重点看两个重载的service方法

  • service(ServletRequest , ServletResponse)

    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {  //下转型为HttpServletRequest(ServletRequest子接口)        HttpServletRequest request;  //下转型为HttpServletRespone(ServletRespone子接口)        HttpServletResponse response;        try {            request = (HttpServletRequest)req;            response = (HttpServletResponse)res;        } catch (ClassCastException var6) {            throw new ServletException(lStrings.getString("http.non_http"));        }//调用自定义的service方法        this.service(request, response);    }

    由于我们的请求都是http请求,所以把ServletRequest请求下转型为HttpServletRequest,ServletRespone请求下转型为HttpServletRespone,以获取更多关于请求的信息(如请求方式等),并调用自定义的service方法

  • service(HttpServletRequest, HttpServletResponse)自定义方法,根据请求的方式去调用不同的方法

当我们新建servlet的时候只需要继承HttpServlet,然后根据请求方式重写对应的doXXX()方法就行了

为什么定义成抽象类?

防止直接创建对象!单纯的HttpServlet对象时不能处理任何业务逻辑的,里边方法没有功能,需要继承它我们重写它的方法!

Servlet中四个重要的对象

HttpServletRequest  请求对象:获取请求信息HttpServletResponse 响应对象: 设置响应对象ServletConfig对象    servlet配置对象ServletContext对象  servlet的上下文对象

对应关系:Servlet与JSP九大内置对象的对应关系

这些上节课学姐的博客里也写的很详细了

蓝旭第四次培训——JSP

转发和重定向

转发

request.getRequestDispatcher("loginfal.jsp").forward(req,resp);

重定向

与转发功能相似的是重定向,重定向的使用是这样的:

response.sendRedirect("loginfal.jsp");

这样也会访问到loginfal.jsp这个页面。

转发和重定向的区别

虽然二者最终实现的功能是相同的.但是还是有很大不同的.不同之处如下:

  1. 地址栏变化
    转发不会改变地址栏中的URL,而重定向则会改变
  2. 跳转范围
    转发只能访问到当前web应用中的内容,而重定向则可以访问到任意web应用中的内容
  3. request对象作用范围
    转发后,在转发后的页面中仍然可以使用原来的request对象,而重定向,原来的request对象则失去作用.

所以,如果想要在多个页面使用相同的request对象,那么只能使用转发,而不能使用重定向。

一个Servlet小demo

register.jsp

<html><head>    <title>注册界面</title></head><body><form action="/register" method="get">    账号:<input type="text" name="name">    <br>    密码:<input type="password" name="password">    <br>    <input type="submit" value="注册"></form></body></html>

Register.java

import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.io.IOException;public class Register extends HttpServlet {    @Override    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        String name = req.getParameter("name");        String password = req.getParameter("password");        HttpSession session = req.getSession();        User user = new User();        user.setName(name);        user.setPassword(password);        session.setAttribute("user",user);//        req.getRequestDispatcher("registersuc.jsp").forward(req,resp);        //设置响应的编码格式为UTF-8编码,否则发生中文乱码现象        resp.setContentType("text/html;charset=UTF-8");        //1.获得请求方式        String method = req.getMethod();        //2.获得请求的资源相关的内容        //获得请求URI        String requestURI = req.getRequestURI();        //获得应用路径(应用名称)        String webName = req.getContextPath();        //获得查询字符串        String querryString = req.getQueryString();        resp.getWriter().write("

下面是获得的字符串

"
); resp.getWriter().write("

method(HTTP方法):

"); resp.getWriter().write("

"+method+"


"
); resp.getWriter().write("

requestURi(请求URI):

"
); resp.getWriter().write("

" + requestURI + "


"
); resp.getWriter().write("

webname(应用名称):

"
); resp.getWriter().write("

" + webName + "


"
); resp.getWriter().write("

querrystring(查询字符串):

"
); resp.getWriter().write("

" + querryString + "

"
);// resp.sendRedirect("registersuc.jsp"); }}

web.xml

<servlet>        <servlet-name>regiter</servlet-name>        <servlet-class>Register</servlet-class>    </servlet>    <servlet-mapping>        <servlet-name>regiter</servlet-name>        <url-pattern>/register</url-pattern>    </servlet-mapping>

jsp界面:

注册后显示的结果:

小结

参考博客

Servlet详细教程

JavaWeb——Servlet(全网最详细教程包括Servlet源码分析)

servlet入门&MVC

理解HttpServlet抽象类没有抽象方法(从Servlet–GenericServlet–HttpServlet)

servlet官方文档