后端框架

SSM学习笔记

2019-10-12  本文已影响0人  万里无风来

maven

什么是maven

项目管理工具

pom

mybatis参数

     ## 单个javabean

默认通过书信值引用。

多个参数

Girl queryByNameFlower(@Param("name") String name,@Param("flower") String flower);
<!--SELECT * FROM girl WHERE  name = #{param1} AND  flower = #{param2}-->
  <!--SELECT * FROM girl WHERE  name = #{arg0} AND  flower = #{arg1}-->
  SELECT * FROM girl WHERE  name = #{name} AND  flower = #{flower}

map

Map<String,Object> map = new HashMap<>();
map.put("name","he");
map.put("flower","flowerLi");

sql语句中直接用名称取值

多个javabean

类似于多个参数,只不过参数变成了对象

一组值的传入(List集合)

SQL标签

<!--foreach
    collection 描述集合
    open 以什么拼接符号开头
    close 以什么结尾
    item 一个数据项的代号
    separator item之间的分隔符
    index 如需使用标号,也可使用
    -->
<!--使用where标签,使得语法合法,
   自动消除多余的and,只能处理前置的and。
   if标签里有多个条件,则用and连接。
-->
<!--例如:传入非空值是修改,否则不修改.
set标签纠正语法,去掉后置的多余逗号。
-->

trim标签

<trim prefix="where" suffixOverrides="and">
    <if test="city != null">
        CITY = #{city} AND
    </if>
    <if test="country != null">
        COUNTRY = #{country}  AND
    </if>
</trim>
解决字符串拼接问题
1.可用sql函数
select * from address
where
city like concat('%',#{city},'%')

2.bind标签
<bind name="_city" value="'%'+city+'%'"/>
select * from address
where
city like #{_city}

sql标签

<sql id="baseCoulmn">
    city,country,state
</sql>

select <include refid="baseCoulmn"/>
from address

cach缓存

默认情况下,一级缓存是开启的,且无法关闭。

一级缓存是单个会话级别的

  1. 如果关闭会话,缓存失效。
  2. 如果会话过程有增删改操作,则缓存失效。
  3. java中 sqlSession.clearCache();清掉所有缓存

二级缓存是多个会话级别的

<setting name="cacheEnabled" value="true">

<cache
  eviction="FIFO"
  flushInterval="60000"
  size="512"
  readOnly="true"/>

多表查询映射

<resultMap id="rMap" type="javaClass">
    <id property="id" column="id"/>
    <result property="id" column="id"/>
    <association property="\\class" javaType="">
        <result property="" column=""/>
    </association>
</resultMap>
<!--
collection标签用来描述集合
ofType是描述集合里的一个元素的类型
-->
List<Comment> comments;
    
<collection property="comments"
             ofType="self.he.pojo.Comment">
  <id property="id" column="cid"/>
  <result property="content" column="commentContent"/></collection>

spring

  1. 添加spring依赖
  2. 编写spring的配置文件
  3. 通过spring应用程序上下文获取对象

1.依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.1.4.RELEASE</version>
</dependency>

2.配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--将对象的创建-交给spring容器,
    在配置文件里声明需要的对象。
    class:Java类的全限定名
    id: 此对象的昵称方便区分-->
    <bean class="self.he.pojo.Girl" id="girl">

    </bean>
</beans>

3.java代码

public class Girl {
    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}
public void  m1(){
    //获取上下文对象,spring里面声明对象都需要通过上下文获取
    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    //通过此对象获取girl
    Girl g = (Girl) ctx.getBean("girl");
    System.out.println(g);
}

核心内容

IOC

概念:控制反转。

将对象的创建交给Spring容器。

值的注入:

bean标签的探讨:

alias标签:

resource

常用注解

xml中要激活注解:

<context:component-scan base-package="self.he"/>

AOP

概念

面向切面编程。

依赖包:

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.9.2</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.2</version>
    </dependency>
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">


    <!--1 aop是基于代理完成的,所以要激活自动代理-->
    <aop:aspectj-autoproxy/>
    <!--2 注册切面-->
    <bean class="self.he.advice.BeforeAdvice" id="beforeAdvice">
    </bean>
    <!--3 配置切入点等信息-->
    <aop:config>
        <aop:aspect id="beforeAspect" ref="beforeAdvice">
            <!--aop:before 表明前置通知
                method:指明使用哪个方法切
                pointcut:切入点
                          包,类,方法
            -->
            <aop:before method="methodBefore" pointcut="execution(* self.he.service.ProviderService.*(..))"></aop:before>
        </aop:aspect>
    </aop:config>

    <bean class="self.he.service.ProviderService"
          id="providerService"></bean>

</beans>

execution()表达式:

例如:execution(* self.he.service.ProviderService.*(..))

测试
@Test
public void m1(){
    ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/applicationContext.xml");

    //不是spring管理的bean,织入无效。
    ProviderService providerService = new ProviderService();
    providerService.add();

    ProviderService providerService1 = ctx.getBean("providerService", ProviderService.class);
    providerService1.add();
}

返回执行:after-returning

<aop:after-returning method="AfterReturn" returning="returning" pointcut="execution(* self.he.service.HelloService.*(..))"/>


注解模式

xml文件

<!--1 自动代理-->
<aop:aspectj-autoproxy/>

<!--2 配置自动扫描包-->
<context:component-scan base-package="self"/>

切面:

@Aspect//标记为一个切面
@Component//标记为一个组件,相当于在xml中注册一个bean
public class BeforeAdvice {
    @Before("execution(* self.she.service.HelloService.hello(String,String))")
    //获取方法名,参数
    public void before(JoinPoint joinPoint){
        System.out.println("before!!!!!"+joinPoint.getSignature().getName()+ Arrays.toString(joinPoint.getArgs()));
    }
    @Before("execution(* self..*.*(..))")
    public void before2(){
        System.out.println("before2!!!");
    }
}

切点:

@Component
public class HelloService {
    public void hello(String name,String sex){
        System.out.println("hello "+name+"!"+sex+"!!!");
    }
    public String eat(){
        System.out.println("eating!!!!");
        return "Li";
    }
}

注解方式获得bean

配置类

@Configuration
@ComponentScan(value = "self.she")
public class SpringConfig {

    @Bean("girl")
    public Girl creatGirl(){
        Girl girl = new Girl();
        girl.setName("Li");
        return girl;
    }

}

测试:

@Test
public void  m1(){
    ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
    Girl girl = ctx.getBean("girl",Girl.class);
    System.out.println(girl.getName());
}

springMVC

简介

springMVC是一个web层的框架。

model 模型

view 视图

controller 控制器

一种设计模式,将责任进行拆分,不同组件负责不同功能。

好处:

坏处:

入门体验

1.创建web项目

2.编写web.xml,注册一个特殊的servlet,前端控制器

3.编写一个springMVC的配置文件

  1. 注册一个视图解析器

4.编写一个控制器

5.编写一个结果页面

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
  <!--注册一个前端控制器-->
  <servlet>
    <!--这里名字有讲究,
        如果不修改spring配置文件的默认位置,那么springmvc
        会去web-inf下找一个springmvc-servlet.xml的文件-->
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  </servlet>
  
  <!--servlet映射配置-->
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <!--统一写/-->
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

pom.xml:

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>5.1.4.RELEASE</version>
</dependency>

控制器代码:

package self.he.controller;

import org.springframework.lang.Nullable;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloController implements Controller {


    @Nullable
    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        ModelAndView mav = new ModelAndView();
        mav.addObject("girl","Li");
        mav.setViewName("girl");
        return mav;
    }
}

视图代码:

<%--
  Created by IntelliJ IDEA.
  User: he
  Date: 2019/2/13
  Time: 16:19
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    ${girl}
</body>
</html>

解释分析

web.xml

注册前端控制器,目的让springmvc去处理请求

<!--servlet映射配置-->
<servlet-mapping>
  <servlet-name>springmvc</servlet-name>
  <!--统一写/-->
  <url-pattern>/</url-pattern>
</servlet-mapping>

url-pattern的写法问题:

springMVC配置文件名

web.xml

默认情况下使用dispatcherServlet的名字作为命名空间

[servlet-name]-servlet.xml (WEB-INF)下寻找

[servlet-name]-servlet=namespace

<servlet>
  <!--这里名字有讲究,
      如果不修改spring配置文件的默认位置,那么springmvc
      会去web-inf下找一个springmvc-servlet.xml的文件-->
  <servlet-name>springmvc</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--重新命名配置文件名-->
  <init-param>
    <param-name>namespace</param-name>
    <param-value>mvc</param-value>
  </init-param>
</servlet>

配置文件默认在WEB-INF下,但是maven项目要求在resources目录下。

解决:重新指定上下文位置即可web.xml

<init-param>
  <!--上下文配置的位置的指定-->
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath:mvc.xml</param-value>
</init-param>

此时在类路径下寻找mvc.xml

视图解析器

springMVC支持多种视图技术

内部的资源视图解析器

注解开发模式

基本注解;

开发步骤

1.配置注解扫描包

<!--配置注解扫描包-->
 <context:component-scan base-package="self.he.controller"/>


<!--配置一个视图解析器
        常用内部资源视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--1 前缀-->
        <property name="prefix" value="/jsp/"/>
        <!--2 后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>


2.在指定类上添加@Controller注解

3.添加@RequestMapping

@Controller//不需要继承任何类
@RequestMapping("/bye")
public class ByeController {

   @RequestMapping("/bye")
    public String bye(Model model){
       model.addAttribute("model","Li");
       // return的是ViewName
       //此时去的/jsp/bye.jsp
       return "bye";
    }

    @RequestMapping("/goodBye")
    public String goodBye(Model model){
        model.addAttribute("model","Lily");
        return "bye";
    }
}

list 问题

导入依赖

<!--jstl依赖-->
<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>jstl</artifactId>
  <version>1.2</version>
</dependency>

controller:

@RequestMapping("/byeBye")
public String byeBye(Model model){
    List<People> list = new ArrayList<>();
    People p1 = new People();
    p1.setName("Li");
    p1.setSex("girl");
    People p2 = new People();
    p2.setName("He");
    p2.setSex("boy");
    list.add(p1);
    list.add(p2);
    model.addAttribute("model",list);
    return "byeBye";
}

jsp:

<c:forEach items="${model}" var="obj">
    <tr>
        <td>${obj.name}</td>
        <td>${obj.sex}</td>
    </tr>
</c:forEach>

转发与重定向

@RequestMapping

请求路径的问题

Springmvc支持的ant风格

@RequestMapping("/Li?")

@GetMapping,@PostMapping.....

对于非get post请求的支持

需要有额外的内容添加,要增加一个过滤器来处理。

过滤器:

<!--注册一个支持所有http请求类型的过滤器-->
<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>

表单还要添加隐藏参数;

delete
<form action="${ctx}/he/m1" method="post">
    <input type="hidden" name="_method" value="DELETE"/>
    <input type="submit" value="提交"/>
</form>

关于静态资源访问的问题

用于在web.xml中设置了servlet的url匹配方式为/ ,所以静态资源也当做一个后台请求。

解决方式:

1.交给默认servlet处理。不让DispatcherServlet处理。

在mvc配置文件中加

<!--默认servlet处理者,识别MIME类型-->
 <!--默认servlet处理者,只加它注解会失效-->
    <mvc:default-servlet-handler/>
    <!--重新激活注解模式-->
    <mvc:annotation-driven/>

2.通过映射关系描述

<mvc:resources mapping="/static/css/*" location="static/css/"/>

3.在web.xml定义映射规则

@PathVariable

路径变量。

@RequestMapping("/add/{name}/{sex}")
public String addPeople(@PathVariable("name") String name,@PathVariable("sex")String sex){
    System.out.println(name+":"+sex);
    return "forward";
}

@Responsebody

返回数据,一般情况下返回json格式数据。

    @PutMapping("/put")
    @ResponseBody//需要额外的json包的支持
    public String putPeople(String name){
        System.out.println(name+":");
//        Map<String,String> map = new HashMap<>();
//        map.put("msg","ok");
        return "ok";
    }

@RequestBody

json数据,不是通过form表单传递

ajax({

​ data:

​ } )

@SessionAttributes

用在类上面,将模型自动填充到会话里去。

@Controller
@RequestMapping("/people2")
@SessionAttributes("people")
public class People2Controller {
        @RequestMapping("/login3")
    public String login3(@ModelAttribute People people)     {
        System.out.println(people.getName());
        return "redirect:/jsp/login.jsp";
    }

}

login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
 ${sessionScope.people.name}
</body>
</html>

@SessionAttribute

要求当前会话里必须要有某个对象。

 public String login3(@SessionAttribute People people)     {
        System.out.println(people.getName());
        return "redirect:/jsp/login.jsp";
    }

关于post请求中文乱码问题

添加过滤器,springmvc提供过滤器。

 <!--指定编码,这段配置要放在所有filter的最前面,否则会不生效-->
  <init-param>
    <param-name>encoding</param-name>
    <param-value>UTF-8</param-value>
  </init-param>
  <init-param>
    <param-name>forceEncoding</param-name>
    <param-value>true</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>characterEncodingFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

关于form表单提交数据方式

方式一:通过属性名绑定

put people
<form action="${ctx}/people/put" method="post">
    <input type="hidden" name="_method" value="put"/>
    <input type="text" name="name"/><br>
    <input type="password" name="sex"/><br>
    <input type="submit" value="提交"/>
</form>
 @PutMapping("/put")
    @ResponseBody//需要额外的json包的支持
    public String putPeople(String name,String sex){
        System.out.println(name+":"+sex);
//        Map<String,String> map = new HashMap<>();
//        map.put("msg","ok");
        return "ok";
    }

方式二:@RequestParam()

 @PutMapping("/put")
    @ResponseBody//需要额外的json包的支持
    public String putPeople(@RequestParam("name")String name,@RequestParam("sex")String sex){
        System.out.println(name+":"+sex);
//        Map<String,String> map = new HashMap<>();
//        map.put("msg","ok");
        return "ok";
    }

方式三:直接用pojo形式

 @PutMapping("/put")
    @ResponseBody//需要额外的json包的支持
    public String putPeople(People people){
        System.out.println(people.getName()+":"+people.getSex());
        return "ok";
    }

关于表单提交date类型数据问题

put people and date
<form action="${ctx}/people/date" method="post">
    <input type="date" name="date"/><br>
    <input type="submit" value="提交"/>
</form>
@InitBinder
public void initBinder(WebDataBinder binder) {
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    dateFormat.setLenient(false);
    binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
}

 @PostMapping("/date")
    @ResponseBody//需要额外的json包的支持
    public String postPeople(People people){
        System.out.println("hhhh");
        System.out.println(people.getDate());
        return "ok";
    }

2.在属性上添加注解

@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date date;

@ModelAttribute可解决页面间数据交换

使用方式一:

//在controller里任意一个方法执行前执行
@ModelAttribute
public People init(){
    System.out.println("init........");
    People people = new People();
    people.setName("Li");
    return people;
}

@RequestMapping("/login")
public String login(Model model){
    System.out.println(model.containsAttribute("people"));
    return "forward";
}

方法二:

@ModelAttribute("people")
public void init(Model model){
    System.out.println("init........");
    People people = new People();
    people.setName("Li");
    model.addAttribute("people",people);
}

方法三:

如果请求页面传了people则使用请求的值,如果没有则使用默认的。

可用于页面间数据交换。

@RequestMapping("/login2")
public String login2(@ModelAttribute People people){
    System.out.println(people.getName());
    return "login";
}
post people to other page
<form action="${ctx}/people2/login2" method="post">
    <input type="text" name="name"/><br>
    <input type="password" name="sex"/><br>
    <input type="submit" value="提交"/>
</form>

后台传json给前端

1.导入json解析依赖

<!--json依赖-->
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.9.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-core</artifactId>
  <version>2.9.8</version>
</dependency>

2.利用@ResponseBody

@RequestMapping("m1")
@ResponseBody
public People m1(){
    People people = new People();
    people.setName("Li");
    people.setSex("girl");
    people.setDate(new Date());
    return people;
}

前台解析json:

<script>
    $(function () {
        $("#b").click(function () {
            $.ajax({
                url:'${ctx}/json/m1',
                type:'post',
                success:function (data) {
                    alert(data.name+":"+data.sex)
                }
            })
        })
    })

</script>

前台ajax给后台传json

注意 contentType:'application/json',不可缺
$("#bb").click(function () {
    var obj={
        'name':'Li 李',
        'sex':'girl'
    };

    $.ajax({
        url:'${ctx}/json/m2',
        type:'post',
        contentType:'application/json',
        data:JSON.stringify(obj),
        success:function (data) {
                 alert(data.name);
                }
    })
})

后台用注解@RequestBody接收

//接收前台传来的json
@RequestMapping("/m2")
@ResponseBody
public People m1(@RequestBody People people){
    System.out.println(people.getName());
   People people = new People();
    people.setName("Li");
    people.setSex("girl");
    people.setDate(new Date());
    return people;
}

@RestController=@Controller+@ResponseBody

xml解析传输

很多第三方开发会使用xml传输数据,例如:微信

1.添加xml依赖

<!--xml依赖-->
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-xml -->
<dependency>
  <groupId>com.fasterxml.jackson.dataformat</groupId>
  <artifactId>jackson-dataformat-xml</artifactId>
  <version>2.9.8</version>
</dependency>

2.@RequestMapping

@RequestMapping(value = "/m1",produces ={MediaType.APPLICATION_XML_VALUE})
@ResponseBody
public People m1(){
    People people = new People();
    people.setName("Lily");
    people.setSex("girl");
    people.setDate(new Date());
    return people;
}

文件上传

1.加入依赖

<!--Apache文件上传依赖-->
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.4</version>
</dependency>

2.在springmvc配置文件中注册文件上传解析器

<!--文件上传解析器,
     id="multipartResolver"只能是这个,源代码规定的
     -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
  <!--定义最大文件上传大小,byte-->
    <property name="maxUploadSize" value="1024000"/>
    <!--指定上传的编码-->
    <property name="defaultEncoding" value="UTF-8"/>
    <!--单个文件最大大小-->
    <property name="maxUploadSizePerFile" value="200000"/>
    
</bean>

3.上传页面

<%--
  Created by IntelliJ IDEA.
  User: he
  Date: 2019/2/15
  Time: 9:39
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
单文件提交:
<form action="${ctx}/file/upload" method="post" enctype="multipart/form-data">
    文件:<input type="file" name="file"/><br>
    <input type="submit" value="提交">
</form>
<br>
多文件提交:
<form action="${ctx}/file/upload2" method="post" enctype="multipart/form-data">
    文件1:<input type="file" name="file"/><br>
    文件2:<input type="file" name="file"/><br>
    文件3:<input type="file" name="file"/><br>
    文件4:<input type="file" name="file"/><br>
    <input type="submit" value="提交">
</form>
</body>
</html>

4.响应控制类

 private static String uploadPath = "E:"+ File.separator;

 @RequestMapping("/upload")
public String upload(@RequestParam("file")MultipartFile multipartFile, Model model){
     //1.传到哪里去。2.数据 3.传的细节
    if (multipartFile != null && !multipartFile.isEmpty()){
        //不空再传
        //1.获得文件名
        String originalFilename = multipartFile.getOriginalFilename();
        //2.截取文件名前缀
        String fileNamePrefix = originalFilename.substring(0,originalFilename.lastIndexOf('.'));
        //3.构建新文件名 前缀+时间戳
        String newFilePrefix = fileNamePrefix+new Date().getTime();
        //4.得到新文件名
        String newFileName =newFilePrefix+originalFilename.substring(originalFilename.lastIndexOf('.'));
        //5.构建文件对象
        File file = new File(uploadPath+newFileName);

        //6.写入文件
        try {
            multipartFile.transferTo(file);
            model.addAttribute("fileName",newFileName);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return "uploadSuc";
}

@RequestMapping("/upload2")
 public String upload2(@RequestParam("file") MultipartFile[] multipartFiles,Model model){
    List<String> fileNames = new ArrayList<>();
    System.out.println(multipartFiles != null && multipartFiles.length >0);
    if (multipartFiles != null && multipartFiles.length >0){
        for (MultipartFile multipartFile:multipartFiles) {
            if (multipartFile != null && !multipartFile.isEmpty()){
                //不空再传
                //1.获得文件名
                String originalFilename = multipartFile.getOriginalFilename();
                //2.截取文件名前缀
                String fileNamePrefix = originalFilename.substring(0,originalFilename.lastIndexOf('.'));
                //3.构建新文件名 前缀+时间戳
                String newFilePrefix = fileNamePrefix+new Date().getTime();
                //4.得到新文件名
                String newFileName =newFilePrefix+originalFilename.substring(originalFilename.lastIndexOf('.'));
                //5.构建文件对象
                File file = new File(uploadPath+newFileName);

                //6.写入文件
                try {
                    multipartFile.transferTo(file);

                    fileNames.add(newFileName);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    model.addAttribute("fileNames",fileNames);
    return "uploadSuc";
}

文件下载

@RequestMapping("/down")
    public void fileDown(HttpServletResponse response){
        //通过输出流写入客户端
//       response.setCharacterEncoding("UTF-8");
       //1.获取下载文件名
       String fileName = "哈哈.jpg";
       //2.构建一个文件对象,通过Paths工具类获得Path对象
       Path path = Paths.get(uploadPath,fileName);

       //3.判断它是否存在
       if(Files.exists(path)){
           //存在则下载
           //4.设定response的响应类型
                //获取文件后缀
           String fileSuffix = fileName.substring(fileName.lastIndexOf('.')+1);
                //设置contentType
           response.setContentType("application/"+fileSuffix);
           try {
               //ISO8859-1编码
               response.addHeader("Content-Disposition","attachment;filename=" + new String(fileName.getBytes("UTF-8"),"ISO8859-1"));
           } catch (UnsupportedEncodingException e) {
               e.printStackTrace();
           }
           System.out.println(fileSuffix);
           //5 通过Path写出去
           try {
               Files.copy(path,response.getOutputStream());
           } catch (IOException e) {
               e.printStackTrace();
           }
       }

   }

注意事项: //ISO8859-1编码
response.addHeader("Content-Disposition","attachment;filename=" + new String(fileName.getBytes("UTF-8"),"ISO8859-1"));

避免中文无法识别

拦截器

通过实现HandlerInterceptor

案例:

登录请求拦截,如果session有user,不拦截,没有则拦截,但/user/login不拦截。

1.拦截类

package self.he.interceptors;

import org.apache.log4j.Logger;
import org.springframework.web.servlet.HandlerInterceptor;
import self.he.pojo.User;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SessionInterceptor implements HandlerInterceptor{


    private static final Logger LOGGER = Logger.getLogger(SessionInterceptor.class);

    //检查当前会话是否有User,有则放行,没有则拦截
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        Object user = request.getSession().getAttribute("SESSION_USER");

        if(user == null){
            LOGGER.warn("没有权限,请先登录!");
            return false;
        }

        if(user instanceof User){
            //查数据库检查
            User u = (User)user;
            u.setPwd(null);
            request.getSession().setAttribute("SESSION_USER",u);
            LOGGER.info(u.getName()+"会话中。。");
            return true;

        }else {
            LOGGER.warn("不要搞事,请先登录!");
            return false;
        }

    }
}

2.配置拦截器

<!--拦截器配置-->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**/*"/>
        <bean class="self.he.interceptors.MethodTimerInterceptor">

        </bean>
    </mvc:interceptor>

    <mvc:interceptor>
        <!-----------------------------------------------
            拦截user下的,但login除外
        -->
        <mvc:mapping path="/user/**/*"/>
        <mvc:exclude-mapping path="/user/login"/>
        <bean class="self.he.interceptors.SessionInterceptor">
       </bean>
    </mvc:interceptor>
</mvc:interceptors>

控制类:

package self.he.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import self.he.pojo.User;

import javax.servlet.http.HttpSession;

@Controller
@RequestMapping("/user")
public class UserController {


    @RequestMapping("/login")
    public String login(User user, HttpSession session){

        if(user != null&& user.getName()!= null && user.getName().equals("Li")){
            //(数据库检查)
            session.setAttribute("SESSION_USER",user);
            return "user";
        }
        System.out.println("....login...........");
        return "redirect:/login.jsp";
    }

    @RequestMapping("/delete")
    public String delete(){
        System.out.println("....可以为所欲为了delete...........");
        return "user";
    }
}

拦截器执行顺序问题

有N个拦截器,都能拦截同一个URI时,执行顺序:

在springmvc配置中配置的顺序有关。配置在前的先执行。

前置处理与后置处理顺序刚好相反。

上一篇下一篇

猜你喜欢

热点阅读