实训笔记_

实训笔记

第一天

事务回滚 extends runtimeException

return Interger

Session 清空密码

throw new ServiceException

MD5加密

第二天

部署项目所需注意

创建spring Boot项目

热部署 :开发工具 web-tools

搜索引擎

@Test

测试数据源

同一个用户不能创建相同的笔记名称

用户名是否重复

序列化 1L implements serialzable

注册

用户名判断>>>>返回 user

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BiTk4ALS-1587123105178)(C:\Users\刘\AppData\Roaming\Typora\typora-user-images\1559007907990.png)]

select * >>不推荐 
select id,uname,upwd,phone,email from  t_user where uname=#{uname}?规范
select count(*) cnt from t_user where uphone=#{uphone}

映射文件 :约束>>>>>>

1、validate

2、namespace

<mapper namespace="com.sx.ybj.mapper">
    <!-- sql注释>
    <select id="方法" parameterType="String" or "pojo"> 
</mapper>

别名>>>> aliaes-package>>>别名

@MapperBean

单元测试

​ src/java/test

1、自定义业务异常

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FXhjH27Q-1587123105180)(C:\Users\刘\Desktop\工具\7019.png)]

throws ServiceException 抛出异常>>>>>>>1自定义异常 2抛出自定义异常
1、单元测试
2、集成测试
Result<void>
Post 和 Get 

模拟测试:>>>单元测试>>>>绕过调用


第三天

项目开发过程任务

需求分析 数据流图 、数据字典、

概要设计:软件结构图

详细设计:(程序算法、数据库设计)

程序算法:程序流程图、NS方框图、判定书、判定表

数据库设计:ER实体练习图(表结构说明)

第二三周、编码>>>>>程序开发文档

最后一个星期做测试>>>>>>>(黑盒测试、白盒测试)

每个阶段复审

第四天

提交:

原型图

需求分析

数据库设计

编写

1、小组会议纪要: 确定工作计划

2、小组周工作计划:完成计划

3、个人周工作计划

4、个人周工作总结

5、小组周工作总结:工作总结

项目规范

1、add

2、get

3、update

4、delete

第五天

springboot 以jar方式在linux后台运行

linux命令如下:

nohup java -jar 自己的springboot项目.jar >日志文件名.log 2>&1 &

nohup java -jar ybj-0.0.1-SNAPSHOT.jar >ybj.log 2>&1 &

netstat -tlunp 
kill pid

命令解释:

nohup:不挂断地运行命令,退出帐户之后继续运行相应的进程。


java -jar 自己的springboot项目.jar:执行springboot的项目,如果单单只执行该命令,linux只会短暂的运行该项目,当退出控制台后会自动关闭该项目。


>日志文件名.log:是nohup把command的输出重定向到当前目录的指定的“日志文件名.log”文件中,即输出内容不打印到屏幕上,而是输出到”日志文件名.log”文件中。不指定文件名会在当前目录创建nohup.out,如果当前目录的 nohup.out 文件不可写,输出重定向到 $HOME/nohup.out 文件中。如果没有文件能创建或打开以用于追加,那么 Command 参数指定的命令不可调用。


2>&1:2就是标准错误,1是标准输出,该命令相当于把标准错误重定向到标准输出么。这里&相当于标准错误等效于标准输出,即把标准错误和标准输出同时输出到指定的“日志文件名.log”文件中。


最后的&:让改作业在后台运行。

spring security跨域调用>前台携带 cookie

//spring security解决跨域调用
.and().cors().and().csrf().disable();

package com.sx.ybj.config;

import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/**
 * @program: ybj
 * @description: 跨域访问
 * @author: lwx
 * @create: 2019-05-15 08:36
 */
@Configuration
@AutoConfigureBefore(HelloSecurity.class)
public class ORSConfiguration extends WebMvcConfigurerAdapter {
   // @Override
        /**
        *@Description: addMapping:配置可以被跨域的路径,可以任意配置,可以具体到直接请求路径。 
         * allowedMethods:允许所有的请求方法访问该跨域资源服务器,如:POST、GET、PUT、DELETE等。 
         * allowedOrigins:允许所有的请求域名访问我们的跨域资源,可以固定单条或者多条内容,如:”http://www.aaa.com“,只有该域名可以访问我们的跨域资源。 
         * allowedHeaders:允许所有的请求header访问,可以自定义设置任意请求头信息。
        *@Param: [registry]
        *@return: void
        *@Author: your name
        *@date: 2019/5/15
        */
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedMethods("*")
                .allowedOrigins("*")
                .allowedHeaders("*")
               .allowCredentials(true)
                .maxAge(3600);


    }

}

第九天

头像上传

为UploadController.java 新增upload用来接受上传
1. 接受上传的文件

@RequestParam("file") MultipartFile file


2. 根据时间戳创建新的文件名,这样即便是第二次上传相同名称的文件,也不会把第一次的文件覆盖了

String fileName = System.currentTimeMillis()+file.getOriginalFilename();


3. 通过req.getServletContext().getRealPath("") 获取当前项目的真实路径,然后拼接前面的文件名

String destFileName=req.getServletContext().getRealPath("")+"uploaded"+File.separator+fileName;


4. 第一次运行的时候,这个文件所在的目录往往是不存在的,这里需要创建一下目录

File destFile = new File(destFileName);
destFile.getParentFile().mkdirs();


5. 把浏览器上传的文件复制到希望的位置

file.transferTo(destFile);


6. 把文件名放在model里,以便后续显示用

m.addAttribute("fileName",fileName);
package com.sx.ybj.controller.user;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * @program: ybj
 * @description: 上传图片
 * @author: lwx
 * @create: 2019-06-04 15:37
 */
@Controller
public class UploadController {

    @RequestMapping("/uploadPage")
    public String uploadPage() {
        return "uploadPage";
    }

    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    public String upload(HttpServletRequest req, @RequestParam("file") MultipartFile file, Model m) {
        try {
            String fileName = System.currentTimeMillis()+file.getOriginalFilename();
            String destFileName=req.getServletContext().getRealPath("")+"uploaded"+ File.separator+fileName;

            File destFile = new File(destFileName);
            destFile.getParentFile().mkdirs();
            file.transferTo(destFile);

            m.addAttribute("fileName",fileName);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return "上传失败," + e.getMessage();
        } catch (IOException e) {
            e.printStackTrace();
            return "上传失败," + e.getMessage();
        }

        return "showImg";
    }
}

第十天

用户信息验证

package com.sx.ybj.service.user.Impl;

import com.sx.ybj.mapper.UserMapper;
import com.sx.ybj.pojo.User;
import com.sx.ybj.pojo.UserExample;
import com.sx.ybj.service.user.UserInfoService;
import com.sx.ybj.utils.YbjResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @program: ybj
 * @description: 用户信息
 * @author: lwx
 * @create: 2019-06-04 14:54
 */
@Service
public class UserInfoServiceImpl implements UserInfoService {
    @Autowired
    UserMapper userMapper;
    @Override
    public YbjResult checkInfo(String value, String type) throws  Exception {
        // TODO Auto-generated method stub
        boolean result = false;
        //type为类型,可选参数1、2、3分别代表username、phone、email
        if ("1".equals(type)) {
           result= checkUserName(value);
        } else if ("2".equals(type)) {
            result = checkEmil(value);
        }
        //返回结果
        if (result) {
            return YbjResult.build(1,"不存在该数值",result);
        }
        return  YbjResult.build(0, "此数值已经存在",result);
    }
//ture 为不存在
    private boolean checkUserName(String username) throws Exception {
        //创建查询条件
        UserExample example = new UserExample();
        UserExample.Criteria criteria = example.createCriteria();
        criteria.andUsernameEqualTo(username);
        List<User> list = userMapper.selectByExample(example);
        //判断结果中是否存在
        if (list == null || list.isEmpty()) {
            return true;
        }
        return false;
    }

    private boolean checkEmil(String eamil) throws Exception {
        //创建查询条件
       UserExample example = new UserExample();
        UserExample.Criteria criteria = example.createCriteria();
        criteria.andUserEmailEqualTo(eamil);
        List<User> list = userMapper.selectByExample(example);
        //判断结果中是否存在
        if (list == null || list.isEmpty()) {
            return true;
        }
        return false;
    }



}

后台管理>.>>>

第十一天

笔记上传

  @RequestMapping(value = "/uploadNote", method = RequestMethod.POST)
    public String uploadNote(HttpServletRequest req, @RequestParam("file") MultipartFile file,Model m,Notebook notebook) throws  Exception{
        String  html=null;
        String  fileName=System.currentTimeMillis()+file.getOriginalFilename();//获取源文件名称

//        String destFileName=req.getServletContext().getRealPath("")+"uploaded"+File.separator+fileName;//生成下载路径

//        String destFileName="/usr/local/tmp2"+"uploaded"+fileName;
         String destFileName="/usr/local/tmp2/"+fileName;
        File destFile = new File(destFileName);//生成文件路径
        destFile.getParentFile().mkdirs();
        file.transferTo(destFile);//生成文件


        FileInputStream fileInputStream=new FileInputStream(destFile);//文件输入流
          byte[] all =new byte[(int) destFile.length()];//文件长度
        while (fileInputStream.read(all) != -1) {
            html = new String(all);
        }
        PegDownProcessor pdp = new PegDownProcessor(Integer.MAX_VALUE);
        html = pdp.markdownToHtml(html);//生成html文件

        notebook.setNotebookTitle(file.getOriginalFilename());
        notebook.setCategorizeId(1);
        notebook.setNotebookContent(html);
        noteService.createNote(notebook);

        m.addAttribute("md",html);
        return "/home";
    }

第十二天

逆向工程遇到的问题

1、字符长度溢出

	<!--<table tableName="activity" domainObjectName="Activity"-->
			   <!--enableCountByExample="true" enableDeleteByExample="true"-->
			   <!--enableSelectByExample="true" enableUpdateByExample="true" >-->
			<!--<columnOverride column="activity_content"  jdbcType="VARCHAR"/>-->
		<!--</table>-->

2、创建笔记,返回笔记Id

<table tableName="categorize" domainObjectName="Categorize"
			   enableCountByExample="true" enableDeleteByExample="true"
			   enableSelectByExample="true" enableUpdateByExample="true" >

			<generatedKey column="categorize_id" sqlStatement="MySql" identity="true" />
		</table>

下载笔记

Springboot对资源的描述提供了相应的接口

https://www.cnblogs.com/yaowen/p/8918678.html

其主要实现类有ClassPathResource、FileSystemResource、UrlResource、ByteArrayResource、

ServletContextResource和InputStreamResource。

  1. ClassPathResource可用来获取类路径下的资源文件。假设我们有一个资源文件test.txt在类路径下,我们就可以通过给定对应资源文件在类路径下的路径path来获取它,new ClassPathResource(“test.txt”)。
  2. FileSystemResource可用来获取文件系统里面的资源。我们可以通过对应资源文件的文件路径来构建一个FileSystemResource。FileSystemResource还可以往对应的资源文件里面写内容,当然前提是当前资源文件是可写的,这可以通过其isWritable()方法来判断。FileSystemResource对外开放了对应资源文件的输出流,可以通过getOutputStream()方法获取到。
  3. UrlResource可用来代表URL对应的资源,它对URL做了一个简单的封装。通过给定一个URL地址,我们就能构建一个UrlResource。
  4. ByteArrayResource是针对于字节数组封装的资源,它的构建需要一个字节数组。
  5. ServletContextResource是针对于ServletContext封装的资源,用于访问ServletContext环境下的资源。ServletContextResource持有一个ServletContext的引用,其底层是通过ServletContext的getResource()方法和getResourceAsStream()方法来获取资源的。
  6. InputStreamResource是针对于输入流封装的资源,它的构建需要一个输入流。

Resource接口中主要定义有以下方法:

  1. exists():用于判断对应的资源是否真的存在。
  2. isReadable():用于判断对应资源的内容是否可读。需要注意的是当其结果为true的时候,其内容未必真的可读,但如果返回false,则其内容必定不可读。
  3. isOpen():用于判断当前资源是否代表一个已打开的输入流,如果结果为true,则表示当前资源的输入流不可多次读取,而且在读取以后需要对它进行关闭,以防止内存泄露。该方法主要针对于InputStreamResource,实现类中只有它的返回结果为true,其他都为false。
  4. getURL():返回当前资源对应的URL。如果当前资源不能解析为一个URL则会抛出异常。如ByteArrayResource就不能解析为一个URL。
  5. getFile():返回当前资源对应的File。如果当前资源不能以绝对路径解析为一个File则会抛出异常。如ByteArrayResource就不能解析为一个File。
  6. getInputStream():获取当前资源代表的输入流。除了InputStreamResource以外,其它Resource实现类每次调用getInputStream()方法都将返回一个全新的InputStream。
  7. 以及一些类似于Java中的File的接口,比如getName,getContenLength等等。

如果需要获取本地文件系统中的指定路径下的文件,有一下几种方式

  1. 通过ResponseEntity实现

  2. 通过写HttpServletResponse的OutputStream实现

  3. 功能实现

  4. 
        @RequestMapping("/downloadOnlineLearnMaterials")
        public String downloadFile(HttpServletRequest request, HttpServletResponse response,int notebookId) {
            //String fileName = "hehe.md";// 设置文件名,根据业务需要替换成要下载的文件名
            String fileName=notebookMapper.selectByPrimaryKey(notebookId).getNotebookUrl();//查询笔记的路径
            if (fileName != null) { //设置文件路径
    //            String realPath = "F:\\IDE";
                String realPath=fileName;
                //File file = new File(realPath, fileName); //文件
                File file=new File(realPath);
                if (file.exists()) {
                    response.setContentType("application/force-download");// 设置强制下载不打开
                    response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);// 设置文件名
                    byte[] buffer = new byte[1024];//设置缓存byte数组
                    FileInputStream fis = null;//文件输入流
                    BufferedInputStream bis = null;//缓存流
                    try {
                        fis = new FileInputStream(file);
                        bis = new BufferedInputStream(fis);//缓存输入流
                        OutputStream os = response.getOutputStream();//输出流
                        int i = bis.read(buffer);//二进制流
                        while (i != -1) {
                            os.write(buffer, 0, i);//写入
                            i = bis.read(buffer);
                        }
                        System.out.println("success");
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        if (bis != null) {
                            try {
                                bis.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                        if (fis != null) {
                            try {
                                fis.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
            return null;
        }
    

###        搜索引擎

​        1.代码高亮显示



### 配置文件如下

服务器发送邮件: 打开 25 端口

````properties
#mysql
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql://106.14.145.180/cloud_note?useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=admin
mybatis.config-location=classpath:/mybatis-config.xml
#mybatis.mapper-locations=classpath:/mapper/*.xml
server.context-path=/note
#文件上传下载
spring.http.multipart.maxFileSize=10Mb
spring.http.multipart.maxRequestSize=10Mb

server.port=8081
#安全
logging.level.org.springframework.security=info
#security.basic.enabled = false
security.user.name=sang
security.user.password=123
#热部署
spring.thymeleaf.cache=false
spring.devtools.restart.enabled=true
spring.devtools.restart.additional-paths=src/main/java
#pojo
mybatis.type-aliases-package=com.sx.ybj.pojo

#搜索引擎
spring.data.elasticsearch.cluster-name=elasticsearch
#spring.data.elasticsearch.cluster-nodes=127.0.0.1:9300
spring.data.elasticsearch.cluster-nodes=106.14.145.180:9300
#邮箱
spring.mail.username=@qq.com
spring.mail.password=yfyzznsrxttmccdg
spring.mail.host=smtp.qq.com
spring.mail.properties.mail.smtp.enable=true;
spring.mail.port=587

#redis
###########################redis#########################
#Redis数据库索引(默认为0)
spring.redis.database=0
#Redis服务器地址
spring.redis.host=106.14.145.180
#Redis服务器连接端口
spring.redis.port=6379
#Redis服务器连接密码(默认为空)
spring.redis.password=
#连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=10
#连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
#连接池中的最大空闲连接
spring.redis.pool.max-idle=8
#连接池中的最小空闲连接
spring.redis.pool.min-idle=0
#连接超时时间(毫秒)
spring.redis.timeout=0

spring.jpa.show-sql=true

第十三天

获取用户反馈信息的空指针异常

    if (userServices.getFeedBack().size()>0&&userServices.getFeedBack()!=null)
                   out.write(JsonUtils.objectToJson(YbjResult.ok(userServices.getFeedBack().get(0))));
              else
                   out.write("{\"status\":\"1\",\"msg\":\"登录成功\"}");         

spring boot Controller获取参数注解总结

总结下获取参数的注解

注解	作用
@Controller	处理http请求
@RestController	Spring4之后新加的注解,作用和原来的@ResponseBody配合@Controller相同。用于返回Json
@PathVariable	获取url中的参数

@RequestParam	获取请求参数的值

@RequestMapping	配置url映射,需要多个时可以将value写成一个集合

@GetMapping	组合注解,相当于@RequestMapping(method = RequestMethod.GET)

@PostMapping	组合注解,相当于@RequestMapping(method = RequestMethod.POST)

@PathVariable

获取url里面的参数

e.g http://localhost:8080/user/123


@RequestMapping(value = "/user/{id}" ,method = RequestMethod.GET)

    public int hi(@PathVariable("id") int id){
        return  id;

    }

@RequestParam

获取url里面?后面的参数

e.g http://locahost:8080/user?id=123

@RequestMapping(value = "/user/{id}" ,method = RequestMethod.GET)


    public int hi(@RequestParam(value="id",defaultValue=2,required=false) int id){

        return  id;

    }

里面参数很好用,defaultValue默认值,required为false时允许传过来的值为空

创建笔记时,默认笔记

  if (notebook.getCategorizeId()==null){
              CategorizeExample categorizeExample=new CategorizeExample();
              CategorizeExample.Criteria criteria=categorizeExample.createCriteria();
              criteria.andUserIdEqualTo(Util.getCurrentUser().getUserId())
                      .andCategorizeNameEqualTo("默认笔记");
              int id=categorizeMapper.selectByExample(categorizeExample).get(0).getCategorizeId();
              notebook.setCategorizeId(id);
          }

第十四天

搜索引擎配置

   <!--pom-->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
@Document(indexName = "notebook",type = "note")//文档>索引
 @Id
    private Integer notebookId;  >索引ID
 @GetMapping("/searchFeedback")
    public YbjResult serarchFeedback(String content){
        try {
            //初始化数据
            List<Feedback> feedbacks=feedbackMapper.selectByExample(null);
            for (Feedback feedback:feedbacks){
                feedbackImpl.index(feedback);
            }
            //查询数据
            return YbjResult.ok(feedbackImpl.findByFeedbackContentLike(content));
        } catch (Exception e) {
            return YbjResult.build(0,"失败",ExceptionUtil.getStackTrace(e));
        }
    }

关于redis缓存

 @Override
    @CacheEvict(allEntries=true)  //清除缓存
@CacheConfig(cacheNames="category")  //设置缓存


@Override
    @Cacheable(key="'category '+#userId")  //添加缓存

关于springsecurity

1、pom依赖

 <!--安全-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

2、java

#安全
logging.level.org.springframework.security=info  //打印安全日志
#security.basic.enabled = false//关闭安全
security.user.name=sang
security.user.password=123
package com.sx.ybj.service;

import com.sx.ybj.mapper.RolesMapper_1;
import com.sx.ybj.mapper.UserMapper;
import com.sx.ybj.pojo.Roles;
import com.sx.ybj.pojo.User;
import com.sx.ybj.pojo.UserExample;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;

@Service
@Transactional
public class UserService implements UserDetailsService {
    @Autowired
    RolesMapper_1 rolesMapper;
   @Autowired
    UserMapper userMapper;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //获得用户名
        UserExample userExample=new UserExample();
        UserExample.Criteria criteria=userExample.createCriteria();
        criteria.andUsernameEqualTo(username);
        List<User> users=userMapper.selectByExample(userExample);
        User user=users.get(0);
        if (user == null) {
            //避免返回null,这里返回一个不含有任何值的User对象,在后期的密码比对过程中一样会验证失败
            return new User();
        }
        //查询用户的角色信息,并返回存入user中
        List<Roles> roles = rolesMapper.getRolesByUid(user.getUserId());
        user.setRoles(roles);
        return user;
    }

}
//用户角色设置
pojo
 @Override
    @JsonIgnore
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<GrantedAuthority> authorities = new ArrayList<>();
        for (Roles role : roles) {
            authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getName()));
        }
        return authorities;
    }
//用户权限
 @Override
    public boolean isEnabled() {
      if (this.enabled.equals("1"))
        return true;
      else
          return  false;
    }

3、config


package com.sx.ybj.config;


import com.sx.ybj.service.UserService;
import com.sx.ybj.utils.JsonUtils;
import com.sx.ybj.utils.YbjResult;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.util.DigestUtils;


import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;


@Configuration
@EnableWebSecurity
@Order(-1)
public class HelloSecurity extends WebSecurityConfigurerAdapter {
    @Autowired
    UserService userService;
   @Autowired
   com.sx.ybj.service.user.UserService userServices;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.headers().frameOptions().disable();
        //请求权限配置
        http.authorizeRequests()
        //指定了/login不需要任何认证就可以访问,
        .antMatchers("/user/checkInfo","/user/getOneShareNote/*","/user/login","/user/reg","/index","/user/findShareNote","/user/updatePwdWL","/user/getCode","/home","/getOneShareNotes/*").permitAll()
         .antMatchers("/hello","/admin/*").hasRole("超级管理员")
        //任何请求,登录后方可访问。
        .anyRequest().authenticated()
        //登陆界面参数
//        .and().formLogin().loginPage("/login").permitAll()
                .and().formLogin().loginProcessingUrl("/user/login").permitAll().successHandler(new AuthenticationSuccessHandler() {
            //成功时候调用的方法
            @Override
            public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                httpServletResponse.setContentType("application/json;charset=utf-8");
                PrintWriter out = httpServletResponse.getWriter();
               // out.write("{\"status\":\"1\",\"msg\":\"登录成功\"}");
               if (userServices.getFeedBack().size()>0&&userServices.getFeedBack()!=null)
                   out.write(JsonUtils.objectToJson(YbjResult.ok(userServices.getFeedBack().get(0))));
              else
                   out.write("{\"status\":\"1\",\"msg\":\"登录成功\"}");
                out.flush();
                out.close();
            }
        }).failureHandler(new AuthenticationFailureHandler() {
            @Override
            public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                httpServletResponse.setContentType("application/json;charset=utf-8");
                PrintWriter out = httpServletResponse.getWriter();
                out.write("{\"status\":\"error\",\"msg\":\"登录失败\"}");
                out.flush();
                out.close();
            }
        })

                //设置注销成功后跳转页面,默认是跳转到登录页面
                .and().logout()
                //权限访问失败界面,关键,如果不定义的话会抛出异常
                .and().exceptionHandling().accessDeniedPage("/").and().cors().and().csrf().disable();


       // http.cors().configurationSource(CorsConfigurationSource());
    }

//    private CorsConfigurationSource CorsConfigurationSource() {
//        CorsConfigurationSource source =   new UrlBasedCorsConfigurationSource();
//        CorsConfiguration corsConfiguration = new CorsConfiguration();
//        corsConfiguration.addAllowedOrigin("http://localhost:8080");	//同源配置,*表示任何请求都视为同源,若需指定ip和端口可以改为如“localhost:8080”,多个以“,”分隔;
//        corsConfiguration.addAllowedHeader("*");//header,允许哪些header,本案中使用的是token,此处可将*替换为token;
//        corsConfiguration.addAllowedMethod("*");	//允许的请求方法,PSOT、GET等
//        ((UrlBasedCorsConfigurationSource) source).registerCorsConfiguration("/**",corsConfiguration); //配置允许跨域访问的url
//        return source;
//    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        System.out.println("不用测试了这里程序运行第一个进入");
        auth.userDetailsService(userService)
                .passwordEncoder(new PasswordEncoder() {
                    @Override
                    public String encode(CharSequence charSequence) {
                        return DigestUtils.md5DigestAsHex(charSequence.toString().getBytes());
                    }

                    @Override
                    public boolean matches(CharSequence charSequence, String s) {
                     
                        return s.equals(DigestUtils.md5DigestAsHex(charSequence.toString().getBytes()));//判断密码
                    }
                });
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/static/**");//静态资源处理
    }

    @Bean
    AccessDeniedHandler getAccessDeniedHandler() {
        return new AuthenticationAccessDeniedHandler();
    }

}

关于回收站

/**
 *根据笔记本ID查询笔记本下的笔记
 * @param categorizerId
 * @return
 */
1·删除笔记本

1.1 删除笔记本时笔记本有笔记不能删除

1.2 将笔记本状态变成0

2.恢复笔记本

2.恢复笔记

2.1修改笔记状态

2.2修改笔记本状态

搭建图片服务器

https://www.cnblogs.com/shuaifing/p/8268949.html

2.安装的依赖环境准备

a. 安装gcc的环境, yum install gcc-c++

第十五天

异常处理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gko1Fy7W-1587123105181)(C:\Users\刘\AppData\Roaming\Typora\typora-user-images\1560392830616.png)]

RuntimeException如果使用try和catch异常可以被捕捉。
错误Error不 能够被捕捉
运行时异常与非运行时异常的区别
Throwable 是所有 Java 程序中错误处理的父类 ,有两种子类: Error 和 Exception 。
Error :表示由 JVM 所侦测到的无法预期的错误,由于这是属于 JVM 层次的严重错误 ,导致 JVM
无法继续执行,因此,这是不可捕捉到的,无法采取任何恢复的操作,顶多只能显示错误信息。
Exception :表示可恢复的例外,这是可捕捉到的。
Java 提供了两类主要的异常 :runtime exception 和 checked exception 。 checked
异常也就是我们经常遇到的 IO 异常,以及 SQL 异常都是这种异常。 对于这种异常, JAVA 编译器强制要求我们必需对出现的这些异常进行
catch 。所以,面对这种异常不管我们是否愿意,只能自己去写一大堆 catch 块去处理可能的异常。
但是另外一种异常: runtime exception ,也称运行时异常,我们可以不处理。当出现这样的异常时,总是由虚拟机
接管。比如:我们从来没有人去处理过 NullPointerException 异常,它就是运行时异常,并且这种异常还是最常见的异常之一。
出现运行时异常后,系统会把异常一直往上层抛,一直遇到处理代码。如果没有处理块,到最上层,如果是多线程就由 Thread.run() 抛出
,如果是单线程就被 main() 抛出
。抛出之后,如果是线程,这个线程也就退出了。如果是主程序抛出的异常,那么这整个程序也就退出了。运行时异常是
Exception 的子类,也有一般异常的特点,是可以被 Catch
块处理的。只不过往往我们不对他处理罢了。也就是说,你如果不对运行时异常进行处理,那么出现运行时异常之后,要么是线程中止,要么是主程序终止。
如果不想终止,则必须扑捉所有的运行时异常,决不让这个处理线程退出。队列里面出现异常数据了,正常的处理应该是把异常数据舍弃,然后记录日志。不应该由于异常数据而影响下面对正常数据的处理。
在这个场景这样处理可能是一个比较好的应用,但并不代表在所有的场景你都应该如此。如果在其它场景,遇到了一些错误,如果退出程序比较好,这时你就可以不太理会运行时异常
,或者是通过对异常的处理显式的控制程序退出

冒泡排序

1、初始化数组

2、1 2 5 3 2 8 3 7

3、 第一糖冒泡 1 2 3 2 5 3 7 8

聚合排序

  //聚合方式
        String name =heroes
                .stream()
                .sorted((h1,h2)->h1.hp>h2.hp?-1:1)
                .skip(2)
                .map(h->h.getName())
                .findFirst()
                .get();

        System.out.println("通过聚合操作找出来的hp第三高的英雄名称是:" + name);

第十六天

关于最近笔记的日期的排序

  @Override
    public List<Notebook> getNewNote(int userId) {
       Date date1=new Date();
        NotebookExample notebookExample=new NotebookExample();
        NotebookExample.Criteria criteria= notebookExample.createCriteria();
        criteria.andUserIdEqualTo(userId).andNotebookStateEqualTo(1);
        List<Notebook> notebooks= notebookMapper.selectByExample(notebookExample);
        List<Notebook> notebooks1=new ArrayList<>();
        for (Notebook notebook:notebooks){
            long day=(date1.getTime()-notebook.getNotebookModfiy().getTime()+1000000)/(60*60*24*1000);//找出最近十天的笔记
            if (day<=10)
                notebooks1.add(notebook);
        }
        //按照修改时间排序
        List<Notebook> notebooks2=new ArrayList<>();
//        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
        notebooks1.stream().sorted((n1,n2)->(n1.getNotebookModfiy().getTime()>n2.getNotebookModfiy().getTime()?-1:1)).forEach(notebook ->notebooks2.add(notebook));
//        notebooks1.stream().forEach(notebook -> System.out.println(simpleDateFormat.format(notebook.getNotebookModfiy())));

        return notebooks2;
      }

笔记本 保存

@RequestMapping("/saveContent")
    @ResponseBody
    public YbjResult downloadFile(int notebookId) throws Exception{
        Notebook notebook = notebookMapper.selectByPrimaryKey(notebookId);
        String nbName =System.currentTimeMillis()+ notebook.getNotebookTitle()+".md" ;//获得文件名称
        String url=notebook.getNotebookUrl();//获得文件路径
        String content=notebook.getNotebookContent();//获得内容
        //删除原先的笔记
        if (url!=null){
            File file=new File(url);
            file.delete();
        }
        url="/usr/local/tmp2/upload/";//定义路径
        File file = new File(url+nbName);
        file.createNewFile(); //创建文件
        try (FileWriter fr = new FileWriter(file)) {
            // 以字符流的形式把数据写入到文件中
            char[] cs = content.toCharArray();
            fr.write(cs);  //写入文件
            //添加url
            notebook.setNotebookUrl(url+nbName);
            notebookMapper.updateByPrimaryKeySelective(notebook);
         return YbjResult.ok();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            return YbjResult.build(0,"保存失败", ExceptionUtil.getStackTrace(e));
        }

    }

第十七天

关于下载笔记本乱码

 response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode( notebook.getNotebookTitle()+".md","UTF-8")  );// 设置文件名

关于云笔记业务逻辑

一、

1、用户都能收藏自己的笔记,和共享的笔记<且不需要分类到文件夹>

2、收藏的笔记都只显示再我的收藏里面

3、共享笔记显示已经收藏的笔记

4、收藏笔记同意放到我的收藏夹文件夹里面去

5、注册用户默认创建一个收藏夹,且不能删除

二、

1、最近笔记:查询最近修改的笔记 ok

2、与我分享:查询共享笔记,且标记是否被共享,可以收藏未共享的笔记 ok

3、我的收藏:根据用户名,显示自己已经收藏的笔记 ok

4、我的笔记本:显示自己创建的笔记本 ok

5、我的笔记:显示笔记本下的笔记,和自己收藏的笔记本,并且标明状态 ok

6、收藏笔记:收藏到自己创建的文件夹下面

第十八天

路径问题

环境:springboot 1.5.2,thymeleaf

情况:在开发环境下正常,但使用jar运行时,报错Error resolving template template might not exist or might not be accessible,意思是模板页不在,但在jar里存在该模板页

1、解决方法:原因是指向模板的路径前有斜杆/,就会出错,去掉就正常了(路径前不能带斜杆,类似相对路径的写法)

网上有人说增加配置spring.thymeleaf.prefix=classpath:/templates也能解决

2、恢复笔记本空指针异常

下载笔记返回return结果

b

 @Override
    public YbjResult deleteNotebook(int categorizeId) {
        try {

            NotebookExample notebookExample=new NotebookExample();
            NotebookExample.Criteria criteria=notebookExample.createCriteria();
            criteria.andCategorizeIdEqualTo(categorizeId).andNotebookStateEqualTo(1);
            List<Notebook> notebooks=notebookMapper.selectByExample(notebookExample);
            if (!notebooks.isEmpty()){
                return YbjResult.build(0,"no","笔记本下面有笔记,删除失败 ");
            }
            Categorize categorize=categorizeMapper.selectByPrimaryKey(categorizeId);
            if (categorize.getCategorizeName().equals("默认笔记")){
                return YbjResult.build(0,"no","不能删除默认笔记");
            }

           //判断回收站是否有笔记,没有的话失败
            NotebookExample notebookExample1=new NotebookExample();
            NotebookExample.Criteria criteria2=notebookExample1.createCriteria();
            criteria2.andCategorizeIdEqualTo(categorizeId).andNotebookStateEqualTo(0);
            List<Notebook> notebooks3=notebookMapper.selectByExample(notebookExample1);
            if (notebooks3.isEmpty()){
                categorizeMapper.deleteByPrimaryKey(categorizeId);
              return YbjResult.build(1,"彻底删除成功");
            }

            categorize.setCategorizeState(0);
            return  YbjResult.ok(  categorizeMapper.updateByPrimaryKeySelective(categorize));
        } catch (Exception e) {
            return YbjResult.build(0, "异常", ExceptionUtil.getStackTrace(e));
        }
    }
   @Test
    public  void  get1() throws  Exception{
        String content=notebookMapper.selectByPrimaryKey(227).getNotebookContent();
        String  conten1 =content.replaceAll("\\&[a-zA-Z]{1,10};", "").replaceAll("<[^>]*>", "").replaceAll("[(/>)<]", "");
        System.out.println(conten1);



    }

第十九天

bug:

  1. 修改个人信息时,用户邮箱设空,导致以后不能修改密码

  2. 后台搜索反馈信息把管理员反馈信息搜索出来,或者也可以获得自己的反馈信息

  3. 管理员不能够禁用管理员

  4. 收藏之后,不能删除其他用户的笔记或者修改 ok 已修复

  5. 不能查看自己分享的笔记

  6. public static boolean isEmail(String string) { if (string == null) return false; String regEx1 = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$"; Pattern p; Matcher m; p = Pattern.compile(regEx1); m = p.matcher(string); if (m.matches()) return true; else return false; }
    --------------------- 
    作者:Danishlyy1995 
    来源:CSDN 
    原文:https://blog.csdn.net/u012934325/article/details/73558084/ 
    版权声明:本文为博主原创文章,转载请附上博文链接!
    

    GitHub的使用

项目的下载,查看和修改
第一步. 从GitHub上下载我们的项目代码。

  1. 以Hello-World项目为例,点击绿色按钮Clone or download,然后在弹出窗口中点击剪切板图标,复制仓库的URL。

  2. 在git bash中输入git clone https://github.com/feicui-android/Hello-World.git,下载项目源码。

第二步. 查看版本历史

  1. cd到项目文件夹下,使用git log能看到我们的历史提交记录。

  2. 要回到某一历史版本,可以使用git checkout commitId,看完后要回到最新代码,使用git checkout master。

第三步. 本地修改代码
你可以在我们的代码基线上任意修改,但为了下载新代码时不出现冲突,请遵循以下步骤:

  1. 下载新代码:git pull。

  2. 从master出捡出一个新的分支:git checkout -b feature。feature是分支名称,你可以随意取名,但请用英文。

  3. 在feature分支上随意修改,改完后你可以提交你的修改:git commit -m “some message”。

  4. 此时要同步代码,请先切回主分支:git checkout master,然后更新git pull。

  5. 如果想删除自己建立的分支,使用git branch -D feature,注意执行此命令后分支被强制删除,无法恢复。

————————————————
版权声明:本文为CSDN博主「n大橘为重n」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/buknow/article/details/80325986

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值