没腿的鸟 发表于 2024-12-28 08:22:45

24.12.27 SpringMVCDay02


[*]

[*]enctype必须是 multipart/form-data

    <form action="/mvc/book/doUpload1" method="post" enctype="multipart/form-data">
      <p>
            <input type="file" name="img_url">
      </p>

      <p>
            <input type="submit" value="上传">
      </p>

    </form>
    @Autowired
    HttpServletRequest request;

    @PostMapping("/doUpload1")
    @ResponseBody
    public String doUpload1() throws ServletException, IOException {
      //获取Request对象
      //getPart(页面表单提交中,获取name=img_url的值
      Part part = request.getPart("img_url");
      //文件存哪里
      //D:\webFolder\mvcdemo1\target\mvcdemo\
      String realPath = request.getServletContext().getRealPath("/");
      //D:\webFolder\mvcdemo1\target\mvcdemo\/imgs/
      String basePath = realPath + "/imgs/";
      System.out.println(basePath);
      //文件夹是否存在
      File baseFile = new File(basePath);
      if (!baseFile.exists()){
            baseFile.mkdirs();
      }
      //文件名
      String fileName = part.getSubmittedFileName();
      part.write(basePath + fileName);
      return "success";
    } 多文件

multiple属性
<form action="/mvc/book/doUpload2" method="post" enctype="multipart/form-data">
      <p>
            <input type="file" name="img_url" multiple>
      </p>

      <p>
            <input type="submit" value="上传">
      </p>

    </form>
@PostMapping("/doUpload2")
    @ResponseBody
    public String doUpload2() throws ServletException, IOException {
      //获取 所有的文件
      Collection<Part> parts = request.getParts();
      String realPath = request.getServletContext().getRealPath("/imgs/");
      System.out.println(realPath);
      File realFile = new File(realPath);
      if (!realFile.exists()){
            realFile.mkdirs();
      }
      parts.forEach(part -> {
            String fileName = part.getSubmittedFileName();
            try {
                part.write(realPath +fileName);
            } catch (IOException e) {
                //不处理异常,仅仅是打印看看
                e.printStackTrace();
            }
      });
      return "success";
    } MVC方式上传文件



[*]引入依赖
    <dependency>
      <groupId>commons-fileupload</groupId>

      <artifactId>commons-fileupload</artifactId>

      <version>1.2.1</version>

    </dependency>

    <dependency>
      <groupId>commons-io</groupId>

      <artifactId>commons-io</artifactId>

      <version>1.4</version>

    </dependency>


[*]mvc.xml
    <!--上传文件的配置-->
    <bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
      <property name="defaultEncoding" value="utf-8"/>
    </bean>
单文件

    //img_url表单提交中的name属性
    @PostMapping("/doUpload3")
    @ResponseBody
    public String doUpload3(MultipartFile img_url) throws IOException {
      //文件名
      String fileName = img_url.getOriginalFilename();
      //获取保存路径
      String realPath = request.getServletContext().getRealPath("/imgs/");
      System.out.println(realPath);
      File realFile = new File(realPath);
      if (!realFile.exists()){
            realFile.mkdirs();
      }
      //文件对象.transferTo(存储的位置+文件名)
      img_url.transferTo(new File(realPath + fileName));

      return "success";
    } 多文件

    @PostMapping("/doUpload4")
    @ResponseBody
    public String doUpload4(MultipartFile[] img_url) throws IOException {
      if (img_url.length > 0){
            for (MultipartFile file : img_url){
                file.transferTo(new File(getFileName(file)));
            }
      }
      return "success";
    }

    private String getFileName(MultipartFile file){
      //文件名
      String fileName = file.getOriginalFilename();
      //获取保存路径
      String realPath = request.getServletContext().getRealPath("/imgs/");
      File realFile = new File(realPath);
      if (!realFile.exists()){
            realFile.mkdirs();
      }
      return realPath + fileName;
    } 文件下载

默认情况下,mvc框架,无法辨认静态资源文件的
超链接下载

<ul>
      <li>
            <a href="/mvc/save/test1.docx">word文档</a>

      </li>

      <li>
            <a href="/mvc/save/test2.jpg">图片</a>

      </li>

      <li>
            <a href="/mvc/save/test3.pdf">PDF</a>

      </li>

      <li>
            <a href="/mvc/save/test4.rar">压缩文件</a>

      </li>

      <li>
            <a href="/mvc/save/test5.xlsx">Excel</a>

      </li>

    </ul>
假如这个文件,欣赏支持,可以打开,就会直接在欣赏器中打开,不进行下载
假如这个文件,欣赏器无法打开,跳出下载页面
利益:简单,易学.写一个url地址超链接即可
弊端:仅能让部分格式的文件下载
流下载

这个下载 ,要经过服务器,让服务器写出文件流 给欣赏器,触发下载


[*]ResponseEntity
    @Autowired
    HttpServletRequest request;

    @GetMapping("/test1")
    public ResponseEntity<byte[]> download(String name) throws IOException {
      //获取文件路径
      String realPath = request.getServletContext().getRealPath("/save/");
      //文件的全路径
      String allPath = realPath + name;
      //获取下载需要的文件流信息
      FileInputStream inputStream = new FileInputStream(allPath);
      //获取流的数组
      byte[] buffer = new byte;
      //读取
      inputStream.read(buffer);
      //文件下载的时候,显示的名字,需要改文件名了,再修改
      //设置响应的头信息,告诉浏览器,返回的是文件
      HttpHeaders httpHeaders = new HttpHeaders();
      //设置响应的头信息,访问文件名中文乱码
      httpHeaders.setContentDispositionFormData("attachment", URLEncoder.encode(name,"utf-8"));
      ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(buffer,httpHeaders, HttpStatus.OK);
      return responseEntity;
    }

[*]HttpServletResponse
    @Autowired
    HttpServletResponse response;

    @GetMapping("/test2")
    public voiddownload2(String name) throws FileNotFoundException, UnsupportedEncodingException {
      //获取文件路径
      String realPath = request.getServletContext().getRealPath("/save/");
      //文件的全路径
      String allPath = realPath + name;
      //判断文件是否存在
      File file = new File(allPath);
      if (!file.exists()){
            throw new FileNotFoundException(name+"文件不存在");
      }
      //代码能执行到这一行,说明文件肯定存在
      //编码格式是utf-8的文件名
      
      String encodeFileName = URLEncoder.encode(name, StandardCharsets.UTF_8.toString());
      //设置头信息 header
      response.setHeader("Content-Disposition","attachment;filename*=UTF-8''"+encodeFileName);

      //使用 try--with --resources 关闭流
      try(FileInputStream inputStream = new FileInputStream(file);
            OutputStream outputStream = response.getOutputStream()){
            IOUtils.copy(inputStream,outputStream);
            outputStream.flush();
      } catch (IOException e) {
            throw new RuntimeException(e);
      }
    } 异常处置惩罚



[*]异常页面


[*]

[*]修改web.xml (会直接跳到这个页面)

<error-page>
    <location>/error.jsp</location>

</error-page>


[*]异常类
@Component
public class TestController implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request,
                                       HttpServletResponse response,
                                       Object o,
                                       Exception e) {
      //产生异常的时候,调用这个方法
      System.out.println(e.getMessage());
      e.printStackTrace();
      //配置返回值
      ModelAndView mv = new ModelAndView();
      mv.setViewName("game/success");//会直接跳到 webapp下的这个页面
      return mv;
    }
}

[*]@RestControllerAdvice
用来处置惩罚指定异常(自定义异常类)
@RestControllerAdvice
public class JavasmExceptionAdvice {
    //当ArithmeticException被抛出来的时候,执行当前方法
    @ExceptionHandler(ArithmeticException.class)
    public String f1(ArithmeticException e){
      System.out.println("算术异常");
      e.printStackTrace();
      //返回值,会代替原有方法的返回内容
      return e.getMessage();
    }

    //当抛出JavasmException的时候,执行当前方法
    @ExceptionHandler(JavasmException.class)
    public Map<String,Object> f2(JavasmException e){
      Map<String,Object> map = new HashMap<>();
      map.put("code",500);
      map.put("msg","自定义异常"+e.getMessage());
      return map;
    }
} public class JavasmException extends RuntimeException{

    public JavasmException() {
    }

    public JavasmException(String message) {
      super(message);
    }
} 拦截器

拦截器 和 过滤器 的区别是什么?
过滤器:web容器,不属于框架,哀求进入tomcat之后,先经过的就是过滤器
拦截器:属于spring容器,springweb中,属于 容器的servlet,相当于,Servlet内部的哀求拦截
https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=assets%2Fimage-20241227145848189.png&pos_id=O1tVGXLj
public class TestInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
      System.out.println("pre--xxx之前----在Controller的方法 执行之前");
      //返回的数据是Boolean类型,返回true,允许进入下一层(可能是下一个拦截器,也可能是Controller)
      //返回false????
      //response.getWriter().write("xxxx");
      return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
      System.out.println("post--xxx之后-----被访问的方法 执行结束之后,执行");

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
      System.out.println("页面渲染成功之后执行");
    }
} 案例登录拦截

public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
      //只有登录的用户才能访问系统
      HttpSession session = request.getSession();
      Object user = session.getAttribute("user");//登录的数据存在session,在这里取出
      if (user != null){
            //已经登录了
            return true;
      }
      Map<String,Object> map = new HashMap<>();
      map.put("code",2001);
      map.put("msg","未登录");
      String s = JSON.toJSONString(map);
      response.setContentType("application/json;charset=utf-8");//预防乱码
      PrintWriter writer = response.getWriter();
      writer.write(s);
      writer.flush();
      writer.close();
      return false;
    }
} <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xmlns:context="http://www.springframework.org/schema/context"       xmlns:mvc="http://www.springframework.org/schema/mvc"       xsi:schemaLocation="http://www.springframework.org/schema/beans       http://www.springframework.org/schema/beans/spring-beans.xsd      http://www.springframework.org/schema/context         https://www.springframework.org/schema/context/spring-context.xsd         http://www.springframework.org/schema/mvc         https://www.springframework.org/schema/mvc/spring-mvc.xsd">    <!--    开启包扫描-->    <context:component-scan base-package="com.javasm"/>    <!--代替适配器等配置-->    <mvc:annotation-driven/>    <!--视图解析器-->    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">      <!--跳转的jsp页面,统一添加前缀-->      <property name="prefix" value="/WEB-INF/"/>      <!--后缀-->      <property name="suffix" value=".jsp"/>    </bean>    <!--静态资源文件放过-->    <mvc:default-servlet-handler/>    <!--上传文件的配置-->
    <bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
      <property name="defaultEncoding" value="utf-8"/>
    </bean>
    <!--配置拦截器-->    <mvc:interceptors>      <mvc:interceptor>            <!--被拦截的路径-->            <!--所有以/game开头的哀求,都要经过拦截器-->            <mvc:mapping path="/game/**"/>            <mvc:mapping path="/player/**"/>            <!--在包罗的路径中,排除其中的某些路径-->            <mvc:exclude-mapping path="/game/test1"/>            <!--拦截器类-->            <bean class="com.javasm.interceptor.TestInterceptor"/>      </mvc:interceptor>      <mvc:interceptor>            <mvc:mapping path="/**"/>                            //拦截页面的范围            <mvc:exclude-mapping path="/game/test1"/>            //不会被拦截的页面            <mvc:exclude-mapping path="/login/**"/>            <bean class="com.javasm.interceptor.LoginInterceptor"/>//拦截所在的位置      </mvc:interceptor>    </mvc:interceptors></beans> 数据范例转换

Field error in object 'bookModel' on field 'ctime': rejected value ; codes ; arguments ; arguments []; default message ]; default message to type for value '2024-12-27'; nested exception is java.lang.IllegalArgumentException]] 表单提交的是String范例数据,实行自动转成Date范例,失败了
    @PostMapping("/doAdd2")
    @ResponseBody
    public Date doAdd2(String name,@DateTimeFormat(pattern = "yyyy-MM-dd") Date ctime){
      return ctime;
    }     @PostMapping("/doAdd")
    @ResponseBody
    public BookModel doAdd(BookModel book){
      return book;
    }
   
    @Data
public class BookModel {

    private Integer id;
    private String name;
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date ctime;
} 自定义参数范例转换器

SimpleDate转换
public class StringToDate implements Converter<String, Date> {
    @Override
    public Date convert(String s) {
      //传入的参数,等待被转换的2024-12-27 字符串
      System.out.println(s);
      SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
      Date date = null;
      try {
            date = simpleDateFormat.parse(s);
      } catch (ParseException e) {
            throw new RuntimeException(e);
      }

      return date;
    }
} <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xmlns:context="http://www.springframework.org/schema/context"       xmlns:mvc="http://www.springframework.org/schema/mvc"       xsi:schemaLocation="http://www.springframework.org/schema/beans       http://www.springframework.org/schema/beans/spring-beans.xsd      http://www.springframework.org/schema/context         https://www.springframework.org/schema/context/spring-context.xsd         http://www.springframework.org/schema/mvc         https://www.springframework.org/schema/mvc/spring-mvc.xsd">    <!--    开启包扫描-->    <context:component-scan base-package="com.javasm"/>    <!--代替适配器等配置-->    <mvc:annotation-driven conversion-service="conversionJavasmService"/>    <!--视图解析器-->    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">      <!--跳转的jsp页面,统一添加前缀-->      <property name="prefix" value="/WEB-INF/"/>      <!--后缀-->      <property name="suffix" value=".jsp"/>    </bean>    <!--静态资源文件放过-->    <mvc:default-servlet-handler/>    <!--上传文件的配置-->
    <bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
      <property name="defaultEncoding" value="utf-8"/>
    </bean>
    <!--配置拦截器-->    <mvc:interceptors>      <mvc:interceptor>            <!--被拦截的路径-->            <!--所有以/game开头的哀求,都要经过拦截器-->            <mvc:mapping path="/game/**"/>            <mvc:mapping path="/player/**"/>            <!--在包罗的路径中,排除其中的某些路径-->            <mvc:exclude-mapping path="/game/test1"/>            <!--拦截器类-->            <bean class="com.javasm.interceptor.TestInterceptor"/>      </mvc:interceptor>      <mvc:interceptor>            <mvc:mapping path="/**"/>            <mvc:exclude-mapping path="/game/test1"/>            <mvc:exclude-mapping path="/login/**"/>            <bean class="com.javasm.interceptor.LoginInterceptor"/>      </mvc:interceptor>    </mvc:interceptors>    <!--消息范例转换-->    <bean id="conversionJavasmService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">      <property name="converters">            <set>                <bean class="com.javasm.convert.StringToDate"/>            </set>      </property>    </bean></beans> localdateTime
Field error in object 'bookModel' on field 'utime': rejected value ; codes ; arguments ; arguments []; default message ]; default message to type for value '2024-12-27T16:08'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value ]] public class StringToDateTime implements Converter<String, LocalDateTime> {
    @Override
    public LocalDateTime convert(String s) {
      return LocalDateTime.parse(s, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
    }
}     <!--消息类型转换-->
    <bean id="conversionJavasmService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
      <property name="converters">
            <set>
                <bean class="com.javasm.convert.StringToDate"/>
                <bean class="com.javasm.convert.StringToDateTime"/>
            </set>

      </property>

    </bean>
JSON数据(用JSON传输数据)



[*]引入依赖
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>

      <artifactId>jackson-databind</artifactId>

      <version>2.11.2</version>

    </dependency>

    <dependency>
      <groupId>com.fasterxml.jackson.datatype</groupId>

      <artifactId>jackson-datatype-jsr310</artifactId>

      <version>2.11.2</version>

    </dependency>


[*]加注解
@GetMapping ("/doAdd3")
@ResponseBody
public BookModel doAdd3(@RequestBody BookModel book){
    System.out.println(book);
    return book;
} @Data
public class BookModel {

    private Integer id;
    private String name;
    //@DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date ctime;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime utime;
} {
    "id":1001,
    "name":"<刑法>",
    "ctime":"2024-12-27",
    "utime":"2024-12-27 16:09:30"
}
json时间,可以写2024-01-27 09:09:09
不能写 2024-1-27 9:9:9


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 24.12.27 SpringMVCDay02