SpringMVC高级

学习目标

  1. 拦截器
  2. 文件的上传与下载
  3. restful

1.拦截器

类似于JavaWeb中的Filter过滤器,用于过滤请求,可以对不符合要求的请求进行拦截

拦截器和过滤器的区别:

1)过滤器的使用范围比拦截器大,JavaWeb项目都可以使用,拦截器只能在SpringMVC使用

2)拦截器效率高于过滤器

1.2 拦截器的使用

1) 实现HandlerInterceptor接口
2)实现方法

  • preHandle 前置处理

  • postHandle 后置处理

  • afterCompletion 完成后处理

//登录拦截器
public class LoginInterceptor implements HandlerInterceptor {

    //前置处理  返回 false 进行拦截,返回true放行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //从session取User对象
        String user = (String) request.getSession().getAttribute("username");
        if(user==null){
            //没有登录,拦截,重定向到登录页面
            response.sendRedirect("/mvc/login");
            return false;
        }
        return true;
    }
}

3) 配置拦截器

<mvc:interceptors>
        <!--配置登录拦截器-->
        <mvc:interceptor>
            <!--拦截所用的请求-->
            <mvc:mapping path="/**"/>
            <!--配置不拦截的请求-->
            <mvc:exclude-mapping path="/**/login"/>
            <mvc:exclude-mapping path="/**/*.js"/>
            <mvc:exclude-mapping path="/**/*.css"/>
            <mvc:exclude-mapping path="/**/*.jpg"/>
            <!--拦截的类-->
            <bean class="com.hp.mvc.filter.LoginInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

2、文件上传下载

文件上传分为两种方式:

  • 传统的Servlet文件上传

  • SpringMVC文件上传

2.1.1 传统的Servlet文件上传

1)导入依赖

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

2)编写表单
表单文件上传的三个要素:

  1. form标签要添加enctype=“multipart/form-data”

  2. 提交方法为post

  3. input类型为file

     <form  action="/upload" method="post" enctype="multipart/form-data">
         ...
         <input type="file" name="file" >
         ...
     </form>
    

2)上传方法

@Controller
public class UploadController {

    @RequestMapping("/upload")
    public String fileupload(HttpServletRequest request) throws Exception {
        //获取项目的upload目录路径
        String path= request.getSession().getServletContext().getRealPath("/upload/");
        File file=new File(path);
        //判断文件夹是否存在
        if (!file.exists()){
            //创建文件夹
            file.mkdirs();
        }
        //创建上传对象
        ServletFileUpload upload=new ServletFileUpload(new DiskFileItemFactory());
        //获得文件列表
        List<FileItem> fileItems= upload.parseRequest(request);
        for (FileItem item:fileItems){
            //判断文件是不是普通表单项
            if (item.isFormField()){
                //如果是普通表单项,打印表单项名和值
                System.out.println(item.getFieldName());
                System.out.println(item.getString());
            }else{
                //如果是文件,截取后缀名
                String filename= item.getName();
                String suffix = filename.substring(filename.lastIndexOf("."));
                //创建唯一的文件名
                String uuid= UUID.randomUUID().toString().replace("-","");
                filename = uuid + suffix;
                //完成文件上传
                item.write(new File(path,filename));
                System.out.println("上传完毕");
            }
        }
        //跳转到success页面
        return "success";
    }

2.1.2 SpringMVC文件上传

依赖和表单和上面一样

上传方法中使用MultipartFile参数获得上传文件

@Controller
public class UploadController {
    public static final String UPLOAD_PATH="D:\\upload\\";
    //单文件上传
    @RequestMapping("upload")
    public String upload(MultipartFile file) throws IOException {
        File dir = new File(UPLOAD_PATH);
        if(!dir.exists()){
            dir.mkdirs();
        }

        String filename = file.getOriginalFilename();
        String suffix = filename.substring(filename.lastIndexOf("."));
        filename= UUID.randomUUID().toString().replace("-","")+suffix;
        //将上传的文件保存到服务器文件中
        file.transferTo(new File(UPLOAD_PATH+filename));
        return "success";
    }
    }

需要在springmvc的配置中添加上传处理器

<!--上传处理器-->
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver">
    <!--上传文件最大字节数-->
    <property name="maxUploadSize" value="10485760"/>
</bean>

2.1.3 SpringMVC多文件上传

给表单添加多个文件项

<form action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="uploads">
    <input type="file" name="uploads">
    <input type="file" name="uploads">
    <input type="submit" value="MVC多文件上传">
</form>

添加MultipartFile数组为参数,参数名和表单name一致

@Controller
public class UploadController {
    public static final String UPLOAD_PATH="D:\\upload\\";
    
	//多文件上传
    @RequestMapping("upload1")
    public String upload1(HttpServletRequest request, MultipartFile[] uploads) throws IOException {
        File dir = new File(UPLOAD_PATH);
        if(!dir.exists()){
            dir.mkdirs();
        }

        for(MultipartFile upload :uploads){
            String filename = upload.getOriginalFilename();
            String suffix = filename.substring(filename.lastIndexOf("."));
            filename= UUID.randomUUID().toString().replace("-","").substring(0,10)+suffix;
            //将上传的文件保存到服务器文件中
            upload.transferTo(new File(UPLOAD_PATH+filename));
        }
        return "success";
    }


}

3、RestFul

3.1 前后端分离

3.1.1 前后端分离是什么
前端项目(html5、小程序、移动端),后端项目(java、数据库、tomcat)分开开发和部署
3.1.2 前后端分离优势

1)开发分工明确,前端团队和后端团队同时分工合作开发

2)项目分开部署不同的服务器,如:Tomcat适合部署动态资源,Nginx适合部署静态资源

3)便于测试和维护

3.1.3 前后端开发人员的交互方式

1)设计人员根据需求设计接口,提供接口文档

1)后端根据接口文档开发后台接口

2)前端通过接口请求数据,渲染页面

在这里插入图片描述

3.2 RESTFul

3.2.1 RESTFul是什么
RESTFul是一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用XML格式定义或JSON格式定义。适用于移动互联网厂商作为业务使能接口的场景,实现第三方调用移动网络资源的功能,动作类型为新增、变更、删除所调用资源。

RESTful架构,是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。

3.2.2 RESTFul架构的特点

  1. 每一个URI对应服务器上的一个资源(数据库数据、方法等)

  2. 通过不同Http请求方法来区别增删改查操作

  • GET --> 查询

  • POST --> 添加

  • PUT --> 更新

  • DELETE --> 删除

  1. 通信的格式是JSON

3.2.3 RESTFul风格的API

传统API设计,常用动词定义API,如:find、get、save、update、delete等

查询所有书籍:
http://域名/book/findAll
查询一本书:
http://域名/book/findById?id=1
添加书籍:
http://域名/book/saveBook
更新书籍:
http://域名/book/updateBook
删除书籍:
http://域名/book/deleteBook?id=1

RESTFul风格API设计,只使用名词,使用不同的请求方法来区别增删改查

查询所有书籍: 	GET
http://域名/books
查询一本书:		GET
http://域名/book/1
添加书籍:		POST
http://域名/book
更新书籍:		PUT
http://域名/book
删除书籍:		DELETE
http://域名/book/1

Restful风格的控制器的实现

@RestController定义RestFul风格的控制器,其中所有的方法都直接返回数据,相当于加了@ResponseBody

@RestController
public class BookController {
    //注入service对象
    @Autowired
    private BookService bookService;
    //查询所用
    @GetMapping("/books")
    public JsonResult findAll(){
        try {
            return new JsonResult(1,"ok",bookService.findAll());
        } catch (Exception e) {
            e.printStackTrace();
            return new JsonResult(0,"error",null);
        }
    }

    //查询一本书籍
    @GetMapping("/books/{id}")
    public JsonResult findById(@PathVariable("id") Long id){
        try {
            return new JsonResult(1,"ok",bookService.findById(id));
        } catch (Exception e) {
            e.printStackTrace();
            return new JsonResult(0,"error",null);
        }
    }

    //添加一本书籍
    @PostMapping("/book")
    public JsonResult addBook(Book book){
        try {
            bookService.add(book);
            return new JsonResult(1,"ok",book);
        } catch (Exception e) {
            e.printStackTrace();
            return new JsonResult(0,"error",null);
        }
    }
    
    //修改书籍
    @PutMapping("/book")
    public JsonResult updateBook(Book book){
        try {
            bookService.update(book);
            return new JsonResult(1,"ok",book);
        } catch (Exception e) {
            e.printStackTrace();
            return new JsonResult(0,"error",null);
        }
    }
    
    //删除书籍
    @DeleteMapping("/book/{id}")
    public JsonResult deleteById(@PathVariable("id")Long id){
        try {
            bookService.delete(id);
            return new JsonResult(1,"ok",bookService.findAll());
        } catch (Exception e) {
            e.printStackTrace();
            return new JsonResult(0,"error",null);
        }
    }
}

service层

@Service
public class BookServiceImpl  implements BookService {
    private List<Book> books =new ArrayList<>();

    {
        books.addAll(Arrays.asList(
                new Book(1L,"红楼梦","曹雪芹",88.0),
                new Book(2L,"水浒传","施耐庵",99.0),
                new Book(3L,"西游记","吴承恩",77.0),
                new Book(4L,"三国演义","罗贯中",66.0)
        ));
    }


    @Override
    public List<Book> findAll() {
        return books;
    }

    @Override
    public Book findById(Long id) {
        return books.stream().filter(book -> book.getId()==id).findFirst().get();
    }

    @Override
    public void add(Book book) {
        books.add(book);
    }

    @Override
    public void update(Book book) {
        Book book1 = findById(book.getId());
        book1.setAuthor(book.getAuthor());
        book1.setName(book.getName());
        book1.setPrice(book.getPrice());
    }

    @Override
    public void delete(Long id) {
        Book book = findById(id);
        books.remove(book);
    }
}

实体类
BOOK

public class Book {
    private Long id;
    private String name;
    private String author;
    private Double price;

}

JsonResult

public class JsonResult {
    private Integer code;
    private String msg;
    private Object date;

}

3.2.4 浏览器支持DELETE和PUT

浏览器默认只支持GET和POST请求,如果要表单提交DELETE或PUT请求,需要通过SpringMVC的过滤器来实现
web.xml添加:

<filter>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

HiddenHttpMethodFilter过滤器的作用是:过滤表单中名称为_method的隐藏域,如果值是DELETE就将请求方法转换为DELETE,是PUT就将请求方法转换为PUT。
表单:

<form action="/testDelete" method="post">
    <input name="name" placeholder="输入姓名"><br>
    <input type="hidden" name="_method" value="DELETE"/>
    <input type="submit" value="提交">
</form>

3.2.5 通过Postma来完成DELETE和PUT

Delete的操作
在这里插入图片描述
PUT的操作
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值