JavaWeb

Maven

maven由于它的约定大于配置,如果遇到配置文件无法被导出或者生效的问题,解决方案:

    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>

            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

Servlet简介

  • Servlet就是sun公司开发动态web的一门技术
  • Sun在这些API中提供一个接口叫做:Servlet,如果你想开发一个Servlet程序,只需要完成两个步骤:
  1. 编写一个类,实现Servlet接口
  2. 把开发好的Java类部署到web服务器中

Servlet原理

Servlet是由Web服务器调用,web服务器在收到浏览器请求之后,会走一下流程:
在这里插入图片描述

ServletContext

web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,他代表了当前的web应用;

1.共享数据

在这个Servlet中保存数据,可以在另外一个servlet中拿到;
public class HelloServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
//        ServletOutputStream outputStream = resp.getOutputStream();
        PrintWriter writer = resp.getWriter();
        writer.println("Hello,Servlet");

        ServletContext servletContext = this.getServletContext();
        servletContext.setAttribute("name","张飞");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        doGet(req, resp);
    }
}

public class HiServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        resp.setContentType("text/html");
        resp.setCharacterEncoding("UTF-8");
        ServletContext servletContext = this.getServletContext();
        PrintWriter writer = resp.getWriter();
        writer.println("Hello," + servletContext.getAttribute("name"));
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        doGet(req, resp);
    }
}

2.获取初始化参数

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <context-param>
        <param-name>url</param-name>
        <param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
    </context-param>

    <servlet>
        <servlet-name>sd</servlet-name>
        <servlet-class>com.release.servlet.ServletDemo</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>sd</servlet-name>
        <url-pattern>/sd</url-pattern>
    </servlet-mapping>
</web-app>
public class ServletDemo extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        ServletContext servletContext = this.getServletContext();
        String url = servletContext.getInitParameter("url");
        resp.getWriter().println(url);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        doGet(req, resp);
    }
}

3.转发请求

public class ServletDemo2 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        ServletContext servletContext = this.getServletContext();
        servletContext.getRequestDispatcher("/sd").forward(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        doGet(req, resp);
    }
}

4.读取资源文件

public class ServletDemo3 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        InputStream inputStream = this.getServletContext().getResourceAsStream("WEB-INF/classes/db.properties");
        Properties properties = new Properties();
        properties.load(inputStream);
        String username = properties.getProperty("username");
        String password = properties.getProperty("password");
        resp.getWriter().println(username + ":" + password);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        doGet(req, resp);
    }
}

HttpservletResponse

1.简单分类

负责向浏览器发送数据的方法


    ServletOutputStream getOutputStream() throws IOException;

    PrintWriter getWriter() throws IOException;

负责向浏览器发送响应头的方法

    void setDateHeader(String var1, long var2);

    void addDateHeader(String var1, long var2);

    void setHeader(String var1, String var2);

    void addHeader(String var1, String var2);

    void setIntHeader(String var1, int var2);

    void addIntHeader(String var1, int var2);

响应的状态码

    int SC_CONTINUE = 100;
    int SC_SWITCHING_PROTOCOLS = 101;
    int SC_OK = 200;
    int SC_CREATED = 201;
    int SC_ACCEPTED = 202;
    int SC_NON_AUTHORITATIVE_INFORMATION = 203;
    int SC_NO_CONTENT = 204;
    int SC_RESET_CONTENT = 205;
    int SC_PARTIAL_CONTENT = 206;
    int SC_MULTIPLE_CHOICES = 300;
    int SC_MOVED_PERMANENTLY = 301;
    int SC_MOVED_TEMPORARILY = 302;
    int SC_FOUND = 302;
    int SC_SEE_OTHER = 303;
    int SC_NOT_MODIFIED = 304;
    int SC_USE_PROXY = 305;
    int SC_TEMPORARY_REDIRECT = 307;
    int SC_BAD_REQUEST = 400;
    int SC_UNAUTHORIZED = 401;
    int SC_PAYMENT_REQUIRED = 402;
    int SC_FORBIDDEN = 403;
    int SC_NOT_FOUND = 404;
    int SC_METHOD_NOT_ALLOWED = 405;
    int SC_NOT_ACCEPTABLE = 406;
    int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
    int SC_REQUEST_TIMEOUT = 408;
    int SC_CONFLICT = 409;
    int SC_GONE = 410;
    int SC_LENGTH_REQUIRED = 411;
    int SC_PRECONDITION_FAILED = 412;
    int SC_REQUEST_ENTITY_TOO_LARGE = 413;
    int SC_REQUEST_URI_TOO_LONG = 414;
    int SC_UNSUPPORTED_MEDIA_TYPE = 415;
    int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
    int SC_EXPECTATION_FAILED = 417;
    int SC_INTERNAL_SERVER_ERROR = 500;
    int SC_NOT_IMPLEMENTED = 501;
    int SC_BAD_GATEWAY = 502;
    int SC_SERVICE_UNAVAILABLE = 503;
    int SC_GATEWAY_TIMEOUT = 504;
    int SC_HTTP_VERSION_NOT_SUPPORTED = 505;

2.常见应用

  1. 向浏览器输出消息
  2. 下载文件
    • 要获取下载文件路径
    • 下载文件名是什么
    • 设置浏览器能够支持下载我们需要的东西
    • 获取下载文件的输入流
    • 创建缓冲区
    • 获取OutputStream对象
    • 将FileOutputStream流写入到buffer缓冲区
    • 使用OutputStream将缓冲区中的数据输出到客户端
public class FileServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        String path = this.getServletContext().getRealPath("/upload");
        File realPath = new File(path);
        if (!realPath.exists()) {
            realPath.mkdir();
        }

//    1.要获取下载文件路径
        String downPath = this.getServletContext().getRealPath("/upload");
        System.out.println("下载文件路径:"+downPath);
//    2.下载文件名是什么
        String fileName = "a.png";
//    3.设置浏览器能够支持下载我们需要的东西
        resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));
//    4.获取下载文件的输入流
        File file = new File(downPath, fileName);
        FileInputStream inputStream = new FileInputStream(file);
//    5.创建缓冲区
        int len = 0;
        byte[] buffer = new byte[1024];
//    6.获取OutputStream对象
        ServletOutputStream outputStream = resp.getOutputStream();
//    7.将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输出到客户端
        while ((len = inputStream.read(buffer))>0){
            outputStream.write(buffer,0,len);
        }
        inputStream.close();
        outputStream.close();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        doGet(req, resp);
    }
}
  1. 验证码功能
public class ImageServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {

        //让浏览器3秒自动刷新一次
        resp.setHeader("refresh", "3");

        //在内存中创建一张图片
        BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
        //得到图片
        Graphics graphics = image.getGraphics();
        //设置图片的背景色
        graphics.setColor(Color.WHITE);
        graphics.fillRect(0,0,80,20);
        graphics.setColor(Color.BLUE);
        graphics.setFont(new Font(null, Font.BOLD, 20));
        graphics.drawString(makeNum(), 0, 20);

        //告诉浏览器,这个请求用图片的方式打开
        resp.setContentType("image/jpeg");
        //网站缓存,不让浏览器缓存
        resp.setDateHeader("expires", -1);
        resp.setHeader("Cache-Control", "no-cache");
        resp.setHeader("Pragma", "no-cache");

        //把图片写给浏览器
        ImageIO.write(image, "jpg", resp.getOutputStream());
    }


    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        doGet(req, resp);
    }

    /**
     * 生产随机数
     *
     * @return
     */
    private String makeNum() {
        Random random = new Random();
        String num = random.nextInt(999999) + "";
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < 6 - num.length(); i++) {
            stringBuffer.append("0");
        }
        num = stringBuffer.toString() + num;
        return num;
    }

}
  1. 实现重定向
 @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {

        resp.sendRedirect("/image");

    }

HttpservletRequest

转发

 @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {

        //转发
        req.getRequestDispatcher("/image").forward(req, resp);
    }

重定向和转发的区别

  • 相同点
    • 页面都会实现跳转
  • 不同点
    • 请求转发的时候,url不会产生变化 307
    • 重定向的时候,url地址栏会发生变化 302

Cookie、Session

会话

会话:用户打开一个浏览器,点击了很多超链接,访问了多个web资源,关闭浏览器,这个过程可以称之为会话

保存会话的两种技术

Cookie

  • 客户端技术(响应,请求)
    Session
  • 服务器技术,利用这个技术我们可以把用的信息或者数据放在Session中

Cookie

  1. 从请求中拿到cookie信息
  2. 服务器响应给客户端 cookie
Cookie[] cookies = req.getCookies();
cookie.getName()
cookie.getValue()
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
cookie.setMaxAge(24 * 60 * 60);//设置cookie的有效期
resp.addCookie(cookie);//响应给客户端一个cookie

cookie:一般会保存在本地的用户目录下appdata

一个网站cookie是否存在上线

  • 一个cookie只能保存一个信息
  • 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie
  • cookie大小有限制4kb
  • 300个cookie浏览器上限

Session

  • 服务器会给每个用户(浏览器)创建一个Session对象
  • 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在
  • 用户登录之后,整个网站它都可以访问!

使用场景:

  • 保存一个登录用户信息
  • 购物车信息
  • 在整个网站中经常使用的数据,我们将它保存的session中

Session和Cookie的区别:

  • Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
  • Session把用户的数据写到用户独占Session中,服务器端保存(保存重要的信息,减少服务器资源的浪费)
  • Session对象由服务器创建

JSP

Java Server Pages: Java服务器端页面,也和Servlet一样,用于动态Web技术
最大的特点:

  • 写jsp就像在写HTML
  • 区别:
    • HTML只给用户提供静态的数据
    • JSP页面中可以嵌入JAVA代码,为用户提供动态数据

Filter

public class CharacterEncodingFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("==========init==========");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");

        System.out.println("=============执行前=================");
        filterChain.doFilter(request, response);
        System.out.println("=============执行后=================");
    }

    @Override
    public void destroy() {
        System.out.println("==========destroy==========");
    }
}

    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>com.release.filter.CharacterEncodingFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

监听器

public class OnlineCountListener implements HttpSessionListener {


    /**
     * 一旦创建Session就会触发一次这个事件
     * @param httpSessionEvent
     */
    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
        Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");
        if (onlineCount == null){
            onlineCount = new Integer(1);
        }else {
            int i = onlineCount.intValue();
            onlineCount = new Integer(i+1);
        }
        servletContext.setAttribute("OnlineCount",onlineCount);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
        Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");
        if (onlineCount == null){
            onlineCount = new Integer(0);
        }else {
            int i = onlineCount.intValue();
            onlineCount = new Integer(i-1);
        }
        servletContext.setAttribute("OnlineCount",onlineCount);
    }
}

    <!--注册监听器-->
    <listener>
        <listener-class>com.release.listener.OnlineCountListener</listener-class>
    </listener>

JDBC

public class TestJdbc {

    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //配置信息
        String url = "jdbc:mysql://localhost:3306/DB01?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&rewriteBatchedStatements=true&autoReconnect=true";
        String username = "root";
        String password = "123456";

        //1.加载驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
        //2.连接数据库
        Connection connection = DriverManager.getConnection(url, username, password);
        //3.向数据库发送SQL的对象Statement:CRUD
        Statement statement = connection.createStatement();
        //4.编写SQL
        String sql  = "select * from dept";
        //5.执行查询SQL,返回一个ResultSet : 结果集
        ResultSet rs = statement.executeQuery(sql);
        while (rs.next()){
            System.out.println("deptno = "+rs.getObject("deptno"));
            System.out.println("dname = "+rs.getObject("dname"));
            System.out.println("db_source = "+rs.getObject("db_source"));
        }

        //6.关闭连接,释放资源,先开后关
        rs.close();
        statement.close();
        connection.close();
    }
}

JDBC事务

public class TestJdbc3 {

    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //配置信息
        String url = "jdbc:mysql://localhost:3306/DB01?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&rewriteBatchedStatements=true&autoReconnect=true";
        String username = "root";
        String password = "123456";

        Connection connection = null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            connection = DriverManager.getConnection(url, username, password);
            //通知数据库开启事务,false 开启
            connection.setAutoCommit(false);
            String sql = "update dept set db_source = 'db03' where deptno = 1";
            connection.prepareStatement(sql).executeUpdate();

//            int i = 1 / 0;

            String sql2 = "update dept set db_source = 'db03' where deptno = 2";
            connection.prepareStatement(sql2).executeUpdate();
            connection.commit();
            System.out.println("提交成功");
        } catch (Exception e) {
            try {
                //如果出现异常,就通知数据库回滚事务
                connection.rollback();
            }catch (SQLException e1){
                e1.printStackTrace();
            }
        }finally {
            try {
                connection.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
    }
}

文件上传

    <dependencies>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>

        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.11.0</version>
        </dependency>

    </dependencies>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>

  <form action="/upload.do" enctype="multipart/form-data" method="post">
    上传用户:<input type="text" name="username"><br/>
    <p><input type="file" name="file1"></p>
    <p><input type="file" name="file1"></p>
    <p><input type="submit"> |<input type="reset"> </p>

  </form>
  </body>
</html>

public class FileServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        //判断上传的文件是普通表单还是文件表单
        if (!ServletFileUpload.isMultipartContent(req)) {
            return;//如果是普通表单,则终止
        }

        String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
        File uploadFile = new File(uploadPath);
        if (!uploadFile.exists()) {
            uploadFile.mkdir();
        }

        //缓存临时文件
        String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
        File tempFile = new File(tempPath);
        if (!tempFile.exists()) {
            tempFile.mkdir();
        }

        //处理上传的文件,一般都需要通过流来获取,我们可以使用request.getInputStream(),原生态的文件上传流获取,十分麻烦
        //但是我们都建议使用Apache的文件上传组件来实现,common-fileupload,它需要依赖于common-io组件;

        try {
            //1.创建DiskFileItemFactory对象,处理文件上传路径或者大小限制的
            DiskFileItemFactory factory = getDiskFileItemFactory(tempFile);
            //2.获取ServletFileUpload
            ServletFileUpload upload = getServletFileUpload(factory);
            //3.处理上传的文件
            String msg = uploadParseRequest(upload, req, uploadPath);

            //servlet请求转发消息
            req.setAttribute("msg", msg);
            req.getRequestDispatcher("info.jsp").forward(req, resp);
        } catch (FileUploadException e) {
            e.printStackTrace();
        }
    }


    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        doGet(req, resp);
    }


    /**
     * 创建DiskFileItemFactory对象,处理文件上传路径或者大小限制的
     *
     * @param tempFile
     * @return
     */
    private DiskFileItemFactory getDiskFileItemFactory(File tempFile) {
        DiskFileItemFactory factory = new DiskFileItemFactory();
        factory.setSizeThreshold(1024 * 1024);//缓存区大小为1M
        factory.setRepository(tempFile);//临时目录的保存目录
        return factory;
    }

    /**
     * 获取ServletFileUpload
     *
     * @param factory
     * @return
     */
    private ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
        DecimalFormat df = new DecimalFormat("#.##");
        df.setRoundingMode(RoundingMode.HALF_UP);
        ServletFileUpload upload = new ServletFileUpload(factory);
        //监听文件上传进度
        upload.setProgressListener((pByteRead, pContentLength, pItems) ->
                System.out.println("总大小:" + pContentLength + " 已上传:" + pByteRead + " 上传百分比:" + df.format((float) pByteRead / pContentLength * 100) + "%")
        );
        //处理乱码
        upload.setHeaderEncoding("utf-8");
        //设置单个文件的最大值
        upload.setFileSizeMax(1024 * 1024 * 10);
        //设置总共能够上传文件的大小
        upload.setSizeMax(1024 * 1024 * 10);
        return upload;
    }


    /**
     * 处理上传的文件
     *
     * @param upload
     * @param req
     * @param uploadPath
     * @return
     */
    private String uploadParseRequest(ServletFileUpload upload, HttpServletRequest req, String uploadPath) throws FileUploadException, IOException {
        String msg = "";
        //解析前端的请求,封装成一个FileItem对象
        List<FileItem> fileItems = upload.parseRequest(req);
        for (FileItem fileItem : fileItems) {
            //判断上传的文件是普通表单还是带文件的表单
            if (fileItem.isFormField()) {
                String name = fileItem.getFieldName();
                String value = fileItem.getString("UTF-8");
                System.out.println("name:" + name + " value:" + value);
            } else {
                //判断它是上传的文件
                //==========================处理文件============================
                //拿到文件名字
                String uploadFileName = fileItem.getName();
                System.out.println("上传的文件名:" + uploadFileName);
                if (uploadFileName.trim().equals("") || uploadFileName == null) {
                    continue;
                }
                //获得上传的文件名
                String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
                //获得文件的后缀名
                String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
                System.out.println("文件信息【文件名:" + fileName + "  文件类型:" + fileExtName + "】");
                //可以使用UUID,保证文件名唯一
                //UUID.randomUUID(),随机生一个唯一识别的通用码
                String uuidPath = UUID.randomUUID().toString();

                //==========================存放地址============================
                //文件真实存在的路径realPath
                String realPath = uploadPath + "/" + uuidPath;
                //给每个文件创建一个对应的文件夹
                File realPathFile = new File(realPath);
                if (!realPathFile.exists()) {
                    realPathFile.mkdir();
                }
                //==========================文件传输============================
                //获得文件上传的流
                InputStream inputStream = fileItem.getInputStream();
                //创建一个文件输出流
                FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName);
                //创建一个缓冲区
                byte[] buffer = new byte[1024 * 1024];
                //判断是否读取完毕
                int len = 0;
                //如果大于0说明还存在数据
                while ((len = inputStream.read(buffer)) > 0) {
                    fos.write(buffer, 0, len);
                }
                //关闭流
                fos.close();
                inputStream.close();
                msg = "文件上传成功!";
                fileItem.delete();//上传成功,清除临时文件
            }
        }
        return msg;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值