关于利用maven搭建ssm的博客,我们一起来探讨下问的最多的问题

  • 时间:
  • 浏览:2

前言

  开心一刻

    有个同学去非洲援建,刚到工地接待他的施工员是个黑人,他就用英语跟人家交流,黑人没做声。 何如让 他又用法语,黑人还是没说话。 何如让 他用手去比划。黑人终于开口了:瞎比划嘎哈,整个工地都中国人

前提背景

  在利用maven/eclipse搭建ssm(spring+spring mvc+mybatis)一文的问题报告 反馈中,大体分另一个 :404和页面无数据;至于10000,此人 认为比较好出理 ,按照提示进行出理 就好,本文就不讨论10000了

  404

    主要也是这一

    1、webapp未发布

      相关资源未部署,类似webapp未发布部署,类似如下

      不本来 webapp,main下的java、resources、webapp,maven依赖一定会时需部署到tomcat,不然就不详细,就会指在各种各样的少内容的问题报告 ;

    2、请求URL不对

      这一不言而喻是好多好多 新入行的小伙伴容易老出 的问题报告

      肯能工程正常部署,请求URL老出 404,很有肯能那个她 们请求的URL不对;我们歌词 歌词 我们歌词 我们歌词 到tomcat的home目录下看看工程算是正常部署,类似如下

      还能都都可不可以 看看工程发布的内容(问题报告 1中时需发布的内容)算是一定会;肯能工程部署正常,而请求的URL又老出 404,那不用想,就那个她 的URL写错了

    404的出理 方案本来 :确认工程算是正确部署到tomcat,确认请求的URL算是正确,基本假如确认这两点也就能找到问题报告 了;后文不用再详细的讲404,我们歌词 歌词 我们歌词 我们歌词 将重点倒入下面这一问题报告 上

  页面无数据

    具体的问题报告 应该是本来 的:我们歌词 歌词 我们歌词 我们歌词 歌词 请求:http://localhost:端口/工程名/personController/showPerson时,数据正常显示如下

    我们歌词 歌词 我们歌词 我们歌词 歌词 直接请求jsp时,越来越title越来越数据,如下

    这是为哪几种?

    对于这一问题报告 一后后结束不言而喻没太在意,本来 提示小伙伴去看servlet的四大作用域和jsp的九大内置对象,上方陆陆续续好多好多 小伙伴都问了我,包括评论区留言、站内消息、QQ私聊等

    站内信

    评论区

    QQ

    我发现这一问题报告 好像一定会个别小伙伴的问题报告 ,好多好多 新入门的小伙伴都指在本来 的问题报告 ,下面我们歌词 歌词 我们歌词 我们歌词 就对此次问题报告 就行另一个 详细的探究;后续篇幅较长,基础铺垫较多,希望我们歌词 歌词 我们歌词 我们歌词 耐心看多

问题报告 探究

  servlet与servlet容器

    狭义上来讲,servlet指的本来 接口:javax.servlet.Servlet,广义上来讲,servlet指的是servlet规范:Java Servlet API 标准;javax.servlet.Servlet与servlet容器一定会servlet规范下的产物。Java Servlet API是Servlet容器和Servlet之间的接口,它定义了Servlet的各种方式,还定义了Servlet容器传送给Servlet的对象类,其中最重要的是请求对象ServletRequest和响应对象ServletResponseo这另一个 对象一定会由Servlet容器在客户端调用Servlet时产生的,Servlet容器把客户请求信息封塞进ServletRequest对象中,何如让 把这另一个 对象都传送给要调用的Servlet,Servlet出理 后后把响应结果写入ServletResponse,何如让 由Servlet容器把响应结果发送到客户端。

    Servlet与Servlet容器的关系不为啥像枪和子弹的关系,枪是为子弹而生,而子弹又让枪有了杀伤力。不言而喻它们是彼此依存的,何如让 又相互独立发展,这一切一定会为了适应工业化生产的结果。从技术深层来说是为了解耦,通过标准化接口来合作协议协议方式。Servlet 容器作为另一个 独立发展的标准化产品,目前它的种类好多好多 ,包括Jetty、tomcat、resin、JBoss、WebSphere、Weblogic等,哪几种一定会性性成长期期期的产品,有专门的公司肯能组织进行维护,我们歌词 歌词 我们歌词 我们歌词 直接拿来用就好。

    我们歌词 歌词 我们歌词 我们歌词 约定下,下文中的servet指的一定会servlet接口:javax.servlet.Servlet,servlet容器指的是:Tomcat,Web服务器与Servlet容器是同另一个 内容(实际是有区别的,具体区别我们歌词 歌词 我们歌词 我们歌词 自行去查阅)

    Tomcat容器模型如下

    Tomcat响应客户请求过程

      其中,①处表示Web服务器接收到客户端发出的HTTP请求后,转发给Servlet容器,再由Servlet容器转发给具体的Servlet实例进行请求的出理 ;②处表示Servlet实例将出理 结果封倒入ServletResponse中,再由Servlet容器把ServletResponse发给Web服务器,通知Web服务器以HTTP响应的方式把结果发送到客户端。也本来 说,与客户端直接打交道的是tomcat(servlet容器),而一定会我们歌词 歌词 我们歌词 我们歌词 的Servlet实例,而真正出理 请求的才那个她 们的Servlet实例。

    说的简单点,我们歌词 歌词 我们歌词 我们歌词 自定义的Servlet,不言而喻是对servlet容器在业务层面的拓展,合适业务定制一样;我们歌词 歌词 我们歌词 我们歌词 能都都可不可以 本来 理解,servlet容器对servlet提供技术支持,而servlet对servlet容器提供业务拓展,两者缺一不可,缺了技术支持,业务拓展实施不起来,缺了业务拓展,技术支持越来越现实意义。Servlet容器封装了底层比较复杂的技术实现,使我们歌词 歌词 我们歌词 我们歌词 能都都可不可以 专注于业务实现,而Servlet容器与业务实现之间的纽带本来 Servlet接口,它那个她 们对Servlet容器进行业务拓展的标准,好多好多 我们歌词 歌词 我们歌词 我们歌词 的业务时需实现Servlet接口。套用阿基米德的杠杆原理:给Servlet容器多个servlet实例,Servlet容器还你富有的web服务。

  JSP

    示例代码:our-servlet

    我们歌词 歌词 我们歌词 我们歌词 先来看看在jsp老出 后后,servlet何如输出页面,HelloServlet如下

    不仅仅是业务数据,还包括静态页面的内容,通通在servlet返回,肯能页面简单,越来越出理 都都可不可以 接受,何如让 肯能页面像淘宝、京东那样非常比较复杂,你能想象吗?太容易出错了,一旦静态页面的元素少了肯能多了内容,都他不知道何如排查,面对茫茫多的out.write,就越来越哭的份了。好多好多 jsp就应运而生了。

    JSP全称:Java Server Pages,允许在传统静态网页HTML中插入Java代码片段(Scriptlet)和JSP标签,以比较复杂页面静态内容的开发。但时需注意的是,JSP文件的本质还是Servlet,只不过与Servlet不同的是,JSP是专门用于进行数据展示的Servlet;JSP最终会被Tomcat解析成Servlet,在Tomcat内置了另一个 JSP解析引擎,当第一次访问该JSP页面时,解析引擎会将JSP页面解析成Servlet,何如让 再由Servlet将动态数据、静态内容详细输出到浏览器供展示。我们歌词 歌词 我们歌词 我们歌词 来看看jsp解析后的文件在哪里、内容是哪几种,以示例中的index.jsp为例。路径如下图

    index_jsp.java

/*
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/7.0.47
 * Generated at: 2019-04-08 13:14:31 UTC
 * Note: The last modified time of this file was set to
 *       the last modified time of the source file after
 *       generation to assist with modification tracking.
 */
package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;

public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {

  private static final javax.servlet.jsp.JspFactory _jspxFactory =
          javax.servlet.jsp.JspFactory.getDefaultFactory();

  private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;

  private javax.el.ExpressionFactory _el_expressionfactory;
  private org.apache.tomcat.InstanceManager _jsp_instancemanager;

  public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
    return _jspx_dependants;
  }

  public void _jspInit() {
    _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
    _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
  }

  public void _jspDestroy() {
  }

  public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
        throws java.io.IOException, javax.servlet.ServletException {

    final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session = null;
    final javax.servlet.ServletContext application;
    final javax.servlet.ServletConfig config;
    javax.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html; charset=utf-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
                  null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write("\n");
      out.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
      out.write("<html>\n");
      out.write("<head>\n");
      out.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n");
      out.write("<title>index</title>\n");
      out.write("</head>\n");
      out.write("<body>\n");
      out.write("    <div>\n");
      out.write("        Welcome, my friend!\n");
      out.write("    </div>\n");
      out.write("</body>\n");
      out.write("</html>");
    } catch (java.lang.Throwable t) {
      if (!(t instanceof javax.servlet.jsp.SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try { out.clearBuffer(); } catch (java.io.IOException e) {}
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
        else throw new ServletException(t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}
View Code

    发现熟悉的out.write又回来了,本来 此时的out.write一定会我们歌词 歌词 我们歌词 我们歌词 手动写的,本来 Tomcat解析jsp后生成的;肯能jsp没变动,jsp只会在第一次被调用时解析、编译一次,后续的请求一定会由编译后的servlet出理 ,我们歌词 歌词 我们歌词 我们歌词 来验证下,何如验证了? 不变index.jsp内容再请求index.jsp,看看上图中文件的修改时间会不用变

    发现文件的修改时间越来越变动,也本来 说上方的的结论:肯能jsp没变动,jsp只会在第一次被调用时解析、编译一次是对的。感兴趣的我们歌词 歌词 我们歌词 我们歌词 能都都可不可以 去看下Tomcat的源码,看看具体的实现细节。

    人们肯能会问:为哪几种不将jsp的内容直接返回给浏览器?我们歌词 歌词 我们歌词 我们歌词 要明白好多好多 :浏览器越来越解析html、css、js,除此之外的内容它解析不了,越来越我们歌词 歌词 我们歌词 我们歌词 能直接将jsp的内容返回给浏览器吗?好多好多 上方有出理 过程,最终由servlet将静态内容返回给浏览器。好多好多 爱问的小伙伴肯能又会问了:浏览器为哪几种越来越解析:html、css、js,这涉及到浏览器规范的问题报告 ,除非你有能力改变这一规范,让浏览器支持你我应该 的内容,这一问题报告 不做太少的讨论,我们歌词 歌词 我们歌词 我们歌词 姑且认为这是浏览器的限制,既然我们歌词 歌词 我们歌词 我们歌词 改变不了这一限制,那就适应这一限制。

  Servlet四大作用域与JSP九大内置对象

    Servlet四大作用域包括:page域、request域、session域、application域,作用域指的是变量的有效期限,具体如下

      当变量的作用域是page,它的有效范围只在当前jsp页面里有效;

      当变量的作用域是request,它的有效范围是当前请求周期,所谓请求周期,本来 指从http请求发起,到服务器出理 后后结束,返回响应的整个过程,在这一过程中肯能使用forward的方式跳转了多个jsp页面,在哪几种页面里你都能都都可不可以 使用这一变量;

      当变量的作用域是session,它的有效范围是当一定会话,何为当一定会话,本来 指从用户打开浏览器后后结束,到用户关闭浏览器的整个过程,这一过程肯能涵盖多个请求响应;

      当变量的作用域是application,它的有效范围是整个应用,何为整个应用,本来 指从应用启动,到应用后后结束;

    JSP九大内置对象包括:page、request 、response、pageContext、session、application、out、config、exception,内置对象指的是Servlet容器创建的一组对象,不需使用new关键字就能都都可不可以 直接使用的内置对象。

    四大作用域与九大内置对象对应关系如下

    更多详情时需我们歌词 歌词 我们歌词 我们歌词 此人 去查阅资料了

  EL表达式与JSTL标签

    我们歌词 歌词 我们歌词 我们歌词 知道jsp中能都都可不可以 插入Java代码片段,类似如下

<%pageContext.setAttribute("sex", "男"); %>  <!-- 设置值,作用域是当前jsp页面 -->
    <div>
        <%=pageContext.getAttribute("sex") %>   <!-- 注意去看解析后的el_jsp.java,被解析成了out.print(pageContext.getAttribute("sex") ); -->
         Welcome, my friend!
    </div>

    其中<% %>寄包裹 邮寄邮寄 的本来 java片段,<%= %>输出表达式值到页面;能都都可不可以 看多不够简洁,阅读性本来 太友好,好多好多 EL表达式就应运而生了,上述代码能都都可不可以 替加进去如下代码

<%pageContext.setAttribute("sex", "男"); %>  <!-- 设置值,作用域是当前jsp页面 -->
<div>
         ${sex} Welcome, my friend! <!-- ${expression} EL的语法型态 -->
    </div>

    EL都都都可不可以 访问页面的上下文以及不同作用域中的对象 ,取得对象属性的值,或执行简单的运算或判断操作,用来比较复杂JSP中的java代码。EL表达式是JSP1.2后后内置支持的,能都都可不可以 直接在JSP中使用,它从servlet四大作用域(范围servletContext > session > request > pageContext)中取值,这有一个域一定会setAttribute("",object)方式和getAttribute("")方式, EL表达式会自动按作用范围从小到大的顺序从四大作用域中寻找对应名字的值,找到了就立即返回不再继续寻找,其内部管理调用的本来 pageContext的findAttribute("")方式。

    EL不言而喻能比较复杂JSP中的java代码,何如让 它功能非常简单,越来越满足好多好多 比较复杂的代码逻辑,好多好多 就诞生了JSTL。JSP标准标签库(JSTL)是另一个 JSP标签集合,它封装了JSP应用的通用核心功能,支持通用的、型态化的任务,比如迭代,条件判断,XML文档操作,国际化标签,SQL标签,另外还支持自定义标签,它实现了JSP页面中的代码复用、比较复杂了代码的书写,同时也保证了JSP的可读性更强。JSTL功能比较富有,但它一定会JSP内置支持的,好多好多 时需导入标签库到JSP页面(时需加进去去jstl的jar包依赖)。JSTL往往会集合EL表达式来使用,简单示类似下

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!-- 引入JSTL标签库,c表示标签库别名,能都都可不可以




任意命名,一般而言用c -->
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>index</title>
</head>
<body>
    <c:set var="sex" value="女" scope="page"></c:set> <!-- scope指定作用域,page/request/session/application -->
    <c:if test="${sex == '男' }">
        Hello, ${sex}
    </c:if>
    <c:if test="${sex != '男' }">
        Hi, girl
    </c:if>
</body>
</html>

    这代码看起来就清爽多了,越来越java代码,前端开发者也很容易看懂;关于EL表达式与JSTL标签更详细信息,时需我们歌词 歌词 我们歌词 我们歌词 自行去查阅资料了,本文篇幅有限,不做太少的讲解了。

  重定向与请求转发

    越来越可想而知,重定向的request作用域的变量是会失效的,而转发则不用

  Spring MVC

    还记得我们歌词 歌词 我们歌词 我们歌词 是何如配置Spring MVC的吗, 我们歌词 歌词 我们歌词 我们歌词 会在web.xml中配置如下代码

<servlet>
        <servlet-name>springDispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springDispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    本来 就配置了Spring MVC;我们歌词 歌词 我们歌词 我们歌词 能都都可不可以 留意下DispatcherServlet,去看他的类图会发现,他本来 另一个 Servlet的实现,也本来 说Sprinv MVC本来 基于Servlet的拓展。

    我们歌词 歌词 我们歌词 我们歌词 在Spring MVC基础上进行开发的后后,将数据绑定到作用域的后后,一般用的是SpringMVC的数据模型:Model肯能ModelMap,类似本来

@RequestMapping("/showPerson")
public String showPersons(Model model){
    List<Person> persons = personService.loadPersons();
    model.addAttribute("persons", persons);        // 绑定数据到视图
    return "showperson";
}

    而一定会显示的直接绑定到Servlet四大作用域,数据难道越来越绑定到四大作用域? 我们歌词 歌词 我们歌词 我们歌词 说过,EL表达式越来越在四大作用域中取值,何如让 取越来越,好多好多 SpringMVC中的数据绑定最终还是会到四大作用域的某另一个 中,至于是了吗、何地、何如将Model中的属性绑定到哪个作用域,这一一定会本文要说的了,篇幅太少了,有兴趣的能都都可不可以 去看看这篇博客:springmvc的工作原理,我们歌词 歌词 我们歌词 我们歌词 来看看其源码实现。这里给个结论:在默认情况报告下,Model中的属性作用域是request级别

  问题报告 解答

    好多好多 小伙伴会抱怨了:上方哔哔了越来越多,为啥么本来 不讲答案,净说好多好多 没用的

    肯能我们歌词 歌词 我们歌词 我们歌词 坚持看多这了,再坚持会,答案马上揭晓,上方铺垫了越来越多,绝对是有用的。

    我们歌词 歌词 我们歌词 我们歌词 回到问题报告 :我们歌词 歌词 我们歌词 我们歌词 歌词 请求http://localhost:端口/工程名/personController/showPerson时,数据正常显示,而我们歌词 歌词 我们歌词 我们歌词 歌词 直接请求jsp时,越来越title却越来越数据,这是为哪几种?title是静态页面内容,这一不用管,那为哪几种直接请求jsp为哪几种越来越数据库的person列表呢? jsp源代码如下

<%@ page language="java" contentType="text/html; charset=utf-8"
     pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <title>person list</title>
    </head>
    <body>
        <table>
            <tr>
                <th>姓名</th>
                <th>年龄</th>
            </tr>
            <c:forEach items="${persons}" var="person">
                <tr>
                    <td>${person.name }</td>
                    <td>${person.age }</td>
                </tr>
            </c:forEach>
        </table>
    </body>
</html>

    上方用到了<c:forEach>和EL表达式,解释下这一流程:EL表达式先从四大作用域获取名为persons的集合,何如让 <c:forEach>遍历该集合,每次遍历的结果倒入page作用域,并取叫安person,最后通过EL表达式输出person的name和age到页面。越来越请问:直接访问JSP,四大作用域涵盖叫安persons的属性吗?很显然越来越,persons不指在,遍历它会有结果输出吗?这本来 为哪几种直接访问jsp越来越数据的答案。

    我们歌词 歌词 我们歌词 我们歌词 再回到Controller层

@RequestMapping("/showPerson")
public String showPersons(Model model){
    List<Person> persons = personService.loadPersons();        // 从数据获取person列表,并存倒入了persons集合中
    model.addAttribute("persons", persons);                    // 将persons集合加进去去到model的persons属性中
    return "showperson";                                    // 转发到showperson.jsp
}

    代码也非常简单,先从数据库获取person集合,何如让 将该集合设置到了model的属性persons中,我们歌词 歌词 我们歌词 我们歌词 知道model的属性默认情况报告下会设置到request作用域;何如让 将请求转发到showperson.jsp,转发过程中,request作用域的变量仍然有效,好多好多 jsp中EL表达式都都都可不可以 读取到persons变量,好多好多 一定会数据输出到页面了。

总结

  1、Servlet与Servlet容器的关系比较暧昧,两者相互作用,实现web服务;简单点说,我们歌词 歌词 我们歌词 我们歌词 自定义的Servlet本来 对Servlet容器的业务拓展,而Servlet容器是对Servlet的支撑;

  2、JSP的老出 时为了比较复杂静态页面的开发,EL表达式与JSTL的老出 则是为了比较复杂JSP页面的Java代码;JSP本质还是Servlet,在第一次被访问的后后会被Servlet容器解析成Servlet、编译Servlet,最终还是有Servlet将页面内容out.write到浏览器;

  3、Spring MVC本质还是Servlet,它的老出 是为了比较复杂web开发,同时能都都可不可以 与spring无缝对接,享受spring带来的好处;Spring MVC的数据绑定,依托的还是Servlet的的四大作用域,本来 上方指在转换过程;

  4、EL表达式的取值时需指在于四大作用域中,在jsp中用EL表达式时,一定要保证数据正确地加进去去到了四大作用域中,不然,EL表达式会取越来越值;

参考

  《深入分析JavaWeb技术内幕》

  《Tomcat 系统架构与模式设计分析》

  Java Web(一) Servlet详解!!