Servlet基础

方式一:通过@WebServlet绑定

绑定某个servlet
@WebServlet(name = “helloServlet”, value = “/hello-servlet”)
(说明:helloServlet为sevlet的类名,hello-servlet为访问的名称)

绑定所有servlet
@WebFilter(filterName=”log”,urlPatterns=”/*”)

http://localhost:8080/hello-servlet

方式二:通过web.xml中绑定

<servlet>
    <servlet-name>HelloServlet</servlet-name>
    <servlet-class>com.example.demo1.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>HelloServlet</servlet-name>
    <url-pattern>/servlet/HelloServlet</url-pattern>
</servlet-mapping>

http://localhost:8080/servlet/HelloServlet

新建第二个servlet

此时,访问地址:http://localhost:8080/Servlet02

如何配置默认首页

一、在web.xml文件中加入:

<welcome-file-list>
    <welcome-file>myIndex.jsp</welcome-file>
</welcome-file-list>

此时项目打开的默认页面就是myIndex.jsp

二、在WebContent文件夹下添加index.jsp文件
此时这个index.jsp页面就是我们想要默认进入的页面
默认的配置如下:
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>

Servlet生命周期

  • init() 方法——一般不用管
  • service() 方法——不用管
  • doGet() 方法
  • doPost() 方法
  • destroy() 方法——一般不用管

获取请求参数:

适用:get和post携带的参数

  //获取请求参数:name
        response.setContentType("text/html;charset=UTF-8");
        String name =new String(request.getParameter("name").getBytes("ISO-8859-1"),"UTF-8");
        System.out.println("请求参数:name"+name);

获取请求的json数据

 /**
     * 获取请求的json
     * @param request
     * @return
     */
    public String getJsosonData(HttpServletRequest request){
        String acceptjson = "";
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader( (ServletInputStream) request.getInputStream(), "utf-8"));
            StringBuffer sb = new StringBuffer("");
            String temp;
            while ((temp = br.readLine()) != null) {
                sb.append(temp);
            }
            br.close();
            acceptjson = sb.toString();
            System.out.print(acceptjson);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return acceptjson;
    }

获取post过来的文件(post表单文件方式):

需要导入包:

 <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
      <dependency>
          <groupId>commons-fileupload</groupId>
          <artifactId>commons-fileupload</artifactId>
          <version>1.3.3</version>
      </dependency>

      <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
      <dependency>
          <groupId>commons-io</groupId>
          <artifactId>commons-io</artifactId>
          <version>2.6</version>
      </dependency>

Servlet具体代码

@WebServlet(name = "ServletFile", value = "/ServletFile")
public class ServletFile extends HttpServlet {

    // 上传文件存储目录
    private static final String UPLOAD_DIRECTORY = "upload";

    // 上传配置
    private static final int MEMORY_THRESHOLD   = 1024 * 1024 * 3;  // 3MB
    private static final int MAX_FILE_SIZE      = 1024 * 1024 * 40; // 40MB
    private static final int MAX_REQUEST_SIZE   = 1024 * 1024 * 50; // 50MB

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {


        System.out.println("收到文件上传请求");

        PrintWriter out = response.getWriter();

        // 配置上传参数
        DiskFileItemFactory factory = new DiskFileItemFactory();
        // 设置内存临界值 - 超过后将产生临时文件并存储于临时目录中
        factory.setSizeThreshold(MEMORY_THRESHOLD);
        // 设置临时存储目录
        factory.setRepository(new File(System.getProperty("java.io.tmpdir")));

        ServletFileUpload upload = new ServletFileUpload(factory);

        // 设置最大文件上传值
        upload.setFileSizeMax(MAX_FILE_SIZE);

        // 设置最大请求值 (包含文件和表单数据)
        upload.setSizeMax(MAX_REQUEST_SIZE);

        // 中文处理
        upload.setHeaderEncoding("UTF-8");

        // 构造临时路径来存储上传的文件
        // 这个路径相对当前应用的目录
        String uploadPath = request.getServletContext().getRealPath("./") + File.separator + UPLOAD_DIRECTORY;


        // 如果目录不存在则创建
        File uploadDir = new File(uploadPath);
        if (!uploadDir.exists()) {
            uploadDir.mkdir();
        }

        try {
            // 解析请求的内容提取文件数据
            @SuppressWarnings("unchecked")
            List<FileItem> formItems = upload.parseRequest(request);

            if (formItems != null && formItems.size() > 0) {
                // 迭代表单数据
                for (FileItem item : formItems) {
                    // 处理不在表单中的字段
                    if (!item.isFormField()) {
                        String fileName = new File(item.getName()).getName();
                        String filePath = uploadPath + File.separator + fileName;
                        File storeFile = new File(filePath);
                        // 在控制台输出文件的上传路径
                        System.out.println(filePath);
                        // 保存文件到硬盘
                        item.write(storeFile);

                        out.println("文件上传成功!"+uploadPath);
                        System.out.println("文件上传成功!"+uploadPath);
                    }
                }
            }
        } catch (Exception ex) {

            out.println("文件上传失败:"+"错误信息: " + ex.getMessage());
            System.out.println("文件上传失败:"+"错误信息: " + ex.getMessage());

        }

    }
}

回复请求参数的两种方式:

方式1:

 PrintWriter out = response.getWriter();
 out.println("缺少参数Name!");

方式2:

 PrintWriter out = response.getWriter();
 out.write("缺少参数Name!");

两种方式区别:
https://blog.csdn.net/javaloveiphone/article/details/8133772

  • out.write()是字节输出流的方法
  • out.print()是字符输出流的方法

回复请求乱码问题:

在servlet的response中设置

response.setContentType("text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8");

请求重定向

// 设置响应内容类型
      response.setContentType("text/html;charset=UTF-8");

      // 要重定向的新位置
      String site = new String("http://www.runoob.com");

      response.setStatus(response.SC_MOVED_TEMPORARILY);
      response.setHeader("Location", site);

Servlet的Filter

常见用法

1.Session管理

2.权限验证

3.日志记录

4.字符编码转换

//https://blog.csdn.net/huoguang_/article/details/88783381

绑定方式一:注解方式绑定相应的servlet

urlPatterns = { “/hello-servlet” }

绑定方式二:web.xml 中绑定

  <filter>
        <filter-name>Filter01</filter-name>
        <filter-class>com.example.demo1.Filter01</filter-class>

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

filter示范:字符编码转换

@WebFilter(filterName = "Filter01",urlPatterns = { "/hello-servlet" })
public class Filter01 implements Filter {
    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }


    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("EncodingFilter执行了:");
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        chain.doFilter(request, response);
    }

}

filter示范:日志

@WebFilter(filterName = "FilterLog",urlPatterns ="/*")
public class FilterLog implements Filter {

    private Log log = LogFactory.getLog(getClass());//log对象
    private String filterName;



    public void destroy() {
        log.info("关闭Filter:"+filterName);
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        String referer = req.getHeader("referer");
        long startTime = System.currentTimeMillis();
        String requestUrl = req.getRequestURI();
        requestUrl = req.getQueryString() == null ?requestUrl:(requestUrl+"?"+req.getQueryString());//所有的地址栏参数

        chain.doFilter(req, res);
        long endTime = System.currentTimeMillis();
        System.out.println(request.getRemoteAddr()+"访问了"+requestUrl+",=总用时"+(endTime-startTime)+"毫秒。");

        log.info(request.getRemoteAddr()+"访问了"+requestUrl+",=总用时"+(endTime-startTime)+"毫秒。");
        this.destroy();

    }

    public void init(FilterConfig fConfig) throws ServletException {
        filterName = fConfig.getFilterName();//获取Filter名称
        log.info("启动Filter:"+filterName);
    }


}

设置中央参考Marven地址

pom.xml文件中添加

  <repositories>
        <repository>
            <id>alimaven</id>
            <name>Maven Aliyun Mirror</name>
            <url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

servlet异步请求注意

//需要添加  asyncSupported=true
@WebServlet(name = "api/order/pay", value = "/api/order/pay" ,asyncSupported=true)
public class pay extends HttpServlet {


//如果有过滤器,过滤器中也要添加
@WebFilter(filterName = "UserFilter",urlPatterns ="/*",asyncSupported=true)
public class UserFilter implements Filter {


//然后进行异步操作
     AsyncContext asyncContext = request.startAsync();
                            asyncContext.start(new Runnable() {
                                @Override
                                public void run() {
                                    try {
                                        Thread.sleep(5000); //这里表示要进行的异步操作
                                        asyncContext.getResponse().getWriter().write("Hello World!");
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }
                                    asyncContext.complete();

                                }
                            });

文件上传和下载

1.导入jar包

commons-io-2.6.jar
commons-fileupload-1.4.jar

文件上传源码:

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;

public class FileServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 判断上传的文件普通表单还是带文件的表单
        if (!ServletFileUpload.isMultipartContent(request)) {
            return;//终止方法运行,说明这是一个普通的表单,直接返回
        }
        //创建上传文件的保存路径,建议在WEB-INF路径下,安全,用户无法直接访间上传的文件;
        String uploadPath =this.getServletContext().getRealPath("/WEB-INF/upload");
        File uploadFile = new File(uploadPath);
        if (!uploadFile.exists()){
            uploadFile.mkdir(); //创建这个目录
        }
        //缓存,临时文件
        //临时路径,假如文件超过了预期的大小,我们就把他放在一个临时文件中,过几天自动删除,或者提醒用户转为永久
        String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
        File tmpFile = new File(tmpPath);
        if (!tmpFile.exists()) {
            tmpFile.mkdir();//创建这个临时目录
        }

        // 处理上传的文件,一般都需要通过流来获取,我们可以使用 request.getInputstream(),原生态的文件上传流获取,十分麻烦
        // 但是建议使用 Apache的文件上传组件来实现, common-fileupload,它需要依赖于commons-io组件;
        try {
            // 1、创建DiskFileItemFactory对象,处理文件路径或者大小限制
            DiskFileItemFactory factory = getDiskFileItemFactory(tmpFile);

            // 2、获取ServletFileUpload
            ServletFileUpload upload = getServletFileUpload(factory);

            // 3、处理上传文件
            // 把前端请求解析,封装成FileItem对象,需要从ServletFileUpload对象中获取
            String msg = uploadParseRequest(upload, request, uploadPath);

            // Servlet请求转发消息
            System.out.println(msg);
            if(msg.equals("文件上传成功!")) {
                // Servlet请求转发消息
                request.setAttribute("msg",msg);
                request.getRequestDispatcher("info.jsp").forward(request, response);
            }else {
                msg ="请上传文件";
                request.setAttribute("msg",msg);
                //转发
                request.getRequestDispatcher("info.jsp").forward(request, response);
            }

        } catch (FileUploadException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }

    }
    // 1、创建DiskFileItemFactory对象,处理文件路径或者大小限制
    /*
     * 通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,
     * 将他放到临时文件 factory.setSizeThreshold(1024 *1024);
     * 缓存区大小为1M factory.setRepository (file);//临时目录的保存目录,需要一个File
     */
    public static DiskFileItemFactory getDiskFileItemFactory(File file) {
        DiskFileItemFactory factory = new DiskFileItemFactory();
        // 通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件中;
        factory.setSizeThreshold(1024 * 1024);// 缓冲区大小为1M
        factory.setRepository(file);// 临时目录的保存目录,需要一个file
        return factory;
    }
    // 2、获取ServletFileUpload
    public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
        ServletFileUpload upload = new ServletFileUpload(factory);
        // 监听文件上传进度
        upload.setProgressListener(new ProgressListener() {

            // pBYtesRead:已读取到的文件大小
            // pContextLength:文件大小
            public void update(long pBytesRead, long pContentLength, int pItems) {
                System.out.println("总大小:" + pContentLength + "已上传:" + pBytesRead);
            }
        });

        // 处理乱码问题
        upload.setHeaderEncoding("UTF-8");
        // 设置单个文件的最大值
        upload.setFileSizeMax(1024 * 1024 * 10);
        // 设置总共能够上传文件的大小
        // 1024 = 1kb * 1024 = 1M * 10 = 10м
        upload.setSizeMax(1024*1024*10);

        return upload;
    }
    // 3、处理上传文件
    //把前端请求解析,封装成FileItem对象,需要从ServletFileUpload对象中获取
    public static String uploadParseRequest(ServletFileUpload upload, HttpServletRequest request, String uploadPath)
            throws FileUploadException, IOException {

        String msg = "";

        // 把前端请求解析,封装成FileItem对象
        List<FileItem> fileItems = upload.parseRequest(request);
        for (FileItem fileItem : fileItems) {
            //fileItem每一个表单对象
            if (fileItem.isFormField()) {// 判断上传的文件是普通的表单还是带文件的表单
                // getFieldName指的是前端表单控件的name;
                String name = fileItem.getFieldName();
                String value = fileItem.getString("UTF-8"); // 处理乱码
                System.out.println(name + ": " + value);
            } else {// 判断它是上传的文件

                // ============处理文件==============

                // 拿到文件名
                String uploadFileName = fileItem.getName();
                System.out.println("上传的文件名: " + uploadFileName);
                if (uploadFileName.trim().equals("") || uploadFileName == null) {
                    continue;
                }

                // 获得上传的文件名/images/girl/paojie.png
                String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
                // 获得文件的后缀名
                String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);

                /*
                 * 如果文件后缀名fileExtName不是我们所需要的 就直按return.不处理,告诉用户文件类型不对。
                 */

                System.out.println("文件信息[件名: " + fileName + " ---文件类型" + fileExtName + "]");
                // 可以使用UID(唯一识别的通用码),保证文件名唯一
                // 0UID. randomUUID(),随机生一个唯一识别的通用码;
                String uuidPath = UUID.randomUUID().toString();

                // ================处理文件完毕==============

                // 存到哪? uploadPath
                // 文件真实存在的路径realPath
                String realPath = uploadPath + "/" + uuidPath;
                // 给每个文件创建一个对应的文件夹
                File realPathFile = new File(realPath);
                if (!realPathFile.exists()) {
                    realPathFile.mkdir();
                }
                // ==============存放地址完毕==============


                // 获得文件上传的流
                InputStream inputStream = fileItem.getInputStream();
                // 创建一个文件输出流
                // realPath =真实的文件夹;
                // 差了一个文件;加上翰出文件的名产"/"+uuidFileName
                FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName);
                System.out.println("path:"+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;
    }

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

文件下载源码:

@WebServlet(name = "api/file/down", value = "/api/file/down")
public class down extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            //处理请求
            //读取要下载的文件
            File f = new File("E:/好久不见.mp3");
            if(f.exists()){
                FileInputStream fis = new FileInputStream(f);
                String filename= URLEncoder.encode(f.getName(),"utf-8"); //解决中文文件名下载后乱码的问题
                byte[] b = new byte[fis.available()];
                fis.read(b);
                response.setCharacterEncoding("utf-8");
                response.setHeader("Content-Disposition","attachment; filename="+filename+"");
                //获取响应报文输出流对象
                ServletOutputStream out =response.getOutputStream();
                //输出
                out.write(b);
                out.flush();
                out.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}