JavaWeb项目中用Servlet实现学生签到和下载文件功能,过程中遇到了一些路径上的问题,做个总结。

目录结构:

 

基于Java实现签到打卡 javaweb签到功能_ide

 

 

学生签到实验(将从前端收到的学生签到信息记录在指定文件中,向login.txt中记录学生签到信息):
1多次试验发现,用相对路径(String path="/login.txt")可以找到文件,但是写不进去内容;
2、String path=this.getServletContext().getRealPath("/login.txt")方法获取绝对路径,可以写入,但是内容是记录在部署目录中原因如下:

输出this.getServletContext().getRealPath("/login.txt")(或去掉斜杠)语句,得
D:\myapps\my-ideaworksapce\JavaWebProject\out\artifacts\testServlet_war_exploded\StudentLoginServlet

可以看到,绝对路径被定位到了部署路径中。因为tomcat上运行的项目是编译、部署完成的项目

3、指定绝对路径D:\myapps\my-ideaworkspace\JavaWebProject\web\login.txt可以在该目录下的文件中写入内容,而且部署路径out/artifacts/testServlet_war_exploded/WEB-INF/classes/login.txt会与之同步
4tomcat重启时会重新部署目录,因此之前的记录信息在tomcat重启后会不复存在

5、在web中的反斜杠  /  

① 和网页跳转相关'/'代表服务器根路径(locallost8080/)开始定位

比如<a href=’/JavaWebProject/index.jsp’>跳转</a>

再比如重定向中的response.sendRedirect("/JavaWebProject/index.jsp");

注:请求转发的跳转页面是从项目根路径开始寻找的request.getRequestDispatcher("/index.jsp").forward(request, response);因为请求转发相当于已经在当前项目中的网页,现在要跳转到该项目中的另一个网页,所以是从当前项目的根目录寻找要跳转的页面。请求转发和重定向的区别需要清楚。

② java中的'/'代表项目部署后的项目根路径(localhost:8080//JavaWebProject)开始定位


下载文件实验:

① 

InputStream fin=this.getServletContext().getResourceAsStream("/downloads/" +filename);//成功!

② 

InputStream fin=new FileInputStream("/downloads/"+filename);//不起作用!

第一条语句可以将downloads中的文件作为字节流输出,并通过设置消息头提供下载功能,而二条语句却没有作用(无法在浏览器下载内容)。联系前面的实验结果“用相对路径(String path="/login.txt")可以找到文件,但是写不进去内容”。推测:Web项目无法直接通过相对路径进行流的操作


代码:

学生签到实验:

@WebServlet(urlPatterns = "/StudentLoginServlet" )
public class StudentLoginServlet extends HttpServlet {//直接继承Servlet类的话,this.getServletConfig.getServletContext.getRealPath()似乎有点问题
    PrintWriter fout=null;//输出流,用于将从前端收到的学生签到信息记录在指定文件中。全局变量,供整个对象使用
    ArrayList<String> idCheck=new ArrayList<>();//记录历史签到id
    ArrayList<String> ipCheck=new ArrayList<>();//记录历史签到ip
    @Override
    public void init() throws ServletException {
        String path="/login.txt";//文件路径
        File file=new File(this.getServletContext().getRealPath(path));
        try {
            fout=new PrintWriter(file);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

    }


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

//解决乱码问题
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        //获取表单数据
        String stuId=req.getParameter("stuId");
        String stuName=req.getParameter("stuName");
        String stuAge=req.getParameter("stuAge");
        //获取客户端的IP地址、签到时间
        String IP=req.getRemoteAddr();
        SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        String loginTime=format.format(new Date());
        //将登陆信息记录到日志文件中
        int index1=0;//判定id是否重复,0代表不重复,1代表重复
        int index2=0;//判定ip是否重复,0代表不重复,1代表重复
        if(fout!=null){
            synchronized (this){
                if(!idCheck.contains(stuId)&&!ipCheck.contains(IP)){
                    idCheck.add(stuId);
                    ipCheck.add(IP);
                    fout.println("学号为:"+stuId+",姓名是:"+stuName+",年龄是:"+stuAge+",IP地址为:"+IP+",签到时间为:"+loginTime);
                    fout.flush();
                }else if(idCheck.contains((stuId))){
                    index1=1;
                }else if(ipCheck.contains(IP)){
                    index2=1;
                }
            }
        }
        PrintWriter out=resp.getWriter();
        if(index1==0&&index2==0){
            out.println("签到成功!");
        }else if(index1==1){
            out.println("请勿重复签到!");
        }else{
            out.println("同一台机器只能签到一名同学!");
        }
    }
    @Override
    public void destroy() {
        if(fout!=null){
            fout.close();
        }
    }
}

 下载文件实验

public class ContextDownloadServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置相应头信息
        String filename=req.getParameter("filename");//接收文件名
        resp.setHeader("Content-Disposition","attachment;filename="+filename);
        //获取绝对路径
        String realpath=this.getServletContext().getRealPath("/downloads/" +filename);
        System.out.println(realpath);
        //发送文件
        InputStream fin=this.getServletContext().getResourceAsStream("/downloads/" +filename);//成功!
//        InputStream fin=new FileInputStream("/downloads/"+filename);//不起作用!
        OutputStream out=resp.getOutputStream();
        byte[] buff=new byte[1024];
        int len=-1;
        while ((len=fin.read(buff))!=-1){
            out.write(buff,0,len);
        }
        fin.close();
        out.close();
    }
}