学习目标
- 拦截器
- 文件的上传与下载
- 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)编写表单
表单文件上传的三个要素:
-
form标签要添加enctype=“multipart/form-data”
-
提交方法为post
-
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架构的特点
-
每一个URI对应服务器上的一个资源(数据库数据、方法等)
-
通过不同Http请求方法来区别增删改查操作
-
GET --> 查询
-
POST --> 添加
-
PUT --> 更新
-
DELETE --> 删除
- 通信的格式是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的操作