第十三章 SpringBoot项目(总)

1.创建SpringBoot项目

1.1.设置编码

 1.4.导入已有的spring boot项目

第十三章 SpringBoot项目(总)_第1张图片

2.快速搭建Restfull风格的项目

2.1.返回字符串

@RestController
public class IndexController {
	
	@RequestMapping("/demo1")
	public Object demo1() {
		System.out.println("demo1 ran....");
		System.out.println("demo1 ran%^*^&*)*(_*(*&)(&&*()&()");
		return "hello world!";
	}
}

效果:

控制台:
第十三章 SpringBoot项目(总)_第2张图片

 2.2.返回自定义对象

@RequestMapping("/demo2/{userId}/{userName}")
	public Object demo2(@PathVariable("userId") Integer userId, @PathVariable("userName") String userName) {
		System.out.println("demo2 ran...");
		User user = new User();
		user.setUserId(userId);
		user.setUserName(userName);
		user.setUserDate(new Date());
		return user; 
	}

时间的配置,在属性文件中application.properties中

# 配置时间输出的pattern
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss   
# 配置时区
spring.jackson.time-zone=Asia/Chongqing

2.3.lombok.jar的引用

        在pom.xml文件中添加


	org.projectlombok
	lombok

去本地库,执行lombok.jar
 执行方式一:在路径哪里点一下,地址会有背景色,无需删除,直接键入cmd

第十三章 SpringBoot项目(总)_第3张图片
在DOS命令行输入:java -jar jar 包的名字,我们可输入:java -jar lombok-1.18.12.jar
按照想到扫描到你本地的开发软件,点击“Install/Update",安装成功后,点击"Quir Installer",完成安装,重启eclipse生效
生效

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Emp {
    private Integer empId;
	private String empName;
	private Date hiredate;
}

返回Map

@RequestMapping("/demo3")
	public Object demo3(@RequestParam(value="userName", defaultValue="老王") String userName) {
		Map map = new HashMap();
		List empList = new ArrayList();
		empList.add(new Emp(1001, "张三", new Date()));
		empList.add(new Emp(1002, "李四", new Date()));
		map.put("empList", empList);
		User user = new User();
		user.setUserId(11);
		user.setUserName(userName);
		// 对日期做个处理
		Calendar cal = Calendar.getInstance(); // 获得日历类
		cal.set(Calendar.YEAR, 1984);
		cal.set(Calendar.MONTH, 5);
		cal.set(Calendar.DATE, 28);
		user.setUserDate(cal.getTime());
		map.put("user", user);
		map.put("money", 888888888);
		return map;
	}

2.4.打包

        有一个要求,运行环境不能只是jre,要上到jdk
第十三章 SpringBoot项目(总)_第4张图片
打包之前需要关闭服务,打包命令:clean package,先如图方式倒灶弹窗
第十三章 SpringBoot项目(总)_第5张图片
看到如下图表示成功了
第十三章 SpringBoot项目(总)_第6张图片
测试
第十三章 SpringBoot项目(总)_第7张图片
第十三章 SpringBoot项目(总)_第8张图片

3.Properties和YML(YAML)

3.1.application属性文件优先级

        优先级高的会覆盖优先级低的,优先级高低如下
                当前目录系的一个/config子目录
                当前目录
                classpath下的/config子目录
                classpath对应的root根路径

3.2.创建的几个配置 

# 配置时间输出的pattern
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss   
# 配置时区
spring.jackson.time-zone=Asia/Chongqing

# 配置服务绑定的端口
server.port=8081

# 配置站点根目录
server.servlet.context-path=/sd1.1

3.3 配置随机值

# 32位的随机字符串
my.msg=${random.value}
# 随机整数(100以内的)
my.num=${random.int(100)}
# 随机整数(10到100之间)
my.num.range=${random.int[10,100]}

如何在后代代码访问属性文件中定义好的随机值

    @Value(value="${my.msg}")
	private String msg;
	@Value(value="${my.num}")
	private Integer num;
	@Value(value="${my.num.range}")
	private Integer range;


// 读取时:使用注解 @Value(value=”${my.msg}”)
@RequestMapping("/demo4")
public Object demo4() {
	Map map = new HashMap();
	map.put("msg", msg);
	map.put("num", num);
	map.put("range", range);
	return map;
}

另一种读取属性文件中值的方式
 

// 先做一个配置类:说明从那个属性文件中,映射哪几个值
@Configuration
@ConfigurationProperties(prefix="my")
@PropertySource(value={"classpath:/application.properties"})
@Data
public class ConfigBean {
	private Integer num;
	private String name;
	private String engname;
}



//要在XXXXAppliction这个入口类上写一个注解进行注册
@EnableConfigurationProperties(value={ConfigBean.class})
public class SpringbootDemo11Application {
}

//在使用的某个Controller类中,先注入,在使用
@RequestMapping("/demo5")
public Object demo5() throws UnsupportedEncodingException {
	System.out.println("demo5 ran...");
	Map map = new HashMap();
	map.put("name", new String(configBean.getName().getBytes("ISO-8859-1"), "utf-8"));
	map.put("engname", configBean.getEngname());
	map.put("num", configBean.getNum());
	return map;
}
	
@Autowired
private ConfigBean configBean;

4.环境配置

4.1.多环境配置的好处

        不同网络环境配置可以配置不同的参数,编译部署,提高效率和减少出错。

4.2.properties多环境配置

        配置激活选项
                spring.profiles.active=dev
        要分别添加不同网环境的properties文件
                application-dev.properties
                application-test.properties
                application-prod.properties

4.3.YML多环境配置

// 配置激活选项
spring: 
    profiles: 
        active: dev
// 在yml文件中添加三个英文状态下的短横线区分的块
---
spring: 
    profiles: dev 

4.4.两种配置方式的比较

        properties文件配置多环境,需要添加多个文件,yml配置多环境,只需要一个文件
        书写格式上:yml相对简洁、优雅、层次清晰

4.5.打包后切换环境的命令

        java -jar springboot-demo-2-2-0.01-SNAPAHOT.jar -- spring.profiles.active=prod

5.日志配置

        springboot项目也支持日志框架:logback、Java Util Logging、log4j2,默认使用logback

5.1.引用外部配置文件

5.1.1.logback配置方式

SpringBOOT会默认加载classpath:logback-spring.xml,在配置文件中记得加上一个配置日志文件的语句:如果properties文件,写法是:logging.config=classpath:logback-my.xml,如果是yml文件写法是:
logging:
        config:classpath:logback-my.xml

5.1.2.log4j2配置

        首先移除logback的依赖,然后添加log4j2的依赖
移除


			org.springframework.boot
			spring-boot-starter-web
			
			
				
					org.springframework.boot
					spring-boot-starter-logging
				
			
		

添加



	org.springframework.boot
	spring-boot-starter-log4j2

如果需要第三方依赖,参考:mvnrepository.com

5.2.比较

        性能:logback和log4j2都比log4j要好(不推荐使用log4j)
        配置方式:logback方式更加简洁
        推荐:使用logback方式,Spring Boot默认。

6.Web应用开发—模板引擎

        Spring Boot的Web应用开发,是基于Spring MVC的。

6.1.SpringBoot特性

        SpringBoot在Spring默认的基础上,自动配置添加了以下的特性:包含了ContentNegotiatingViewResolver和BeanNameViewResolver;对静态资源的支持,包括对WebJars的支持;自动注册Converter、GenericConverter、Formatter;对HttpMessageConverters的支持;自动注册MessageCodeResolver;对静态index.html的支持;对自定义的favicon的支持;对自定义的banner的支持;主动使用ConfigurableWebBindingInitializer。

6.2.模板引擎的选择

        Freemarker;Thymeleaf;Groovy;Mustache
        注意:尽量不要使用jsp
        原因:jsp只能打war报,不支持jar,需要单独部署(tomcat);内嵌的Jetty不支持jsp;Undertow不支持jsp;jsp中的自定义错误页面不能覆盖SpringBoot默认的错误页的。

7.Web应用开发—模板引擎之ThyMeleaf

7.1.引入ThyMeleaf依赖


	org.springframework.boot
	spring-boot-starter-thymeleaf

7.2.添加Thymeleaf的相关配置

spring: 
      thymeleaf:
        cache: false      # 不使用缓存
        suffix: .html     # 静态页面的后缀
        encoding: utf-8   # 页面编码
      mvc: 
        static-path-pattern: /static/**     # 配置静态资源路径

        在thymeleaf页面中要访问不同域的数据,写法如下:
 

// 后台代码封装数据:
	model.addAttribute(“name1”, “val1”);
	session.setAttribute(“name2”, “val2”);
application.setAttribute(“name2”, “val2”);
// 前台代码获取数据
	${“name1”}        	//  能够获得 val1
	${“name2”}			//  什么也获得不到,因为域不对
	${“session.name2”}	//  能够获得val2
${“application.name3”} 	// 能够获得val3

8.Web应用开发—模板引擎之FreeMarker

8.1.引入FreeMarker的依赖


	org.springframework.boot
	spring-boot-starter-freemarker

8.2.在配置文件中加入freemarker的相关配置

spring:
	freemarker:                                     # 配置freemarker的相关信息
      suffix: .ftl                                  # 配置模板后缀
    	  template-loader-path: classpath:/templates/   # 设置ftl文件路径
      cache: false                                  # 设置页面不缓存
      content-type: text/html                       # 设置文档类型
      charset: utf-8                                # 设置页面编码格式 
      request-context-attribute: rc                 # 设置站点根目录属性 这样设置以后,如果ftl页面要获取站点根目录,可以使用${rc.contextPaht}

9.Web应用开发—JSP

9.1.使用模板引擎jsp的依赖



	org.apache.tomcat.embed
	tomcat-embed-jasper


	javax.servlet
	jstl

		

9.2.添加配置参数

spring:
	  mvc: 
        view: 
          prefix: /WEB-INF/templates/
          suffix: .jsp

9.3.入口类改写

@SpringBootApplication
public class SpringbootDemo33Application extends SpringBootServletInitializer{

	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
		return application.sources(SpringbootDemo33Application.class);
	}
	
	public static void main(String[] args) {
		SpringApplication.run(SpringbootDemo33Application.class, args);
	}

}

9.4.项目结构 ​​​
第十三章 SpringBoot项目(总)_第9张图片

 9.5.jsp页面编写


	
	Insert title here
	
	
	
	
	


	测试
去百度 去新浪

${测试用 }

10.Web应用开发—错误处理

10.1.错误处理方式一

        SpringBoot会将所用的错误默认映射到/error。所以,我们可以自定义一个错误处理的Controller,让他实现ErrorController并配置他的访问路径是/error即可
 

@Controller
@RequestMapping("/error")
public class BaseErrorController implements ErrorController {

	private static final Logger LOG = LoggerFactory.getLogger(BaseErrorController.class);
	
	@Override
	public String getErrorPath() {
		LOG.info("出错了!进入自定义错误控制器。");
		return "error/error";
	}
	
	@RequestMapping()
	public String error() {
        return getErrorPath();
	}

}

        错误页的层级
第十三章 SpringBoot项目(总)_第10张图片

 10.2.错误处理方式二—添加自定义的错误页面

        html静态页面:在resources/public/error/下定义一个404.html页面
        模板引擎页面:在templates/error下定义一个5xx.html页面

10.3.错误处理方式三

        定义一个处理错误的Handler类,使用注解@ControllerAdvice

@ControllerAdvice
public class MyErrorHandler {
	
	private static final Logger LOG = LoggerFactory.getLogger(MyErrorHandler.class);
	
	@ExceptionHandler({RuntimeException.class})
	@ResponseStatus(HttpStatus.OK)
	public ModelAndView processException(RuntimeException e) {
		LOG.info("自定义异常处理-RuntimeException!");
		ModelAndView mav = new ModelAndView();
		mav.addObject("myException", e.getMessage());
		mav.setViewName("error/500");
		return mav;
	}
	
	@ExceptionHandler({Exception.class})
@ResponseStatus(HttpStatus.OK)
	public String processException(Model model, Exception e) {
		LOG.info("统一异常处理-Exception!");
		model.addAttribute("myException", e.getMessage());
		return "error/500";
	}
	
}

错误处理页在项目中的层级:
第十三章 SpringBoot项目(总)_第11张图片

 错误处理页的内容(带上后台抛过来的信息)
我是错误页-错误信息是:<font size="20px" th:text="${myException}">font>

11.Web应用开发Servlert、Filter、Listener

        Web开发中,我们使用Controller基本上可以完成大部分需求,三实我们还可能会用到Servlet、Filter、Listener

11.1SpringBoot中的三种实现方式

        方式一:通过注册。ServletRegistrationBean、FiterRegistrationBean、ServletListenerRegistrationBean来获取控制。
        Servlet的使用

public class AServlet extends HttpServlet{

	private static final long serialVersionUID = 1L;
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("a servlet get method ran...");
		doPost(req, resp);
}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("a servlet post method ran...");
		resp.getWriter().print("hello world, I'm servlet A.");
	}
	
}

// 在程序启动类中注册Aservlet
@Bean
public ServletRegistrationBean aServletRegistrationBean() {
	return new ServletRegistrationBean(new AServlet(), "/a");
}

         Filter的使用

public class MyFilter implements Filter {

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("放行!"); 
		chain.doFilter(request, response);
	}

}


// 在入口类中注册
@Bean
public FilterRegistrationBean myFilterRegistrationBean() {
	return new FilterRegistrationBean(
        new MyFilter(),aServletRegistrationBean()
    );
}

Listener

public class MyListener implements ServletContextListener {
	
	@Override
	public void contextInitialized(ServletContextEvent sce) {
		System.out.println("应用初始化。。。");
	}
	
	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		System.out.println("应用销毁。");
	}
	
}

//注册:
@Bean
public ServletListenerRegistrationBean myServletListenerRegistrationBean(){
	return new ServletListenerRegistrationBean(new MyListener());
}

        方式二:(推荐)在入口类上添加一个注解@ServletComponentScan后,直接扫描带有@WebServlet、@WebFilter、@WebListener注解的组件镜像注册

//在入口类上添加注解
@SpringBootApplication
@ServletComponentScan
public class SpringbootDemo31Application{

	public static void main(String[] args) {
		SpringApplication.run(SpringbootDemo31Application.class, args);
	}

}

//在各个组件上添加注解等待扫描
@WebServlet(urlPatterns = "/a", name="aServlet")
public class AServlet extends HttpServlet{

@WebServlet(urlPatterns = "/b", name = "bServlet")
public class BServlet extends HttpServlet{

@WebFilter(urlPatterns = {"/*"})
public class MyFilter implements Filter {

@WebListener
public class MyListener implements ServletContextListener {

        方式三:让入口类实现ServletContextInitializer接口的方式镜像注册

public class SpringbootDemo31Application implements ServletContextInitializer{

	public static void main(String[] args) {
		SpringApplication.run(SpringbootDemo31Application.class, args);
	}

	@Override
	public void onStartup(ServletContext sc) throws ServletException {
		sc.addServlet("aServlet", new AServlet()).addMapping("/a");
		sc.addServlet("bServlet", new BServlet()).addMapping("/b");
		sc.addFilter("myFilter", new MyFilter()).addMappingForServletNames(
				EnumSet.of(DispatcherType.REQUEST), true, new String[] {"aServlet", "bServlet"});
		sc.addListener(new MyListener());
	}
	
}

12.SpringBoot中的文件上传

12.1.SpringBoot默认使用SpringMVC包装好的解析器进行上传

12.2.表单代码

文件:

12.3.Controller代码

@RestController
@RequestMapping("/file")
@RestController
@RequestMapping("/file")
public class FileController {

	private static final Logger LOG = LoggerFactory.getLogger(FileController.class);
	
	@RequestMapping("upload")
	public String upload(@RequestParam("myFile") MultipartFile file) {
		if(file.isEmpty()) {
			return "未选择文件!";
		}
		// 获取文件名
		String fileName = file.getOriginalFilename();
		LOG.info("获取到前台传来的文件名是:" + fileName);
		// 获取文件的后缀名
		String suffixName = fileName.substring(fileName.lastIndexOf("."));
		LOG.info("上传文件的后缀名是:" + suffixName);
		// 指定文件上传路径
		String filePath = "D://tmp/";
		// 使用随机字符作为文件名称
		String newFileName = UUID.randomUUID().toString().replace("-", "");
		String fullFileName = filePath + newFileName + suffixName;
		LOG.info("上传文件路径全名称是:" + fullFileName);
		File dest = new File(fullFileName);
		// 检测是否存在父级目录
		if(!dest.getParentFile().exists()) {
			dest.getParentFile().mkdirs();
		}
		// 文件上传
		try {
			file.transferTo(dest);
			return "上传成功!";
		} catch(Exception e) {
			e.printStackTrace();
			System.err.println(e.getMessage());
			return "上传失败!";
		}
	}
	
}

13.SpringBoot整合MyBatis

13.1.依赖


	
		
			org.springframework.boot
			spring-boot-starter-thymeleaf
		
		
		
			org.springframework.boot
			spring-boot-starter-web
		
		
		
			org.mybatis.spring.boot
			mybatis-spring-boot-starter
			2.1.2
		

		
			org.springframework.boot
			spring-boot-devtools
			runtime
			true
		
		
		
			mysql
			mysql-connector-java
			runtime
		
		
		
			org.projectlombok
			lombok
			true
		
		
		
			org.springframework.boot
			spring-boot-starter-test
			test
			
				
					org.junit.vintage
					junit-vintage-engine
				
			
		
		
		
		    org.webjars.bower
		    jquery
		    3.2.1
		
		
		
		    org.webjars
		    bootstrap
		    4.3.1
		
		
	

13.2.配置

spring:
  datasource:   # mysql数据库的配置信息
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost/mypro?&useSSL=false&serverTimezone=Asia/Chongqing&characterEncoding=utf8
    username: root
password: 123456

mybatis: # 配置XXXXMapper.xml文件的路径
  mapper-locations: classpath:mybatis/**/*.xml 
//日志文件中加上一句配置:

13.3.项目结构

第十三章 SpringBoot项目(总)_第12张图片

13. 4.数据库表设计&实体类设计

第十三章 SpringBoot项目(总)_第13张图片

实体类代码如下:

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User {
//	user_id	int
	private Integer userId;
//	user_name	varchar
	private String userName;
//	user_create_time	timestamp
	private Date userCreateTime;
}

13.5.Mapper接口的编写

13.5.1.注解处理方式

        这种方式就不用在写XXXMapper.xml文件

@Mapper
public interface UserMapper {
	
	/**
	 * 新添用户
	 * @param user 
	 */
	@Insert(value = "insert into user(user_name, user_create_time) "
				  + "values(#{userName, jdbcType=VARCHAR}, #{userCreateTime, jdbcType=TIMESTAMP})")
	void insert(User user);
	
	/**
	 * 根据id删除指定用户
	 * @param userId
	 */
	@Delete(value = "delete from user where user_id = #{userId, jdbcType=INTEGER}")
	void deleteById(Integer userId);
	
	/**
	 * 修改指定用户信息
	 * @param user
	 */
	@Update(value = "update user set user_name = #{userName, jdbcType=VARCHAR}, "
				  + "user_create_time = #{userCreateTime, jdbcType=TIMESTAMP} "
				  + "where user_id = #{userId, jdbcType=INTEGER}")
	void update(User user);
	
	/**
	 * 根据用户id查找用户
	 * @param userId
	 * @return
	 */
	@Select(value = "select * from user where user_id = #{userId, jdbcType=INTEGER}")
	@Results(value = {
			@Result(column="user_id", property="userId", jdbcType=JdbcType.INTEGER),
			@Result(column="user_name", property="userName", jdbcType=JdbcType.VARCHAR),
			@Result(column="user_create_time", property="userCreateTime", jdbcType=JdbcType.TIMESTAMP)
	})
	User selectById(Integer userId);
	
	/**
	 * 查全部
	 * @return
	 */
	@Select(value = "select * from user")
	@Results(value = {
			@Result(column="user_id", property="userId", jdbcType=JdbcType.INTEGER),
			@Result(column="user_name", property="userName", jdbcType=JdbcType.VARCHAR),
			@Result(column="user_create_time", property="userCreateTime", jdbcType=JdbcType.TIMESTAMP)
	})
	List selectAll();
}
测试:
@Autowired
	private UserMapper userMapper;
	
	@Test
	public void userMapperInsert() {
		User user = new User(2, "张三", new Date());
		userMapper.insert(user);
	}
	
	@Test
	public void userMapperSelectById() {
		User user = userMapper.selectById(3);
		System.out.println(user);
	}
	
	@Test
	public void userMapperUpdate() {
		User user = new User(4, "老王", new Date());
		userMapper.update(user);
	}
	
	@Test
	public void userMapperDelete() {
		userMapper.deleteById(4);
	}
	
	@Test
	public void userMapperSelectAll() {
		List userList = userMapper.selectAll();
		for (User user : userList) {
			System.out.println(user);
		}
	}

13.5.2..xml的处理方式

 


	
	
		
		
	
	
	
		goods_type_id, goods_type_name
	
	
	
	
		insert into goods_type(goods_type_name) values (#{goodsTypeName})
	
	
	
	
	
	
	

13.6.mybatis-generator

13.6.1.在pom.xml文件中加上一段插件配置的代码


			
			    org.mybatis.generator
			    mybatis-generator-maven-plugin
			    
			        src/main/resources/generator/generatorConfig.xml
			        true
			        true
			    
			

13.6.2.创建逆向生成用的配置文件generatorConfig.xml




    
    
    
        
            
            
            
        
        
        

        
        
            
        
        
        
            
            
        
        
        
            
        
        
        
            
        
        
			
        	

13.6.3.时区设置

第十三章 SpringBoot项目(总)_第14张图片

13.6.4.你想生成用的命令mybatis-generator:generate

 第十三章 SpringBoot项目(总)_第15张图片

 13.7.分页插件PageHelper的使用

依赖


    com.github.pagehelper
    pagehelper-spring-boot-starter
	1.2.10

使用

    @Test
	public void userMapperSelcetByPage() {
		// 要查询第3页的2条数据
		PageHelper.startPage(3, 2);
		List userList = userMapper.selectAll();
		PageInfo pageInfo = new PageInfo<>(userList);
		for (User user : pageInfo.getList()) {
			System.out.println(user);
		}
		System.out.println(pageInfo.getSize());
		System.out.println(pageInfo.getPrePage());
		System.out.println(pageInfo.getNextPage());
		System.out.println(pageInfo.getPages());
		System.out.println(pageInfo.getTotal());
	}

13.8.业务层

public interface UserService {
	
	List findAll();
	
	void add(User user);
}
@Service
public class UserServiceImpl implements UserService {

	@Autowired
	private UserMapper userMapper;
	
	@Override
	@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
	public List findAll() {
		try {
			return userMapper.selectAll();
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
	public void add(User user) {
		try {
			userMapper.insert(user);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	
}

13.9.Controller层

@Controller
@RequestMapping("/user")
public class UserController {
	
	@Autowired
	private UserService userService;
	
	@RequestMapping("showAll")
	public String showAll(Model model) {
		List userList = userService.findAll();
		model.addAttribute("userList", userList);
		return "user/showAll";
	}
	
}

13.10.View层




	
	用户信息展示页
	
	
	


	
序号 Id 姓名 日期

你可能感兴趣的:(springboot,spring,boot,java,后端)