Spring Boot (two): web application development, implement CRUD

First, the development of web applications

Spring Boot Web development is very simple, including the commonly used json output, filters, property, log, etc.

Two, json interface development

What needs to be done previously used spring development projects, the need to provide an interface json it?

1, related to add a jar jackjson

2, the scan package arranged spring controller

3. The method of docking Add @ResponseBody

We often 406 errors due to a configuration error, since the scan package is not in place to understand the configuration error (SSM framework encountered, engage in several days to get rid of!) And so on, how springboot do it, you only need to add the class  @RestController  to the default class method format will return to json

@RestController
public class HelloController {
    @RequestMapping("/getUser")
    public User getUser() {
    	User user=new User();
    	user.setUserName("素小暖");
    	user.setPassWord("xxxx");
        return user;
    }
}

If you need to use as long as the page developers to use @Controllerannotations to, the following will be explained in conjunction with the template.

Third, custom filter

We often use the filters used to call logs in the project, rule out the threat XXS characters, execute permissions verification and so on.

springboot automatically added OrderedCharacterEncodingFilter and HiddenHttpMethodFilter, and we can customize the filter.

Two step

(1) filter implemented interface, the filter method

(2) adding annotations @Configuration, custom filter filtering chain added

@Configuration
public class WebConfiguration {
    @Bean
    public RemoteIpFilter remoteIpFilter() {
        return new RemoteIpFilter();
    }
    
    @Bean
    public FilterRegistrationBean testFilterRegistration() {

        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new MyFilter());
        registration.addUrlPatterns("/*");
        registration.addInitParameter("paramName", "paramValue");
        registration.setName("MyFilter");
        registration.setOrder(1);
        return registration;
    }
    
    public class MyFilter implements Filter {
		@Override
		public void destroy() {
			// TODO Auto-generated method stub
		}

		@Override
		public void doFilter(ServletRequest srequest, ServletResponse sresponse, FilterChain filterChain)
				throws IOException, ServletException {
			// TODO Auto-generated method stub
			HttpServletRequest request = (HttpServletRequest) srequest;
			System.out.println("this is MyFilter,url :"+request.getRequestURI());
			filterChain.doFilter(srequest, sresponse);
		}

		@Override
		public void init(FilterConfig arg0) throws ServletException {
			// TODO Auto-generated method stub
		}
    }
}

Fourth, custom property

In the process of Web development, I often need to customize some configuration files, and how to use it?

1, arranged in the application.properties

server.port=8081
#spring.profiles.active=dev

# idea\uFF0Cproperties\u914D\u7F6E\u6587\u4EF6utf-8
# \uFFFD\uFFFD\uFFFD\uFFFDperson\uFFFD\uFFFD\u05B5
person.last-name=\u5F20\u4E09${random.uuid}
person.age=${random.int}
person.birth=2017/12/15
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
person.dog.name=${person.hello:hello}_dog
person.dog.age=15

2, custom configuration class

@Component
public class NeoProperties {
	@Value("${person.last-name}")
	private String last-name;//此处last-name与lastName一样
	@Value("${person.age}")
	private int age;
    ...
	//省略getter settet方法

}

3, log configuration

Address and configure the output of the output level

logging.path=/user/local/log
logging.level.com.favorites=DEBUG
logging.level.org.springframework.web=INFO
logging.level.org.hibernate=ERROR

native path of log address, logging.level back-log can be configured according to different resources package path

Fifth, database operations

Here we will focus MySQL, using the spring data jpa. jpa hibernate generated using a variety of automated sql, if only a simple CRUD, the basic need handwriting, spring interior has a good package.

Here are some in use in springboot

1, add the relevant jar package

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
 <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

2. Add a profile

spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql= true

In fact, this role hibernate.hbm2ddl.auto parameter is mainly used for: Automatic record.

Verification database table structure has four values:

  • create: every time the load will be removed once the hibernate generated table, and then re-generate a new table based on your model type, even if; nothing has changed twice so will perform, and this is leading to the loss of a database table data important reason.
  • create-drop: loading each model class-table according to hibernate, but sessionFactory a closed table is automatically deleted.
  • update: most commonly used properties, for the first time when loading hibernate automatically creates the underlying structure of the model class, after the automatic update table structure based on model class is loaded hibernate, even before the table structure changes but does not delete rows in the table still exists line. Note that when deployed to the server, the table structure will not be immediately established, is to wait after the first application up and running before.
  • validate: Each time hibernate loaded, verified create a database table structure, and the only table in the database compares practice, does not create a new table, but will insert a new value.

dialect Mainly designated storage engine generated table name is InnoDBD
show-sql whether to print out the automatically generated SQL, convenient when debugging View

3, the entity class and add dao

@Entity
public class User implements Serializable {

	private static final long serialVersionUID = 1L;
	@Id
	@GeneratedValue
	private Long id;
	@Column(nullable = false, unique = true)
	private String userName;
	@Column(nullable = false)
	private String passWord;
	@Column(nullable = false, unique = true)
	private String email;
	@Column(nullable = true, unique = true)
	private String nickName;
	@Column(nullable = false)
	private String regTime;

	//省略getter settet方法、构造方法

}

As long dao class can inherit JpaRepository, almost can not write method, there is a particularly urinary function is very commendable, is that you can automatically generate SQL according to the method name, such as findByUserName automatically generated to a  userName query method as a parameter, such as  findAlll automatically queries all the data inside the table, such as automatic pagination, and so on. .

Entity is a field in a row should not have to add the  @Transient  notes, annotations without also mapped to columns

public interface UserRepository extends JpaRepository<User, Long> {
    User findByUserName(String userName);
    User findByUserNameOrEmail(String username, String email);
}

4, the test

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(Application.class)
public class UserRepositoryTests {

	@Autowired
	private UserRepository userRepository;

	@Test
	public void test() throws Exception {
		Date date = new Date();
		DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);        
		String formattedDate = dateFormat.format(date);
		
		userRepository.save(new User("aa1", "[email protected]", "aa", "aa123456",formattedDate));
		userRepository.save(new User("bb2", "[email protected]", "bb", "bb123456",formattedDate));
		userRepository.save(new User("cc3", "[email protected]", "cc", "cc123456",formattedDate));

		Assert.assertEquals(9, userRepository.findAll().size());
		Assert.assertEquals("bb", userRepository.findByUserNameOrEmail("bb", "[email protected]").getNickName());
		userRepository.delete(userRepository.findByUserName("aa1"));
	}

}

Six, Thymeleaf template

Spring Boot recommended Thymeleaf instead Jsp.

1, Thymeleaf Introduction

Thymeleaf is a tool for rendering XML / XHTML / HTML5 content template engine. Similar to the JSP. It can easily be integrated as a web application template engine with springMVC framework. Compared with other template engines, Thymeleaf biggest feature is the ability to open directly in the browser and displays the correct page template without the need to start the entire web application.

Thymeleaf using natural template technology, which means Thymeleaf template syntax does not destroy the structure of the document, the template is still a valid XML document. Templates can also be used as a working prototype, Thymeleaf will replace static values ​​at runtime.

URL occupies a very important position in the Web application template, special attention is Thymeleaf URL for processing by the syntax  @{...} handled. Thymeleaf absolute path URL:

<a th:href="@{http://www.thymeleaf.org}">Thymeleaf</a>

Condition evaluation

<a th:href="@{/login}" th:unless=${session.user != null}>Login</a>

 for loop

<tr th:each="prod : ${prods}">
      <td th:text="${prod.name}">Onions</td>
      <td th:text="${prod.price}">2.41</td>
      <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
</tr>

2, namely page prototypes

  In traditional Java Web development process, the front-end and back-end engineers, like engineers also need to install a complete development environment, then all kinds of Java IDE to modify the template, static resource files, start / restart / reload the application server, refresh the page see the final results.

But in fact the responsibility of the front-end engineers should focus more pages, using JSP difficult to do, because the JSP application server must be rendered to see the results after completion in the browser, and can not keep from Thymeleaf solve this problems, the template rendered by property does not introduce any new browsers do not recognize the tag, such as JSP, the tag will not write internal expression. The entire page as an HTML file directly open the browser, you can almost see the final results, which liberated the productivity front-end engineers, their final deliverable is pure HTML / CSS / JavaScript files.

Seven, Gradle build tools

spring project is recommended to use Maven / Gradle build the project, Maven terms Gradle more concise compared to more suitable and Gradle build large, complex projects. Gradle absorbed the characteristics of the ant and maven, but at the moment is still the mainstream java maven industry, first look at the thing.

A project Gradle configured to use:

buildscript {
    repositories {
        maven { url "http://repo.spring.io/libs-snapshot" }
        mavenLocal()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.6.RELEASE")
    }
}

apply plugin: 'java'  //添加 Java 插件, 表明这是一个 Java 项目
apply plugin: 'spring-boot' //添加 Spring-boot支持
apply plugin: 'war'  //添加 War 插件, 可以导出 War 包
apply plugin: 'eclipse' //添加 Eclipse 插件, 添加 Eclipse IDE 支持, Intellij Idea 为 "idea"

war {
    baseName = 'favorites'
    version =  '0.1.0'
}

sourceCompatibility = 1.7  //最低兼容版本 JDK1.7
targetCompatibility = 1.7  //目标兼容版本 JDK1.7

repositories {     //  Maven 仓库
    mavenLocal()        //使用本地仓库
    mavenCentral()      //使用中央仓库
    maven { url "http://repo.spring.io/libs-snapshot" } //使用远程仓库
}
 
dependencies {   // 各种 依赖的jar包
    compile("org.springframework.boot:spring-boot-starter-web:1.3.6.RELEASE")
    compile("org.springframework.boot:spring-boot-starter-thymeleaf:1.3.6.RELEASE")
    compile("org.springframework.boot:spring-boot-starter-data-jpa:1.3.6.RELEASE")
    compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.6'
    compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.4'
    compile("org.springframework.boot:spring-boot-devtools:1.3.6.RELEASE")
    compile("org.springframework.boot:spring-boot-starter-test:1.3.6.RELEASE")
    compile 'org.webjars.bower:bootstrap:3.3.6'
	compile 'org.webjars.bower:jquery:2.2.4'
    compile("org.webjars:vue:1.0.24")
	compile 'org.webjars.bower:vue-resource:0.7.0'

}

bootRun {
    addResources = true
}

Eight, WebJars

WebJars is a wonderful thing, so that we can be in the form of the jar package using a variety of front-end framework components.

1. What is WebJars

WebJars is to package the client resources to jar package file to rely unified management of resources. WebJars jar package deployed on the maven central repository.

2, Why

We will use Maven java web development project when, Gradle and other build tools to achieve the jar package version dependency management, and automated management of the project, but for JavaScript, css resources and other front-end package, we can only use the copy to the webapp way, to do so would not be able to rely on the management of these resources, then WebJars jar package provides resources to those of us front-end resources, we can rely on to manage.

3, How to Use

(1) add dependencies

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>vue</artifactId>
    <version>2.5.16</version>
</dependency>

(2) introduction page

<link th:href="@{/webjars/bootstrap/3.3.6/dist/css/bootstrap.css}" rel="stylesheet"></link>

Nine, CRUD

We have completed the CRUD springboot

The key code stickers, share it

1, look at the architecture project

2, the extended functionality SpringMVC

package com.springboot.config;

import com.springboot.component.LoginHandlerInterceptor;
import com.springboot.component.MyLocaleResolver;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

//使用WebMvcConfigurerAdapter可以来扩展SpringMVC的功能
//@EnableWebMvc   不要接管SpringMVC
@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
       // super.addViewControllers(registry);
        //浏览器发送 /atguigu 请求来到 success
        registry.addViewController("/atguigu").setViewName("success");
    }

    //所有的WebMvcConfigurerAdapter组件都会一起起作用
    @Bean //将组件注册在容器
    public WebMvcConfigurerAdapter webMvcConfigurerAdapter(){
        WebMvcConfigurerAdapter adapter = new WebMvcConfigurerAdapter() {
            @Override
            public void addViewControllers(ViewControllerRegistry registry) {
                registry.addViewController("/").setViewName("login");
                registry.addViewController("/index.html").setViewName("login");
                registry.addViewController("/main.html").setViewName("dashboard");
            }

            //注册拦截器
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                //super.addInterceptors(registry);
                //静态资源;  *.css , *.js
                //SpringBoot已经做好了静态资源映射
//                registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**")
//                        .excludePathPatterns("/index.html","/","/user/login");
            }
        };
        return adapter;
    }

    @Bean
    public LocaleResolver localeResolver(){

        return new MyLocaleResolver();
    }

}

3、controller

package com.springboot.controller;

import com.springboot.dao.DepartmentDao;
import com.springboot.dao.EmployeeDao;
import com.springboot.entities.Department;
import com.springboot.entities.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.Collection;

@Controller
public class EmployeeController {
    @Autowired
    EmployeeDao employeeDao;

    @Autowired
    DepartmentDao departmentDao;

    //查询所有员工返回列表页面
    @GetMapping("/emps")
    public String  list(Model model){
        Collection<Employee> employees = employeeDao.getAll();

        //放在请求域中
        model.addAttribute("emps",employees);
        // thymeleaf默认就会拼串
        // classpath:/templates/xxxx.html
        return "emp/list";
    }

    //来到员工添加页面
    @GetMapping("/emp")
    public String toAddPage(Model model){
        //来到添加页面,查出所有的部门,在页面显示
        Collection<Department> departments = departmentDao.getDepartments();
        model.addAttribute("depts",departments);
        return "emp/add";
    }

    //员工添加
    //SpringMVC自动将请求参数和入参对象的属性进行一一绑定;要求请求参数的名字和javaBean入参的对象里面的属性名是一样的
    @PostMapping("/emp")
    public String addEmp(Employee employee){
        //来到员工列表页面

        System.out.println("保存的员工信息:"+employee);
        //保存员工
        employeeDao.save(employee);
        // redirect: 表示重定向到一个地址  /代表当前项目路径
        // forward: 表示转发到一个地址
        return "redirect:/emps";
    }

    //来到修改页面,查出当前员工,在页面回显
    @GetMapping("/emp/{id}")
    public String toEditPage(@PathVariable("id") Integer id,Model model){
        Employee employee = employeeDao.get(id);
        model.addAttribute("emp",employee);

        //页面要显示所有的部门列表
        Collection<Department> departments = departmentDao.getDepartments();
        model.addAttribute("depts",departments);
        //回到修改页面(add是一个修改添加二合一的页面);
        return "emp/add";
    }

    //员工修改;需要提交员工id;
    @PutMapping("/emp")
    public String updateEmployee(Employee employee){
        System.out.println("修改的员工数据:"+employee);
        employeeDao.save(employee);
        return "redirect:/emps";
    }

    //员工删除
    @DeleteMapping("/emp/{id}")
    public String deleteEmployee(@PathVariable("id") Integer id){
        employeeDao.delete(id);
        return "redirect:/emps";
    }

}

4, the front page

To list.html example, the use Thymeleaf template engine with a special springboot

(1) introduction

xmlns:th="http://www.thymeleaf.org"

(2) critical js, css introduced

script type="text/javascript" src="asserts/js/jquery-3.2.1.slim.min.js" th:src="@{/webjars/jquery/3.3.1/jquery.js}"></script>
<script type="text/javascript" src="asserts/js/popper.min.js" th:src="@{/webjars/popper.js/1.11.1/dist/popper.js}"></script>
<script type="text/javascript" src="asserts/js/bootstrap.min.js" th:src="@{/webjars/bootstrap/4.0.0/js/bootstrap.js}"></script>

<!-- Icons -->
<script type="text/javascript" src="asserts/js/feather.min.js" th:src="@{/asserts/js/feather.min.js}"></script>

(3) form form submission

<div class="container-fluid">
  <div class="row">
	<!--引入侧边栏-->
	<div th:replace="commons/bar::#sidebar(activeUri='emps')"></div>

	<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
		<h2><a class="btn btn-sm btn-success" href="emp" th:href="@{/emp}">员工添加</a></h2>
		<div class="table-responsive">
		  <table class="table table-striped table-sm">
			<thead>
				<tr>
					<th>#</th>
					<th>lastName</th>
					<th>email</th>
					<th>gender</th>
					<th>department</th>
					<th>birth</th>
					<th>操作</th>
				</tr>
			</thead>
			<tbody>
				<tr th:each="emp:${emps}">
					<td th:text="${emp.id}"></td>
					<td>[[${emp.lastName}]]</td>
					<td th:text="${emp.email}"></td>
					<td th:text="${emp.gender}==0?'女':'男'"></td>
					<td th:text="${emp.department.departmentName}"></td>
					<td th:text="${#dates.format(emp.birth, 'yyyy-MM-dd HH:mm')}"></td>
					<td>
					  <a class="btn btn-sm btn-primary" th:href="@{/emp/}+${emp.id}">编辑</a>
					  <button th:attr="del_uri=@{/emp/}+${emp.id}" class="btn btn-sm btn-danger deleteBtn">删除</button>
					</td>
				</tr>
			</tbody>
		  </table>
		</div>
	</main>
	<form id="deleteEmpForm"  method="post">
		<input type="hidden" name="_method" value="delete"/>
	</form>
  </div>
</div>

(4) jQuery achieve

<script>
    $(".deleteBtn").click(function(){
	//删除当前员工的
	$("#deleteEmpForm").attr("action",$(this).attr("del_uri")).submit();
		return false;
    });
</script>

5, to achieve results

Su speak little warm Spring Boot

Published 110 original articles · won praise 8 · views 6917

Guess you like

Origin blog.csdn.net/guorui_java/article/details/104181423