Javaweb学习


JavaWeb

1.Servlet

Servlet接口有两个默认实现类,GenericServlet、HttpServlet(继承自GenericServlet类)

Servlet接口有如下方法:

void init(ServletConfig var1) throws ServletException;
?
ServletConfig getServletConfig();
?
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
?
String getServletInfo();
?
void destroy();

GenericServlet 没有重写 service 函数,HttpServlet 重写了 service 函数,处理了多种请求方式。

开发一个Servlet程序,需要:

  • 建立一个空的Maven项目,删掉src目录,以后在项目里建module,空的即是主工程;主工程包含多个Module,子项目可以使用父工程的所有,配置xml文件,添加依赖项。

  • 新建Module,编写maven子工程,配置项目的web-info下的web.xml为最佳配置,编写一个实现Servlet接口的类

  • 把开发好的java类部署到web服务器中:注册Servlet,配置映射路径,映射路径可有多个(/hello/*),可自定义后缀( *.do),可通配所有( / *)

  • 配置Tomcat,设置项目为 s1,启动测试,如下代码访问链接为:http://localhost:8080/s1/hiii

package com.wang.servlet;
?
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
?
public class HelloServlet extends HttpServlet {
?
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter();
        writer.write("Hello, Hello, Hello!");
    }
?
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<?xml version="1.0" encoding="UTF-8"?>

?
    
      hi
      com.wang.servlet.HelloServlet
    
    
      hi
      /hiii
    
?

浏览器发送请求给web服务器,web服务器(如Tomcat服务器)获取请求,交给servlet,servlet通过service函数,处理请求得到响应,交给web服务器,传给浏览器作为响应。

1.1 ServletContext

可共享数据、可获取初始化参数、可请求转发、可读取资源文件

// 文件1设置参数
this.getServletContext().setAttribute("userName", new String("wang"));
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().println("ServletContext1执行");
// 文件2读取参数、资源、请求转发
// 实现共享数据
String name = (String)this.getServletContext().getAttribute("userName");
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().println(name);
?
// 实现请求转发
RequestDispatcher dispatcher = this.getServletContext().getRequestDispatcher("/ser1");
dispatcher.forward(req, resp);
?
// 实现获取资源配置文件
// 不在resources目录下的properties文件,需要在主工程下的xml里面配置build标签,再重启IDEA即可
InputStream stream = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/wang/servlet/aa.properties");
Properties properties = new Properties();
properties.load(stream);
String user = (String)properties.get("user");
Object pwd = properties.get("pwd");
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().println(user);
resp.getWriter().println(pwd);

1.2 HttpServletResponse

  • 实现打印文字信息

  • 实现文件下载

    String res = "D:\\idea_java_projects\\javaweb_servlet_2\\servlet_response\\src\\main\\resources\\壁纸.jpg";
    String fileName = res.substring(res.lastIndexOf("\\") + 1);
    // 设置浏览器可下载,即设置消息头参数
    resp.setHeader("Content-Disposition","attachment;filename=" + URLEncoder.encode(fileName,"utf-8"));
    FileInputStream fis = new FileInputStream(res);
    ServletOutputStream os = resp.getOutputStream();
    byte[] buffer = new byte[1024];
    int len;
    while ((len = fis.read(buffer)) != -1) {
        os.write(buffer, 0, len);
    }
    System.out.println("成功!");
    os.close();
    fis.close();
  • 实现图片验证码

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 图片验证码实现
        // 设置网页的刷新率,每5秒刷新一次
        resp.setHeader("refresh", "5");
        // 创建保存在内存中的image
        BufferedImage image = new BufferedImage(200,50,BufferedImage.TYPE_INT_RGB);
        Graphics g = image.getGraphics();
        g.setColor(Color.orange);
        g.drawRect(0,0,200,50);
        g.setColor(Color.blue);
        g.setFont(new Font("宋体", Font.BOLD, 30));
        g.drawString(getNum() ,30, 40);
        // 告知浏览器以图片形式打开
        resp.setContentType("image/jpg");
        // 删除网站缓存
        resp.setDateHeader("expires", -1);
        resp.setHeader("Cache-Control", "no-cache");
        resp.setHeader("Pragma", "no-cache");
        // 图片写给浏览器
        ImageIO.write(image,"jpg",resp.getOutputStream());
    }
    protected String getNum() {
        String num = new Random().nextInt(99999999) + "";
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < 8 - num.length(); i++) {
            stringBuffer.append(new Random().nextInt(10) + "");
        }
        return stringBuffer.append(num).toString();
    }
  • 实现重定向

    req.setCharacterEncoding("utf-8");
    resp.setCharacterEncoding("utf-8");
    String username = req.getParameter("username");
    String pwd = req.getParameter("pwd");
    String[] hobbies = req.getParameterValues("hobby");
    System.out.println("=================");
    System.out.println(username+":"+pwd+";"+ Arrays.toString(hobbies));
    System.out.println("=================");
    // 请求转发
    req.getRequestDispatcher("/success.jsp").forward(req, resp);
    // 重定向
    resp.sendRedirect("/servlet_response_war/success.jsp");

1.3 HttpServletRequest

主要使用 getParameter、getParameterValues、getRequestDispatcher等

重定向:访问路径(url)发生变化,请求两次,需要加上web应用的名字,因返回根目录

请求转发:访问路径(url)不变,请求一次,不能加上web应用的名字,因返回项目目录

<%-- form 表单的 action 设置为转向的路径 --%>
用户名:
密 码:
多选框: 唱歌 跳舞 玩耍

2.Cookie and Session

Cookie

req.getCookies();
cookie.getName();
cookie.getValue();
cookie.setMaxAge(); // 设置有效期为0,手动删除cookie
resp.addCookie();
// 手动删除cookie下的last_time,即清除缓存
Cookie cookie = new Cookie("last_time", System.currentTimeMillis() + "");
cookie.setMaxAge(0);
resp.addCookie(cookie);

Session

// 设置编码格式
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");

// Session1 : 设置session信息
HttpSession session = req.getSession();
session.setAttribute("name", "王");
if (session.isNew()) {
    resp.getWriter().write("session 创建成功,Id为" + session.getId());
} else {
    resp.getWriter().write("session 已创建,Id为" + session.getId());
}

// Session2 : 获取session信息
HttpSession session = req.getSession();
String name = (String)session.getAttribute("name");
System.out.println(name);

// Session3 : 手动删除Session信息
HttpSession session = req.getSession();
session.removeAttribute("name");
session.invalidate();

亦可在 xml 文件中配置 session 的存活时间


    
    3

3.JSP

Java Server Pages:Java代码原封不动,HTML以网页形式读取,JSP帮助简化网页

JSP 基本语法和指令:

<%@ page import="java.util.Date" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page errorPage="error.jsp" %>


    Title


<%--变量、表达式--%>
<%= new Date(System.currentTimeMillis()) %>
<%--Java片段--%>
<%  for (int i = 0; i < 5; i++) {%>

Hello World!

<% } %> <%= global_var%> <%--变量声明--%> <%! int global_var = 10;%> <%--JSP注释--%> <%= 1/0 %>

9大内置对象:

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;

pageContext、Request、Response、Session、Application、config、out、page、exception

从底层到高层(作用域):以下均可以 setAttribute

PageContext(当前页面)

Request(一次请求,请求转发,放新闻)

Session(一次会话,关闭浏览器消失,加购物车)

Application(关闭服务器消失,多用户 聊天记录)

// 实现请求转发,请求转发会将请求的数据携带
pageContext.forward();

JSP标签

<%--包含某个页面--%>

<%--请求转发至某个页面,可携带参数--%>

    

JSTL核心标签:c:if,c:choose,c:when,c:forEach (不常用) EL表达式 ${}

<%
    int[] nums = new int[]{2,4,6,3,9};
    request.setAttribute("nums", nums);
%>

    

JavaBean 实体类




4.MVC

View:视图(JSP,展示数据,提供用户操作)

Controller:控制器(Servlet,处理请求、控制视图跳转,响应交给业务层)

Model: 控制业务操作、增删改查数据,包括业务层(Service)、数据持久层(Dao)、JavaBean(实体类 :pojo、entity、vo、dto)

5.过滤器 (重要)

filter 过滤器过滤网站的数据,导包,实现Filter接口,配置web.xml

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    servletRequest.setCharacterEncoding("utf-8");
    servletResponse.setCharacterEncoding("utf-8");
    servletResponse.setContentType("text/html;charset=utf-8");
    System.out.println("执行前");
    filterChain.doFilter(servletRequest, servletResponse);
    System.out.println("执行后");
}

    filter1
    com.wang.filter.Filter1


    filter1
    /servlet/*

且过滤器在服务器打开时就初始化,服务器关掉后才会销毁。

6.监听器

Listener 实现监听器接口,配置web.xml

public void sessionCreated(HttpSessionEvent se) {
    ServletContext context = se.getSession().getServletContext();
    Integer count = (Integer)context.getAttribute("OnlineCount");
    if (count == null) {
        count = 1;
    } else {
        count++;
    }
    context.setAttribute("OnlineCount", count);
}
?
public void sessionDestroyed(HttpSessionEvent se) {
    ServletContext context = se.getSession().getServletContext();
    Integer count = (Integer)context.getAttribute("OnlineCount");
    if (count == null) {
        count = 0;
    }else {
        count--;
    }
    context.setAttribute("OnlineCount", count);
}

    com.wang.listener.Listener1

    

当前有<%= request.getServletContext().getAttribute("OnlineCount")%> 人在线

7.smbms 踩坑

报错异常java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/core/ConditionalTagSupport,应该从 http://archive.apache.org/dist/jakarta/taglibs/standard/binaries/ 下载jakarta-taglibs-standard-1.1.2.zip这个包,解压缩后将standard和jstl两个包放入tomcat下的lib下即可

界面显示不出来其实是因为 其他jsp放在head.jsp后面,用一个标签session,前一个在head,后一个在相应页面,不能擅自给head添加session,不然界面跑到下面去!!!

8.其他

文件上传

  • 为保证服务器安全,上传文件应该放在外界无法直接访问的目录,比如web-inf文件下

  • 为防止覆盖,要为上传文件产生一个唯一文件名(时间戳,uuid,md5,位运算算法)

  • 要限制上传文件的最大值(服务器耗钱)

  • 限制上传文件的类型,判断后缀名是否合法

ServletFileUpload 负责处理上传的文件数据,将表单中的每个输入项封装成一个FileItem对象,在使用ServletFileUpload对象解析请求时需要DiskFileItemFactory对象。所以需要在进行解析工作前构造好DiskFileItemFactory 对象,通过ServletFileUpload对象的构造方法或者setFileItemFactory()方法设置ServletFileUpload对象的fileItemFactory属性。

1、创建DiskFileItemFactory 对象,处理文件上传路径或者缓存文件大小限制

2、创建ServletFileUpload 对象,传入1的对象作为构造函数参数,可监听文件上传进度、处理乱码问题、设置单个文件的最大值、设置总共能够上传文件的大小

3、处理上传文件:ServletFileUpload 对象将前端请求解析封装成FileItem对象,读取FileItem的数据,进行后续处理

邮件发送

需要 mail.jar 包和 activation.jar 包

设置服务器、邮箱发送协议等信息,新建 Session 对象,通过 Session 得到 transport 对象,使用邮箱的用户名和密码 connect 邮件服务器,创建发送邮件 MimeMessage 对象,发送邮件,关闭连接。

MimeBodyPart()描述一个邮件的一部分,比如文字、图片、附件,MimeMultipart()作为一个容器,包含其他数据,并设置 alternative / related / mixed,最后将 MimeMultipart 放到 MimeMessage 中。

异步处理,多线程,email 继承 Thread 类,实现多线程,防止网页一直加载页面不出来,影响用户体验。