SSM学习笔记

maven

什么是maven

项目管理工具

pom

mybatis参数

     ## 单个javabean

默认通过书信值引用。

多个参数

Girl queryByNameFlower(@Param("name") String name,@Param("flower") String flower);

  
  SELECT * FROM girl WHERE  name = #{name} AND  flower = #{flower}

map

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

sql语句中直接用名称取值

多个javabean

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

一组值的传入(List集合)

SQL标签




trim标签


    
        CITY = #{city} AND
    
    
        COUNTRY = #{country}  AND
    

解决字符串拼接问题
1.可用sql函数
select * from address
where
city like concat('%',#{city},'%')

2.bind标签

select * from address
where
city like #{_city}

sql标签


    city,country,state


select 
from address

cach缓存

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

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

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

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


多表查询映射


    
    
    
        
    


List comments;
    

  
  

spring

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

1.依赖


    org.springframework
    spring-context
    5.1.4.RELEASE

2.配置文件




    

    

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
  • AOP

IOC

概念:控制反转。

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

值的注入:

  • setter注入(最常用)

    • 必须有setter方法,如:name setName()

    • 用property标签注入

    • 
          
      
      
    • 非字面值的注入问题:使用ref指向另一个bean

    • 
          
      
      
          
      
      
    • String[]

    • 
          
              钰子
              雨子
              呀子
          
      
      
    • List<>

    • 
          
              1
              3
              4
          
      
      
    • set<>

    • 
          
             
                 
                 
             
              
                  
                  
              
          
      

      Map<>

    • 
          
              
                  
                      
                      
                  
              
              
                  
                      
                      
                  
              
          
      
      
  • 构造器注入

    • 默认使用无参构造器

    • constructor-arg标签

    • 
          
          
      
      

bean标签的探讨:

  • abstract:抽象
  • parent:继承bean标签
  • destory-method: 这个bean销毁是执行的方法。容器close(),refresh()
  • init-method: 初始化时使用的方法。
  • scope:指定范围
    • singleton:单例,spring上下文
    • prototype:原型
  • lazy-init: true使用时初始化。
  • depends-on: 依赖bean,如果bean的使用严重依赖于另一个bean。

alias标签:

  • 注入别名

  • 
    
  • 自动注入,autowire属性

  • byType

  • byName

  • constructor:根据构造器的参数名去匹配bean。

  • no

  • 
    
        
        
    
    
        
        
    
    
        
        
    

resource

  • Xml文件里引入其他properties文件:

  • 
    
    
    
  • 一个配置文件引入其他配置文件:classPath的根目录是resource目录

  • 
    

常用注解

xml中要激活注解:


  • component
  • controller
  • service
  • repository
  • autowired自动注入

AOP

概念

面向切面编程。

依赖包:


    
      org.aspectj
      aspectjrt
      1.9.2
    
    
    
      org.aspectj
      aspectjweaver
      1.9.2
    
配置文件




    
    
    
    
    
    
    
        
            
            
        
    

    


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




注解模式

xml文件






切面:

@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:



  
  
    
    springmvc
    org.springframework.web.servlet.DispatcherServlet
  
  
  
  
    springmvc
    
    /
  

pom.xml:



  org.springframework
  spring-webmvc
  5.1.4.RELEASE

控制器代码:

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" %>


    Title


    ${girl}


解释分析

web.xml

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



  springmvc
  
  /

url-pattern的写法问题:

  • /
  • /* (永远不要这样写,请求helloController时,过去后视图为girl.jsp,又将girl.jsp作为请求再去访问controller)
  • *.do

springMVC配置文件名

web.xml

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

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

[servlet-name]-servlet=namespace


  
  springmvc
  org.springframework.web.servlet.DispatcherServlet
    
  
    namespace
    mvc
  

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

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


  
  contextConfigLocation
  classpath:mvc.xml

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

视图解析器

springMVC支持多种视图技术

  • jsp
  • freemaker(模板技术)

内部的资源视图解析器

  • 视图前缀

    • /jsp/ 请求响应的资源路径配置

      viewName:girl /jsp/girl

  • 后缀

    • .jsp 此时前缀+视图名+后缀 = /jsp/girl.jsp

注解开发模式

基本注解;

  • @Controller
  • @RequestMapping

开发步骤

1.配置注解扫描包


 



    
        
        
        
        
    


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 问题

导入依赖




  javax.servlet
  jstl
  1.2

controller:

@RequestMapping("/byeBye")
public String byeBye(Model model){
    List 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:


    
        ${obj.name}
        ${obj.sex}
    

转发与重定向

  • 转发到页面

  • 重定向到另一个页面redirect:path

    @RequestMapping("redirect")
    public String redirect(Model model){
        model.addAttribute("model","hello");
        return "redirect:/jsp/redirect.jsp";
    }
    
  • 转发到另一个控制器forward:path

  • //    模拟请求
        @RequestMapping("/request")
        public String request(WebRequest request){
            System.out.println(request.getParameter("girl"));
            return "forward";
        }
    

@RequestMapping

  • @RequestMapping("/m1")
  • value 写的是路径,是一个数组的形式,可匹配多个路径,path与 value对等
    • @RequestMapping(value={"m1","m2"})
  • method 指定接收的请求类型,如果没写就所有类型都接收
    • @RequestMapping(value={"m1","m2"}, method= RequestMethod.GET)
  • params 可以指定参数
    • @RequestMapping(value="/m1",params={"girl","boy"})
    • 可以指定值params={"girl=王妃","boy!=爱卿"}
  • header 能够影响浏览器的行为
  • consumers 消费者,媒体类型,可以限定必须为application/json;chartset=UTF-8
  • produces 产生的响应的类型

请求路径的问题

Springmvc支持的ant风格

@RequestMapping("/Li?")

  • ?任意的字符,斜杠除外
  • *表示0-n,任意个字符都行,斜杠除外
  • /** 支持任意层路径

@GetMapping,@PostMapping.....

  • getMapping 只限定了get请求
  • postMapping 只限定了post请求

对于非get post请求的支持

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

过滤器:



  hiddenHttpMethodFilter
  org.springframework.web.filter.HiddenHttpMethodFilter



  hiddenHttpMethodFilter
  /*

表单还要添加隐藏参数;

delete

关于静态资源访问的问题

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

解决方式:

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

在mvc配置文件中加


 
    
    
    

2.通过映射关系描述


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 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" %>


    Title


 ${sessionScope.people.name}


@SessionAttribute

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

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

关于post请求中文乱码问题

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

 
  
    encoding
    UTF-8
  
  
    forceEncoding
    true
  


  characterEncodingFilter
  /*

关于form表单提交数据方式

方式一:通过属性名绑定

put people


 @PutMapping("/put")
    @ResponseBody//需要额外的json包的支持
    public String putPeople(String name,String sex){
        System.out.println(name+":"+sex);
//        Map 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 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

@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


后台传json给前端

1.导入json解析依赖




  com.fasterxml.jackson.core
  jackson-databind
  2.9.8



  com.fasterxml.jackson.core
  jackson-core
  2.9.8

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:


前台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依赖




  com.fasterxml.jackson.dataformat
  jackson-dataformat-xml
  2.9.8

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.加入依赖




  commons-fileupload
  commons-fileupload
  1.4

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



  
    
    
    
    
    
    

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" %>


    Title


单文件提交:
文件:

多文件提交:
文件1:
文件2:
文件3:
文件4:

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 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.配置拦截器



    
        
        

        
    

    
        
        
        
        
       
    

控制类:

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配置中配置的顺序有关。配置在前的先执行。

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

你可能感兴趣的:(SSM学习笔记)