zoukankan      html  css  js  c++  java
  • servlet学习

     推荐一个博客:https://www.cnblogs.com/xdp-gacl/tag/JavaWeb学习总结/default.html?page=3

    这里有将tomcat和serlvet的知识,很详细,有示例

    一、使用idea搭建Servlet程序

    https://blog.csdn.net/jesonjoke/article/details/78276714

    问题解决:

    1 tomcat和servlet、java有版本兼容性问题

    警告 [RMI TCP Connection(2)-127.0.0.1] org.apache.tomcat.util.descriptor.web.WebXml.setVersion Unknown version string [4.0]. Default version will be used.

    原因:低版本的tomcat不兼容高版本的servlet和java,参照官网http://tomcat.apache.org/whichversion.html,换成tomcat高版本即可

    2 idea tomcat 控制台乱码

    使用了网上的多种改变编码的方法,还是不行,最后发现tomcat9的日志输出格式就是utf-8。我猜应该是中文操作系统idea的控制台是GBK编码,修改方法如下:

    1、找到${CATALINA_HOME}/conf/logging.properties
    2、找到java.util.logging.ConsoleHandler.encoding = UTF-8
          修改为java.util.logging.ConsoleHandler.encoding = GBK

    二、Servlet线程安全性问题

    https://yq.aliyun.com/articles/612905

    Servlet是单例多线程,一个请求对应一个线程,每个线程去调用service方法,要保证安全性问题,尽量避免在doGet等方法中使用servlet类实例的变量,而使用在doGet等方法中使用局部变量,这样多线程就不会出现线程安全问题(每个线程有自己的虚拟机栈用于存储局部变量)。如果实在要使用实例变量,使用synchronized进行同步(效率比较低,因为会有较多线程同步,阻塞严重)。当然远古可以设置servlet为多例单线程,实现SingleThreadModel接口即可,容器会创建对各请求创建一个实例,这将引起大量的系统开销,SingleThreadModel在Servlet2.4中已被不提倡。

    三、简单的Servlet程序(纯后台Serlvet,返回json数据)

     可以使用postman发送get请求报文,数据放在body中。在servlet中使用inputStream进行获取body中的内容,将其读出即可。

     1 @WebServlet("/ServletReJSON")
     2 public class ServletReJSON extends HttpServlet {
     3     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     4 
     5     }
     6 
     7     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     8         InputStream is = request.getInputStream();
     9         int byteLength = request.getContentLength();
    10         byte b[] = new byte[byteLength];
    11         int len = is.read(b);
    12         StringBuilder repJson = new StringBuilder("{msgJson:");
    13         repJson.append(new String(b)).append("}");
    14         response.setContentType("text/javascript");
    15         response.getWriter().print(repJson.toString());
    16     }
    17 }

    四、servlet过滤器:filter

     在请求传到servlet处理之前和servlet传出响应到客户端之前,进行一次过滤操作

    过滤器实现javax.servlet.Filter类,实现doFilter方法即可。写好filter类之后,在web.xml中配置好filter的过滤地址(即哪些地址需要被过滤)

    filter类:

     1 public class MyTestFilter implements Filter {
     2     public void destroy() {
     3     }
     4 
     5     public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
     6         System.out.println("doFilter! --request"); //过滤请求的代码写在这里
     7         chain.doFilter(req, resp); //一旦执行doFilter,过滤器就会把请求交给下一个过滤器,如果没有下一个过滤器,那就传给匹配的servlet
     8         System.out.println("doFilter! --response"); //根据过滤器链依次传递响应到每一个过滤器
     9     }
    10 
    11     public void init(FilterConfig config) throws ServletException {
    12         String param = config.getInitParameter("MyParam"); //获取在web.xml中配置的过滤器的filterConfig参数
    13         System.out.println("myFilter init!");
    14         System.out.println(param+"!");
    15     }
    16 }

    web.xml配置:

     1 <filter>
     2     <filter-name>MyTestFilter</filter-name>
     3     <filter-class>com.lzj.filter.MyTestFilter</filter-class>
     4     <init-param>
     5         <param-name>MyParam</param-name>
     6         <param-value>get my param</param-value>
     7     </init-param>
     8 </filter>
     9 <filter-mapping>
    10     <filter-name>MyTestFilter</filter-name>
    11     <url-pattern>/TestFilterServlet</url-pattern>
    12 </filter-mapping>

    五、session/cookie

    http协议是无状态协议,当一个用户想要登陆一次就能持续获取后台数据,后台程序就要使用cookie和session来保持这个连接

    cookie

    浏览器发送请求到servlet后台程序时,servlet创建一个cookie对象,然后返回响应,浏览器根据响应的cookie信息,在本地创建一个cookie文件。以后每次发送请求就带上这个cookie

    可以为cookie设置key-value值,cookie有多对key-value值,servlet中可以通过request获取,也可以通过response设置

    使用postman发送请求,可以看到这里返回了json内容,如果请求没有发送cookie就会提示无cookie或者已过期

     1 @WebServlet("/CookieServlet")
     2 public class CookieServlet extends HttpServlet {
     3     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     4 
     5     }
     6 
     7     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     8         Cookie[] reqCookies = request.getCookies();
     9         Cookie cookieName = new Cookie("name", "heh");
    10         Cookie cookieSex = new Cookie("sex", "nan");
    11         cookieName.setMaxAge(60*2);
    12         response.addCookie(cookieName);
    13         response.addCookie(cookieSex);
    14         StringBuilder resp = new StringBuilder("");
    15         if(reqCookies != null){
    16             for (Cookie reqCookie : reqCookies) {
    17                 resp.append(reqCookie.getName()).append(":").append(reqCookie.getValue()).append("
    ");
    18             }
    19         }else{
    20             resp.append("无cookie或者已过期");
    21         }
    22         response.setContentType("text/javascript;charset=utf-8");
    23         response.getWriter().print(resp.toString());
    24     }
    25 }

     session

    session也是为了保持浏览器和服务器之间状态。其利用了cookie来承载一个sessionid,cookie的key值为JSESSIONID,value值为sessionid的值,对应到服务器后台,sessionid对应了一个session对象,这个对象可以放很多key-value值,可以理解为cookie的升级(因为cookie的大小是有限的)

    session集合在后台被Manager的一个类保存,每次请求时,容器会根据前台请求cookie中的的sessionid(或者url中的sessionid,这是为了避免有些浏览器不支持cookie)在session集合中找到对应的session对象,赋值到容器request对象中。在request对象中可以通过request.getSession()来获取这个session对象,如果没有获取到session对象则创建一个新的session对象(同时添加这个session到session集合中,并设置response header的cookie值)

     1 @WebServlet("/SessionServlet")
     2 public class SessionServlet extends HttpServlet {
     3     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     4 
     5     }
     6 
     7     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     8         HttpSession session =  request.getSession(); // 获取session,如果request没有session就创建一个新session,并且添加到sesssion集合并设置response header的cookie值
     9         String sessionId = session.getId();
    10         response.setContentType("text/javascript;charset=utf-8");
    11         if(session.isNew()){
    12             session.setAttribute("usrId", "123");
    13             response.getWriter().print("服务端第一次新建sesstion,sessionId: " + sessionId + "
    " + "set usrId = 123");
    14         }else{
    15             response.getWriter().print("浏览器每次请求携带sesstion,sessionId: " + sessionId
    16                     + "
    " + "getUsrId:" +  session.getAttribute("usrId"));
    17         }
    18     }
    19 }

    六、乱码问题

    七、servlet监听器:listenner

    servlet监听器是Servlet规范中定义的一种特殊类,它用于监听web应用程序中的ServletContext, HttpSession和 ServletRequest等域对象的创建与销毁事件,以及监听这些域对象中的属性发生修改的事件。

    以如何写一个ServletContextListener监听器为例:

    ServletContextListener负责监听servletContext对象的创建和销毁(context对应一个web应用,可参考tomcat结构,可以说servletContext对象就是一个web应用的全局对象)

    1. 首先创建一个监听的servletContext的类,实现serlvet的ServletContextListener接口,实现其两个方法

     1 import javax.servlet.ServletContextEvent;
     2 import javax.servlet.ServletContextListener;
     3 
     4 public class MyServletContextListener implements ServletContextListener {
     5 
     6     @Override
     7     public void contextInitialized(ServletContextEvent sce) {
     8         System.out.println("ServletContext对象创建");
     9     }
    10 
    11     @Override
    12     public void contextDestroyed(ServletContextEvent sce) {
    13         System.out.println("ServletContext对象销毁");
    14     }
    15 }

    2. 在web.xml配置监听器

    <listener>
      <description>ServletContextListener监听器</description>
      <listener-class>com.lzj.listener.MyServletContextListener</listener-class>
    </listener>

     其他监听同理,实现serlvet提供的对应接口即可

  • 相关阅读:
    dedecms列表页实现文档按权重weight排序
    DEDEcms5.7各个文件的作用与安全防御设置
    我的SEO笔记
    分析网站日志
    网页上链接的添加规范与标准
    解决引用bootstrap样式时遇到的冲突问题
    js滚动到指定位置导航栏固定顶部
    使用rem自适应屏幕
    SQL 操作结果集 -并集、差集、交集、结果集排序
    简洁的左右滑动式轮播图
  • 原文地址:https://www.cnblogs.com/hahlzj/p/11312367.html
Copyright © 2011-2022 走看看