springMVC学习--day02

响应

返回字符串以及void的情况

1.返回字符串
<br>
<a href="responseController/returnString">returnString</a>
<br>
2.没有返回值
<br>
<a href="responseController/returnVoid">returnVoid</a>
<br>
3.没有返回值,转发
<br>
<a href="responseController/returnVoidAndDispatcher">returnVoidAndDispatcher</a>
<br>
4.没有返回值,重定向
<br>
<a href="responseController/returnVoidAndResponse">returnVoidAndResponse</a>
<br>
5.没有返回值,转发到同一个控制器的其他映射方法
<br>
<a href="responseController/returnVoidAndDispatcherToConreoller">returnVoidAndDispatcherToConreoller</a>
<br>
6.没有返回值,重定向到其他控制器的其他映射方法
<br>
<a href="responseController/returnVoidAndDispatcherToConreoller2">returnVoidAndDispatcherToConreoller2</a>
<br>
@RequestMapping("/responseController")
@Controller("responseController")
public class _06ResponseController {
    /**
     * 1.测试返回字符串类型
     * 指的是返回逻辑结果视图名称
     * springMVC会以此返回值作为文件名,到视图解析器里面进行拼接成JSP页面,并最终跳转到该页面
     */
    @RequestMapping("/returnString")
    public static String returnString() {
        return "sucess";
    }

    /**
     * 2.没有返回值
     * 当我们的方法返回值是void时,springMVC会把@RequestMapping()里面的映射路径名作为返回值去视图解析器解析查找对应的页面
     * 例如,这里会:HTTP Status 404 - /springMVC_war/WEB-INF/pages/responseController/returnVoid.jsp
     * 我们可以通过转发或者重定向跳转到指定的JSP页面或者其他的映射方法(控制器)里面
     */
    @RequestMapping("/returnVoid")
    public static void returnVoids() {
        System.out.println("returnVoid方法执行");
    }

    /**
     * 2.1.转发到jsp
     */
    @RequestMapping("/returnVoidAndDispatcher")
    public static void returnVoidAndDispatcher(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//        /WEB-INF/下面的地址是服务器内部地址,我们使用转发访问
        request.getRequestDispatcher("/WEB-INF/pages/sucess.jsp").forward(request, response);
    }

    /**
     * 2.2重定向到jsp
     */
    @RequestMapping("/returnVoidAndResponse")
    public static void returnVoidAndResponse(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//      重定向的方式只能访问服务器外部资源,所有我们在/WEB-INF/文件夹之外新建一个redirectView.jsp页面
        System.out.println(request.getContextPath());
        response.sendRedirect(request.getContextPath() + "/redirectView.jsp");
    }

    /**
     * 2.3转发或者重定向到本控制器的其他控制方法
     */
    @RequestMapping("/returnVoidAndDispatcherToConreoller")
    public static void returnVoidAndDispatcherToConreoller(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//        转发到同一个Controller下面的其他控制器方法(浏览器地址栏还是:***/responseController/returnVoidAndDispatcherToConreoller
        request.getRequestDispatcher("returnString").forward(request, response);
        //也可以使用重定向方法(浏览器地址栏变为:***/responseController/returnString
//        response.sendRedirect("returnString");
    }

    /**
     * 2.4重定向其他控制器
     * 跳转到其他控制器只能用重定向
     */
    @RequestMapping("/returnVoidAndDispatcherToConreoller2")
    public static void returnVoidAndDispatcherToConreoller2(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//        重定向到其他Controller下面的控制器方法
//        response.sendRedirect("test/hello");//不可用
//        重定向其他Controller需要加request.getContextPath(),否则只会在本Controller下面寻找目标路径
        response.sendRedirect(request.getContextPath() + "/test/hello");
    }
}

原始servlet -API把响应数据带回浏览器

    /**
     * 3.1.转发到jsp并传值
     */
    @RequestMapping("/returnValue")
    public static void returnValue(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//        /WEB-INF/下面的地址是服务器内部地址,我们使用转发访问
        request.setAttribute("username", "李沁");
        request.setAttribute("password", "123456");
        request.getRequestDispatcher("/WEB-INF/pages/sucess.jsp").forward(request, response);
    }
<html>
<head>
    <title>成功页面</title>
</head>
<body>
执行成功
<%--
    JSP四大域对象:
         page域           PageContext         最小页面范围,出了当前页面就失效
         request域        ServletRequest      当前请求和当前请求的转发                  一次请求用
         session域        HttpSession         一次会话                                多次请求用
         application域    ServletContext      最大整个应用

     --%>
后台传过来的username:${username}<%--相当于pageContext的getAttribute方法--%>
后台传过来的password:${requestScope.password}<%--明确从请求域中获取数据--%>
</body>
</html>

ModelAndView

/**
 * 4.ModelAndView
 *      返回ModelAndView,该对象是spring为我们提供的可以存放响应数据的对象。
 *   它里面有两个方法:
 *      setViewName:用于设置逻辑结果视图名称
 *      addObject(String,Object):用于设置响应正文的内容。存放的结构是key=value的形式。存入的位置是请求域中
 */
@RequestMapping("/returnModelAndView")
public ModelAndView returnModelAndView(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    ModelAndView modelAndView = new ModelAndView();
    ArrayList<String> list = new ArrayList<>();
    list.add("1");
    list.add("2");
    list.add("3");
    modelAndView.addObject("list",list);
    modelAndView.setViewName("modelAndView");
    return modelAndView;
}
modelAndView.jsp:
<%--导入jstl--%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>modelAndView</title>
</head>
<body>
${list}
${requestScope.list}
<c:forEach items="${list}" var="str">
    ${str}
</c:forEach>
</body>
</html>

springMVC的转发和重定向

    /**
     * springmvc的请求转发:
      */
    @RequestMapping("/springmvcDispatcher")
    public static String springmvcDispatcher() {
//        简写:写的是逻辑结果视图名称
//        return "sucess";
//        完整写法:写的是物理视图地址
        return "forward:/WEB-INF/pages/sucess.jsp";
    }
    /**
     * springmvc的请求重定向:
      */
    @RequestMapping("/springmvcRedirect")
    public static String springmvcRedirect() {
//        return "forward:/WEB-INF/pages/sucess.jsp";///WEB-INF/下面的内容我们是无法重定向进去的,下面我们演示重定向到springmvcDispatcher这个方法映射
        return "redirect:springmvcDispatcher";
    }

JSON数据的发送和返回

@ResponseBody:
@RequestBody:
<html>
<head>
    <title>responseJson</title>
</head>
<script src="${pageContext.request.contextPath}/js/jquery-3.1.1.js"></script>
<script>
    $(function () {
        $("#getJson").click(function () {
            alert(1)
            $.ajax({
                type: "post",//请求的方式
                url: "${pageContext.request.contextPath}/responseController/returnJson",//请求的地址
                dataType: "json",//响应的数据格式
                data: '{"id":1,"name":"李沁"}',//请求的正文(请求的参数)
                contentType: "application/json;charset=utf-8",//请求参数的格式
                success: function (data) {//执行成功后的回调函数
                    alert(data)
                }
            })
        })
    })

</script>
<body>
returnJson测试响应ison数据
<br>
<input type="button" value="提交" id="getJson">
</body>
</html>

依赖支持:

<!--    导入json支持jar-->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.9.6</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.9.6</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.6</version>
    </dependency>
    /**
     * 7.测试响应ison数据
     * 应用场景:
     *      一般都是异步请求,不希望浏览器刷新。
     *      @ResponseBody:将返回值的对象封装成json格式之后返回
     *      @RequestBody:将前台传递过来的json字符串封装成对应的对象
     */
    @RequestMapping("/returnJson")
    public @ResponseBody Account returnJson(@RequestBody Account accountJson) {
        System.out.println(accountJson);
        return accountJson;
    }

 文件上传:

1.传统方式:

参考:https://www.cnblogs.com/luzhanshi/p/13285516.html

2.springMVC提供的方式:

所需依赖:

<!--    上传文件所需jar包-->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.3</version>
    </dependency>
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.4</version>
    </dependency>

springMVC.xml新增配置:

<!--    配置springmvc提供的文件解析器-->
<!--    注意:!!!下面的id只能是multipartResolver!!!-->
    <bean  id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--        配置上传文件的最大尺寸为10M-->
        <property name="maxUploadSize">
            <value>10240000</value>
        </property>
    </bean>

前台代码:

<body>
<form action="springMVCfileUploadController/fileUploadtest" method="post"  enctype="multipart/form-data">
   名称: <input type="text" name="text"><br>
   图片:<input type="file" name="file" multiple="multiple" accept="image/png,image/gif,image/jpeg, image/jp2,.txt" ><br>
    <input type="submit"><br>
</form>
</body>

后台代码:

@RequestMapping("/springMVCfileUploadController")
@Controller("springMVCfileUploadController")
public class _08springmvcFileUploadController {
    @RequestMapping("/fileUploadtest")
    public ModelAndView fileUploadtest(String text, MultipartFile file, HttpServletRequest request) throws Exception {
        System.out.println("文件上传方法执行了");
        System.out.println(text);
//        1.设置保存目录
        File fatherDir = new File("D:\\fileUpload");
//        2.为防止文件过多,以日期为名创建子文件夹储存位置
        String childDir = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        File targetDir = new File(fatherDir, childDir);
        if (!targetDir.exists()) {
            targetDir.mkdirs();
        }
//        3.获取上传文件名,并随机化
        String fileName = file.getOriginalFilename();
        String uuid = UUID.randomUUID().toString();
        String newFileName = uuid + "_" + fileName;
//        4.写入文件
        file.transferTo(new File(targetDir, newFileName));
       
        return "sucess";
    }
}

3.springMVC跨服务器上传:

在实际开发中,我们会有很多处理不同功能的服务器。例如:
应用服务器:负责部署我们的应用

数据库服务器:运行我们的数据库
缓存和消息服务器:负责处理大并发访问的缓存和消息

文件服务器:负责存储用户上传文件的服务器。
(注意:此处说的不是服务器集群)

分服务器处理的目的是让服务器各司其职,从而提高我们项目的运行效率。

所需依赖:

<!--    上传文件所需jar包-->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.3</version>
    </dependency>
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.4</version>
    </dependency>
<!--    跨域上传文件额外所需jar包-->
    <!-- https://mvnrepository.com/artifact/com.sun.jersey/jersey-core -->
    <dependency>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-core</artifactId>
<!--      我们一般在第二行直接写jar的名字,静静地等待maven给我们提示,然后回车补全,搞定-->
      <version>1.18.1</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.sun.jersey/jersey-client -->
    <dependency>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-client</artifactId>
      <version>1.18.1</version>
    </dependency>

导入jersey 失败?请参考https://www.cnblogs.com/luzhanshi/p/13286405.html解决

springMVC.xml同样要新增配置:

<!--    配置springmvc提供的文件解析器-->
<!--    注意:!!!下面的id只能是multipartResolver!!!-->
    <bean  id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--        配置上传文件的最大尺寸为10M-->
        <property name="maxUploadSize">
            <value>10240000</value>
        </property>
    </bean>

接收文件的Tomact服务器安装目录下的conf/web.xml配置文件中加上:(使得服务器允许文件写入。)

 <init-param>
        <param-name>readonly</param-name>
        <param-value>false</param-value>
    </init-param>

否则会报如下错误:

 接收文件的服务器项目要保证有如下目录:

否则会报如下错误:PUT http://localhost:9090/fileServer_War/upload/20160515104302348740.jpg returned a response status of 409 Conflict

 发送文件前台代码:

<form action="springMVCTwoServerfileUploadController/fileUploadtest" method="post"  enctype="multipart/form-data">
   名称: <input type="text" name="text"><br>
   图片:<input type="file" name="file" multiple="multiple" accept="image/png,image/gif,image/jpeg, image/jp2" ><br>
    <input type="submit"><br>
</form>

 发送文件后台代码:

@RequestMapping("/springMVCTwoServerfileUploadController")
@Controller("springMVCTwoServerfileUploadController")
public class _08springmvcTwoServerFileUploadController {
    //    全局定义图片服务器路径
    private static final String FILESERVERPATH = "http://localhost:9090/fileServer_war/upload/";

    @RequestMapping("/fileUploadtest")
    public String fileUploadtest(String text, MultipartFile file, HttpServletRequest request) throws Exception {
        System.out.println("文件上传方法执行了");
        System.out.println(text);
//        1.获取上传文件名,并随机化
        String fileName = file.getOriginalFilename();
        String uuid = UUID.randomUUID().toString();
        String newFileName = uuid + "_" + fileName;
//        2.获取jersey的jar包中提供的Client对象
        Client client = Client.create();
//        3.建立和图片服务器的联系
        WebResource resource = client.resource(FILESERVERPATH + newFileName);
//        4.把文件写到远程服务器(String.class决定返回值类型)
        String s = resource.put(String.class, file.getBytes());
        System.out.println(s);
        return "sucess";
    }
}

演示效果

 最后一定要去tomcat发布项目的目录下去查看文件是否上传成功!!!不要傻傻的去项目里面的upload目录下去看

 自定义异常:

1.创建自定义异常类

/**
 * 客户自定义异常类;继承RuntimeException或者Exception
 */
public class MyException extends RuntimeException {
//    定义异常信息
    private String msg;
//通过构造方法获取异常信息
    public MyException(String msg) {
        this.msg = msg;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

2.创建自定义异常处理器:

/**
 * 自定义异常处理器(需要实现:HandlerExceptionResolver)
 * 并且要注册为speing组件,对象的创建交给speing容器管理,可以使用下面注解的方式,也可以在speingMVC.xml里面配置bean:<bean id="myExceptionResolver" class="web.pojo.MyExceptionResolver"></bean>
 */
@Component("myExceptionResolver")
public class MyExceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) {
//        打印异常信息
        e.printStackTrace();
//        定义自己的异常类对象
        MyException myException = null;
//        判断当前传入的异常对象是否是我们的自定义对象对象
        if (e instanceof MyException) {//如果是,我们就直接强转为我们自定义的异常类型
            myException = (MyException) e;
        } else {//否则就获取该异常的异常信息创建我们的自定义异常
            myException = new MyException(e.getMessage());
        }
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("error");
        modelAndView.addObject("errorMsg", myException.getMsg());
        return modelAndView;
    }
}

3.新建统一错误信息展示页面:

<html>
<head>
    <title>失败页面</title>
</head>
<body>
<%--注意!!!下面的"errorMsg"要和我们自定义异常处理器里面返回的错误信息字段名一致--%>
${errorMsg};
</body>
</html>

4.测试代码:

@RequestMapping("/exceptionController")
@Controller("exceptionController")
public class _10exceptionController {
    @RequestMapping("testException")
    public String testException(String name) throws MyException {
        System.out.println("测试异常方法执行了"+name);
        if (StringUtils.isEmpty(name))
        throw new RuntimeException("用户名不能为空");
//        throw new MyException("用户名不能为空");//也可以抛出我们自定义异常
        return "sucess";
    }
}

自定义拦截器:

拦截器:

Spring MVC的处理器拦截器类似于Servlet开发中的过滤器Filter用于对处理器进行预处理和后处理。用户可以自己定义一些拦 截器来实现特定的功能。

谈到拦截器;还要向太家提一个词一 拦截器链( Interceptor Chain)。 拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。

说到这里,可能大家脑海中有了一个疑问;这不是我们之前学的过滤器吗?是的它和过滤器是有几分相似,但是也有区别,接下来我们就来说说他们的区别:

过滤器是Servlet规范中的一-部分,任何iava web工程都可以使用。

拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能用。

过滤器在url-pattern中配置了/*之后:可以对所有要访问的资源拦截。

拦截器它是只会拦截访问的控制器方法,如果访问的是j3R: html, ce image或者ia是不会进行拦

截的。

它也是AOP思想的具体应用。

我们要想自定义拦截器,要求必须实现: HandlerInterceptor接只。

 举例:假如我们要对用户访问下面的路径的时候要验证用户是否已经登录,没有登录不可以访问:

@RequestMapping("/interceptorController")
@Controller("interceptorController")
public class _11interceptorController {
    @RequestMapping("/testInterceptor")
    public String testInterceptor(String name)  {
        System.out.println("控制器中方法执行了"+name+" 说明用户登录了");
        return "sucess";
    }
}

首先我们要编写一个拦截器:

//自定义拦截器实现HandlerInterceptor并重写所有的方法
public class CheckLoginInterceptor implements HandlerInterceptor {
    /**
     * preHandle
     * 当请求到达时,先执行此方法。
     * 此方法的返回值决定了是否放行
     * 返回true:放行放行的含义:如果有下一个拦截器执行下一个,如果该拦截器处于最后一个,则执行handler方法(控制器中的方法)
     * 返回false:不放行
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle方法执行了");
//       1. 获取Session对象
        HttpSession session = request.getSession();
//       2. 判断session域中是否有登录标记
        Object userinfo = session.getAttribute("userinfo");
        if (userinfo != null) {
            return true;
        }
        //        没有登录信息的情况下    跳转到登录页面
        request.getRequestDispatcher("/WEB-INF/pages/login.jsp").forward(request, response);
        return false;
    }

    /**
     * postHandle
     * 如何调用:
     * 按拦截器定义逆序调用
     * 何时调用:
     * 在拦截器链内所有拦戴器返成功调用
     * 有什么用:
     * 在业务处理器处理完请求后,但是DiapatcherServlet向客户端返回响应前,在该方法中对用户请求request进行处理。
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle方法执行了");
    }

    /**
     * afterCompletion
     * 如何调用:
     * 按拦截器定义逆序调用
     * 何时调用:
     * 只有preHandle返回true才调用
     * 有什么用:
     * 在DiapatcherServlet完全处理完请求后被调用,可以在该方法中进行一些资源清理的操作。
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion方法执行了");
    }
}

然后我们需要在springMVC.xml里面配置拦截器:

<!--配置自定义拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
<!-- path="/interceptorController/**":表示拦截  interceptorController下面的所有映射路径         -->
            <mvc:mapping path="/interceptorController/**"/>
            <bean class="web.pojo.CheckLoginInterceptor" id="myInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>
</beans>

我们的登录login.jsp:

<body>
<a href="${pageContext.request.contextPath}/login/userLogin">登录</a>
<%--${pageContext.request.contextPath}:springMVC_war(项目的根目录)--%>
</body>

登录的Controller代码:

@Controller("loginController")
@RequestMapping("/login")
public class LoginController {
    @RequestMapping("/userLogin")
    public String userLogin(HttpServletRequest request) {
//        1.获取session
        request.getSession().setAttribute("userinfo", "...");
        return "redirect:/main.jsp";
    }
}

main.jsp:

<body>
主页
</body>

 上述文件的位置:

 

 
posted @ 2020-07-11 00:30  指尖下的世界  阅读(207)  评论(0编辑  收藏  举报
/* 看板娘 */ /*炸泡*/
/* 鼠标点击求赞文字特效 */