美文网首页
菜鸟搭建web服务笔记-1

菜鸟搭建web服务笔记-1

作者: DizzyDwarf | 来源:发表于2019-03-13 17:57 被阅读0次

笔者最近看了Spring,MyBatis,Maven和Git等技术的相关资料,想自己试着从头搭建一个web服务,以巩固并加深学到的知识,于是便有了这一系列文章。这一系列文章将主要记录整个搭建过程,碰到的问题以及解决方案。注意本系列文章并不是各类技术的入门使用教程,需要读者对技术本身有一定的了解。

开发环境

  • Tomcat:9.0.16
  • Maven:3.6.0
  • Git:2.20
  • 操作系统:windows10

项目需求

因为暂时没想好要做什么服务,那么就以最简单的登录功能开始吧。

创建项目

  • 首先在github上创建了一个dizzydwarf项目
  • 然后在eclipse中创建了一个Maven项目,并将两者关联起来
    git remote add origin https://github.com/xuben/dizzydwarf.git

问题1:Maven中创建web项目

这里笔者在创建Maven项目的目录结构时没有选择web项目的模板,因此需要自己将其改造成一个web项目。

  • 首先需要告诉Maven这是一个web项目,最后需要打包成war包,因此修改pom.xml
<packaging>war</packaging>
  • 然后在src/main目录下新建如下目录结构
src
    main
        webapp
            WEB-INF
                web.xml

设计并实现

一开始的设计思路是这样的,用Tomcat作为web容器,写一个servlet,将所有的url请求都交给这个servlet处理,由servlet决定不同的url应该调用哪个类的哪个方法。

  • 写了个DispatchServlet,继承HttpServlet,重写doGetdoPost,根据getRequestURI判断请求的url,并把/login请求交给LoginAction处理
  • 在web.xml中配置servlet
  • 写了个index.html页面,里面只有一个表单,提交的action为/login
  • mvn package生成一个war包
  • 将这个war包放到Tomcat安装目录的webapps子目录下并启动Tomcat

问题2:Invalid <url-pattern>

Tomcat启动时提示Invalid <url-pattern>,笔者在web.xml中是这样配置servlet-mapping的

<servlet-mapping>
    <servlet-name>Dispatcher</servlet-name>
    <url-pattern>*</url-pattern>
</servlet-mapping>

到底什么样的url-pattern是合法的,具体规则可以参见servlet specification的Mapping Requests to Servlets部分。如果我们只是想要匹配所有url,可以把*改成/*

<servlet-mapping>
    <servlet-name>Dispatcher</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

问题3:Tomcat在命令行输出中文乱码

  • 找到注册表项HKEY_CURRENT_USER\Console\Tomcat,如果没有则新建。
  • 新建CodePage,类型为DWORD(32位)值,值为fde9,也就是65001

问题4:web项目的地址

笔者在浏览器中输入的访问地址是http://localhost:8080/index.html,结果跳到了Tomcat自带的web项目。原来要访问这个新添加的web项目需要输入相对于host的路径。
这里webapps是host的根目录,而新添加的war包被解压到了webapps/dizzydwarf-0.0.1-SNAPSHOT目录,因此访问的时候需要输入http://localhost:8080/dizzydwarf-0.0.1-SNAPSHOT/index.html,虽然有够麻烦的,不过暂时不是什么大问题,毕竟我们可以在必要的时候将其部署到host根目录。

问题5:url-pattern匹配

输入正确的地址,还是没有看到表单。原来是笔者将servlet的url-pattern配置为了/*,因此就算是请求静态的html页面,也会被匹配到然后交给servlet处理。查了下网上的资料,似乎并没有什么简单的方法可以在url-pattern中排除指定类型的文件,无奈之下把url-pattern改回了/login

问题5:表单action的绝对路径和相对路径问题

再次输入正确的地址,终于看到表单了。点击登录按钮,返回404错误,怎么回事?仔细一看浏览器的地址栏,发现地址栏变成了http://localhost:8080/login
原来表单的action属性的值为/login,而这个url地址也是相对于host根目录,而不是当前web应用根目录的地址,正确的值应该是login

问题6:getRequestURI获得的路径

把action改成login,重新打包部署后提交表单还是一片空白,在servlet中输出getRequestURI结果一看,发现url是/dizzydwarf-0.0.1-SNAPSHOT/login,而不是预期的/login。因为在servlet配置中已经有url映射了,所以这里删除这部分的代码,改成直接处理请求。
至此,用一个servlet处理所有url请求,然后在servlet内部分发的想法算是彻底破灭。但是事实上,关于url的映射通过web.xml方式配置也有其灵活性,只不过需要写多个servlet类处理。

JSP中的解决方案

对于前端请求使用绝对路径的问题,在jsp中可以用${pageContext.request.contextPath}表示web根目录的路径

struts2的解决方案

简单看了下struts2的StrutsPrepareAndExecuteFilter类,关于uri的处理调用了RequestUtils.getUri方法。大致的思路是用到了getServletPath方法,这个方法返回的是与url-pattern匹配的部分,不包括通过*匹配的部分。结合getServletPathgetRequestURIgetPathInfo方法最终得到相对于web服务根目录的uri路径。
另外struts2中的请求都以.do结尾,因此可以很好的排除对静态html文件的匹配。

结论

  • 前端url请求的绝对路径是相对于host根目录,后端url-pattern则是相对于web服务的根目录
  • url-pattern无法简单排除所有的静态html文件,同时servlet中也无法简单获得相对于web服务根目录的url请求路径,因此用单个servlet处理所有请求并在内部进行分发的想法实现起来并不简单。解决办法可以参考struts2。

相关文章

网友评论

      本文标题:菜鸟搭建web服务笔记-1

      本文链接:https://www.haomeiwen.com/subject/wvmtmqtx.html