Создание REST контроллера

 
 
 
Сообщения:44
Добрый день. Я работаю на своим учебным проектом. У меня есть обычные контроллеры, но сейчас хочу переделать их в REST. К примеру, вот один из моих контроллеров:
@Controller
public class MainController {
	
	private static final Logger logger = Logger.getLogger(MainController.class);
	
	@Autowired
	private OrderService orderService;
	
	@Autowired
	private UserService userService;
	
	@RequestMapping(value = {"/", "/home"}, method = RequestMethod.GET)
	public ModelAndView ApplicationEntry() {
		ModelAndView mav = new ModelAndView("startpage");
		logger.info("Startpage loaded");
		return mav;
	}
	
	@RequestMapping(value = "/welcome", method = RequestMethod.GET)
	public ModelAndView showHomePage() {
		ModelAndView mav = new ModelAndView("me");
		logger.info("Welcome page loaded");
		return mav;
	}
	
	@ModelAttribute(name = "orderList")
	public Iterable<OrderBean> showOrders() {
		Iterable<OrderBean> orderList = orderService.findByStatusAndEmployeeId(true, 0);
		for (OrderBean order : orderList) {
			int userId = order.getUserId();
			UserBean user = userService.findUserById(userId);
			String name = user.getName();
			order.setUserName(name); 
		}
		return orderList;
	}
 }


С помощью этого контроллера на стартовую страницу выводится общий список доступных заказов. Я хочу написать rest api, чтоб можно было в дальнейшем использовать ajax(Jquery). Я понимаю, что нужно использовать ResponseEntity, но как мне запихнуть туда ModelAttribute?
Изменен:24 авг 2018 08:59
 
 
Сообщения:9775
ModelAttribute в REST API уже не нужен. Вместо него используется ResponseEntity, ResponseBody, а также HTTP headers. ResponseEntity/ResponseBody сериализуется в JSON с помощью Jackson или другого сериализатора. Ну и затем отправляется на UI.
 
 
Сообщения:44
Староверъ:
ModelAttribute в REST API уже не нужен

Но ведь у меня в ModelAttribute производятся дополнительные действия(добавление имени). Как мне тогда это прописать? В контроллере в каждом рест методе отдельно
public ResponseEntity<Iterable<OrderBean>> showOrders() {
    Iterable<OrderBean> orderList = orderService.findByStatusAndEmployeeId(true, 0);
	for (OrderBean order : orderList) {
		int userId = order.getUserId();
		UserBean user = userService.findUserById(userId);
		String name = user.getName();
		order.setUserName(name); 
    }
    return new ResponseEntity<Iterable<OrderBean>>(orderList, HttpStatus.OK);
}

или сразу вбить это в метод сервис слоя может быть, чтоб в контроллере не производить этих манипуляций? тогда в контроллере будет что-то вроде этого:
public ResponseEntity<Iterable<OrderBean>> showOrders() {
    Iterable<OrderBean> orderList = orderService.findByStatusAndEmployeeId(true, 0);
    return new ResponseEntity<Iterable<OrderBean>>(orderList, HttpStatus.OK);
}
Изменен:24 авг 2018 09:30
 
 
Сообщения:9775
Как правило создают объект который удобно трансформировать в JSON/XML - Data Transfer Object (DTO). В твоем случае это будет OrderDto. Именно такая DTO возвращается в ResponseEntity и сериализуется.

Простую конвертацию из Entity в DTO можно производить либо в самой DTO, либо в Entity: orderBean.toWebDto(). Вызывать эту конвертацию в сервисе или в контроллере - это повод для дебатов. У обоих подходов если свои плюсы и минусы. Если же конвертация сложная (приходится еще лазить в БД или другие сервисы за доп данными), то тут без вариантов - такое заполнение прийдется делать на уровне сервисов и соответственно сервисный метод будет возвращать DTO.
 
 
Сообщения:44
Староверъ:
Как правило создают объект который удобно трансформировать в JSON/XML - Data Transfer Object (DTO).

У меня OrderBean - это и есть уже сконвертированный DTO. Для Entity у меня есть отдельный класс.

А как использовать аннотацию @ResponseBody? Вернее, в каких случаях? Просто я пишу метод в контроллере, смотрю на него, и мне кажется, что эта аннотация нужна. Но хочется научиться отличать те моменты, когда ее нужно использовать, а когда нет.
 
 
Сообщения:9775
ResponseEntity дает бОльший контроль над возвращаемой информацией - можно указывать как само тело, так и хедеры. А ResponseBody позволяет задать только тело, а статус код и хедеры будут по умолчанию. Поэтому если нужен контроль над хедерами и статусом - нужно использовать ResponseEntity.
 
 
Сообщения:53
пример restController (JAX-RS)


@Path( "/employees" )
@Produces( MediaType.APPLICATION_JSON )
@Consumes( MediaType.APPLICATION_JSON )
public class EmployeApi {

    @GET
    public Response getAllEmployees() {
        EmployeeDao dao = new EmployeeDaoImpl();
        List<Employee> allEmloyees = dao.loadAllEmloyees();

        Response response = Response.ok(allEmloyees).build();
        return response;
    }
......


ajax

$(function () {
    loadAllEmployes();

    $("#saveBtn").click(function () {
        saveEmployee();
    });

});


....

function loadAllEmployes() {
    $("#table_body").empty();

    $.ajax({
        url: 'api/employees',
        method: 'get',
        dataType: 'json',
        success: function (data) {
            $.each(data, function (index, employe) {
                addEmploye(employe);
            });

            $('#table_body').find('input:radio').change(function () {
                var selectedVal = $("#table_body").find("input:radio:checked").attr("name");
                /* отправить запрос в базу данных на удаление данной записи или загрузку выбранной
                строки (в ajax запросе) и редактирование ее на странице, а затем запись в базу, обновленной
                записи.
                 по значению, которое хранится в name, в текущий момент*/
                alert(selectedVal);
            });
        }
    });
}

...

function addEmploye(employe) {
    var employeList = $("#table_list").find("tbody:last");

    var idCol = "<td>" + employe.id + "</td>";
    var emailCol = "<td>" + employe.email + "</td>";
    var passwordCol = "<td>" + employe.password + "</td>";
    var salaryCol = "<td>" + employe.salary + "</td>";

    var btn = "<input type='radio' name='myRadio_" + employe.id + "' id='myRadio_" + employe.id + "'>";

    var inputRadio = "<input class='radioClass' type='radio' name=" + employe.id + " data-flag=\"false\"/>";
    var iTag = "<i></i>";
    var labelForRadioLeft = "<label onMouseDown=\"this.firstElementChild.isChecked=this.firstElementChild.checked;\"" +
        "onClick=\"this.firstElementChild.checked=!this.firstElementChild.isChecked;\">";
    var labelForRadioRight = "</label>";
    var radio = "<td><div class='editClass'>" + labelForRadioLeft + inputRadio + iTag + labelForRadioRight +
        "</label></div></td>";

    var actionCol = "<td>" + btn + "</td>";

    var employeRow = "<tr>" + idCol + emailCol + passwordCol + salaryCol + /*actionCol*/ radio + "</tr>";

    employeList.append(employeRow);
}



html

<html>
<head>
    <meta charset="UTF-8">
    <title>JDBC Examples</title>

    <link rel="stylesheet" type="text/css" href="/resources/css/styles-table.css"/>
    <link rel="stylesheet" type="text/css" href="/resources/style/styles.css"/>
    <script src="/resources/js/jquery/jquery-3.1.1.min.js"></script>
    <script src="/resources/js/scripts/js-focus.js"></script>
    <script src="/resources/js/scripts/ajax-query.js"></script>

</head>

<body>

<h1>Список сотрудников</h1>

<div class="tableList">
    <table id="table_list">
        <tr>
            <th>ID</th>
            <th>Email</th>
            <th>Пароль</th>
            <th>Заработная плата</th>
            <th>Операции</th>
        </tr>
        <tbody id="table_body">
        </tbody>
    </table>
</div>


web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
		 version="3.1">

	<resource-ref>
		<description>This section describes link to the DataSource JNDI resource</description>
		<res-ref-name>jdbc/personnel_department_db_link</res-ref-name>
		<res-type>javax.sql.DataSource</res-type>
		<res-auth>Container</res-auth>
	</resource-ref>

	<servlet>
		<servlet-name>Jersey REST Service</servlet-name>
		<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
		<init-param>
			<param-name>jersey.config.server.provider.packages</param-name>
			<param-value>com.skillsimprover.restexamples.rest</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>Jersey REST Service</servlet-name>
		<url-pattern>/api/*</url-pattern>
	</servlet-mapping>

</web-app>


maven

<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

		<mysql.version>8.0.12</mysql.version>

		<jersey.rest.version>2.27</jersey.rest.version>

        <servlets.version>4.0.1</servlets.version>
        <jsp.version>2.3.3</jsp.version>
        <jstl.version>1.2</jstl.version>
        <commons.lang.version>3.8</commons.lang.version>
	</properties>

	<dependencies>
		<dependency>
		    <groupId>mysql</groupId>
		    <artifactId>mysql-connector-java</artifactId>
		    <version>${mysql.version}</version>
		</dependency>

		<dependency>
		    <groupId>org.glassfish.jersey.containers</groupId>
		    <artifactId>jersey-container-servlet-core</artifactId>
		    <version>${jersey.rest.version}</version>
		</dependency>
		<dependency>
		    <groupId>org.glassfish.jersey.media</groupId>
		    <artifactId>jersey-media-json-jackson</artifactId>
		    <version>${jersey.rest.version}</version>
		</dependency>
		<dependency>
			<groupId>org.glassfish.jersey.inject</groupId>
	        <artifactId>jersey-hk2</artifactId>
	        <version>2.26</version>		
		</dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>${servlets.version}</version>
            <scope>provided</scope>
        </dependency>
		<dependency>
		    <groupId>javax.servlet.jsp</groupId>
		    <artifactId>javax.servlet.jsp-api</artifactId>
		    <version>${jsp.version}</version>
		    <scope>provided</scope>
		</dependency>
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>${jstl.version}</version>
        </dependency>
		<dependency>
		    <groupId>org.apache.commons</groupId>
		    <artifactId>commons-lang3</artifactId>
		    <version>${commons.lang.version}</version>
		</dependency>
	</dependencies>
 
Модераторы:wedens
Сейчас эту тему просматривают:Нет